Compare commits

..

5 Commits

Author SHA1 Message Date
8a4bc72b34 Release 4.0.8 2022-01-25 23:33:20 +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
aaf7a88de7 HayBale: fixed fall damage 2022-01-22 21:26:44 +00:00
67a0ae0246 Fixed incorrect drops for ender chest (#4751) 2022-01-22 14:01:56 +00:00
273 changed files with 1270 additions and 2433 deletions

View File

@ -43,7 +43,6 @@ return (new PhpCsFixer\Config)
'import_classes' => null,
],
'indentation_type' => true,
'logical_operators' => true,
'native_function_invocation' => [
'scope' => 'namespaced',
'include' => ['@all'],

View File

@ -40,4 +40,4 @@ echo json_encode([
"details_url" => "https://github.com/$argv[3]/releases/tag/$argv[2]",
"download_url" => "https://github.com/$argv[3]/releases/download/$argv[2]/PocketMine-MP.phar",
"source_url" => "https://github.com/$argv[3]/tree/$argv[2]",
], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_THROW_ON_ERROR) . "\n";
], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) . "\n";

View File

@ -58,7 +58,7 @@ function generateMethodAnnotations(string $namespaceName, array $members) : stri
$memberLines = [];
foreach($members as $name => $member){
$reflect = new \ReflectionClass($member);
while($reflect !== false && $reflect->isAnonymous()){
while($reflect !== false and $reflect->isAnonymous()){
$reflect = $reflect->getParentClass();
}
if($reflect === false){

View File

@ -50,7 +50,7 @@ use const STR_PAD_LEFT;
require_once dirname(__DIR__) . '/vendor/autoload.php';
function replaceVersion(string $versionInfoPath, string $newVersion, bool $isDev, string $channel) : void{
$versionInfo = Utils::assumeNotFalse(file_get_contents($versionInfoPath), $versionInfoPath . " should always exist");
$versionInfo = file_get_contents($versionInfoPath);
$versionInfo = preg_replace(
$pattern = '/^([\t ]*public )?const BASE_VERSION = "(\d+)\.(\d+)\.(\d+)(?:-(.*))?";$/m',
'$1const BASE_VERSION = "' . $newVersion . '";',

View File

@ -1620,3 +1620,10 @@ 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.

View File

@ -1,117 +0,0 @@
**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.

View File

@ -35,12 +35,12 @@
"fgrosse/phpasn1": "^2.3",
"netresearch/jsonmapper": "^4.0",
"pocketmine/bedrock-data": "~1.5.0+bedrock-1.18.0",
"pocketmine/bedrock-protocol": "~7.3.0+bedrock-1.18.0",
"pocketmine/bedrock-protocol": "~7.1.0+bedrock-1.18.0",
"pocketmine/binaryutils": "^0.2.1",
"pocketmine/callback-validator": "^1.0.2",
"pocketmine/classloader": "^0.2.0",
"pocketmine/color": "^0.2.0",
"pocketmine/errorhandler": "^0.6.0",
"pocketmine/errorhandler": "^0.3.0",
"pocketmine/locale-data": "~2.3.0",
"pocketmine/log": "^0.4.0",
"pocketmine/log-pthreads": "^0.4.0",

47
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": "055bec16a9bbc839f4410d09b09f2703",
"packages": [
{
"name": "adhocore/json-comment",
@ -275,16 +275,16 @@
},
{
"name": "pocketmine/bedrock-protocol",
"version": "7.3.0+bedrock-1.18.0",
"version": "7.1.0+bedrock-1.18.0",
"source": {
"type": "git",
"url": "https://github.com/pmmp/BedrockProtocol.git",
"reference": "418b4dbaa6720b6c6c4385a4d321d9c0b3dbf14b"
"reference": "42f2a00634c17c346fd98c05b2daf29d1fbf5805"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/418b4dbaa6720b6c6c4385a4d321d9c0b3dbf14b",
"reference": "418b4dbaa6720b6c6c4385a4d321d9c0b3dbf14b",
"url": "https://api.github.com/repos/pmmp/BedrockProtocol/zipball/42f2a00634c17c346fd98c05b2daf29d1fbf5805",
"reference": "42f2a00634c17c346fd98c05b2daf29d1fbf5805",
"shasum": ""
},
"require": {
@ -298,7 +298,7 @@
"ramsey/uuid": "^4.1"
},
"require-dev": {
"phpstan/phpstan": "1.3.1",
"phpstan/phpstan": "1.2.0",
"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.1.0+bedrock-1.18.0"
},
"time": "2022-01-06T20:44:27+00:00"
"time": "2021-12-15T03:07:05+00:00"
},
{
"name": "pocketmine/binaryutils",
@ -497,25 +497,24 @@
},
{
"name": "pocketmine/errorhandler",
"version": "0.6.0",
"version": "0.3.0",
"source": {
"type": "git",
"url": "https://github.com/pmmp/ErrorHandler.git",
"reference": "dae214a04348b911e8219ebf125ff1c5589cc878"
"reference": "ec742b209e8056bbe855069c4eff94c9734ea19b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pmmp/ErrorHandler/zipball/dae214a04348b911e8219ebf125ff1c5589cc878",
"reference": "dae214a04348b911e8219ebf125ff1c5589cc878",
"url": "https://api.github.com/repos/pmmp/ErrorHandler/zipball/ec742b209e8056bbe855069c4eff94c9734ea19b",
"reference": "ec742b209e8056bbe855069c4eff94c9734ea19b",
"shasum": ""
},
"require": {
"php": "^8.0"
"php": "^7.2 || ^8.0"
},
"require-dev": {
"phpstan/phpstan": "0.12.99",
"phpstan/phpstan-strict-rules": "^0.12.2",
"phpunit/phpunit": "^9.5"
"phpstan/phpstan": "0.12.75",
"phpstan/phpstan-strict-rules": "^0.12.2"
},
"type": "library",
"autoload": {
@ -530,9 +529,9 @@
"description": "Utilities to handle nasty PHP E_* errors in a usable way",
"support": {
"issues": "https://github.com/pmmp/ErrorHandler/issues",
"source": "https://github.com/pmmp/ErrorHandler/tree/0.6.0"
"source": "https://github.com/pmmp/ErrorHandler/tree/0.3.0"
},
"time": "2022-01-08T21:05:46+00:00"
"time": "2021-02-12T18:56:22+00:00"
},
{
"name": "pocketmine/locale-data",
@ -2389,16 +2388,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 +2475,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 +2487,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

@ -128,9 +128,7 @@ chunk-ticking:
blocks-per-subchunk-per-tick: 3
#IDs of blocks not to perform random ticking on.
disable-block-ticking:
#- grass
#- ice
#- fire
#- 2 # grass
chunk-generation:
#Max. amount of chunks in the waiting queue to be populated

View File

@ -28,6 +28,7 @@ use pocketmine\network\mcpe\cache\ChunkCache;
use pocketmine\scheduler\DumpWorkerMemoryTask;
use pocketmine\scheduler\GarbageCollectionTask;
use pocketmine\timings\Timings;
use pocketmine\utils\AssumptionFailedError;
use pocketmine\utils\Process;
use pocketmine\utils\Utils;
use Webmozart\PathUtil\Path;
@ -64,7 +65,6 @@ use function sprintf;
use function strlen;
use function substr;
use const JSON_PRETTY_PRINT;
use const JSON_THROW_ON_ERROR;
use const JSON_UNESCAPED_SLASHES;
use const SORT_NUMERIC;
@ -168,14 +168,14 @@ class MemoryManager{
}
public function canUseChunkCache() : bool{
return !$this->lowMemory || !$this->lowMemDisableChunkCache;
return !$this->lowMemory or !$this->lowMemDisableChunkCache;
}
/**
* Returns the allowed chunk radius based on the current memory usage.
*/
public function getViewDistance(int $distance) : int{
return ($this->lowMemory && $this->lowMemChunkRadiusOverride > 0) ? min($this->lowMemChunkRadiusOverride, $distance) : $distance;
return ($this->lowMemory and $this->lowMemChunkRadiusOverride > 0) ? min($this->lowMemChunkRadiusOverride, $distance) : $distance;
}
/**
@ -214,18 +214,18 @@ class MemoryManager{
public function check() : void{
Timings::$memoryManager->startTiming();
if(($this->memoryLimit > 0 || $this->globalMemoryLimit > 0) && ++$this->checkTicker >= $this->checkRate){
if(($this->memoryLimit > 0 or $this->globalMemoryLimit > 0) and ++$this->checkTicker >= $this->checkRate){
$this->checkTicker = 0;
$memory = Process::getAdvancedMemoryUsage();
$trigger = false;
if($this->memoryLimit > 0 && $memory[0] > $this->memoryLimit){
if($this->memoryLimit > 0 and $memory[0] > $this->memoryLimit){
$trigger = 0;
}elseif($this->globalMemoryLimit > 0 && $memory[1] > $this->globalMemoryLimit){
}elseif($this->globalMemoryLimit > 0 and $memory[1] > $this->globalMemoryLimit){
$trigger = 1;
}
if($trigger !== false){
if($this->lowMemory && $this->continuousTrigger){
if($this->lowMemory and $this->continuousTrigger){
if(++$this->continuousTriggerTicker >= $this->continuousTriggerRate){
$this->continuousTriggerTicker = 0;
$this->trigger($memory[$trigger], $this->memoryLimit, $trigger > 0, ++$this->continuousTriggerCount);
@ -240,7 +240,7 @@ class MemoryManager{
}
}
if($this->garbageCollectionPeriod > 0 && ++$this->garbageCollectionTicker >= $this->garbageCollectionPeriod){
if($this->garbageCollectionPeriod > 0 and ++$this->garbageCollectionTicker >= $this->garbageCollectionPeriod){
$this->garbageCollectionTicker = 0;
$this->triggerGarbageCollector();
}
@ -291,7 +291,8 @@ class MemoryManager{
* @param mixed $startingObject
*/
public static function dumpMemory($startingObject, string $outputFolder, int $maxNesting, int $maxStringSize, \Logger $logger) : void{
$hardLimit = Utils::assumeNotFalse(ini_get('memory_limit'), "memory_limit INI directive should always exist");
$hardLimit = ini_get('memory_limit');
if($hardLimit === false) throw new AssumptionFailedError("memory_limit INI directive should always exist");
ini_set('memory_limit', '-1');
gc_disable();
@ -299,7 +300,7 @@ class MemoryManager{
mkdir($outputFolder, 0777, true);
}
$obData = Utils::assumeNotFalse(fopen(Path::join($outputFolder, "objects.js"), "wb+"));
$obData = fopen(Path::join($outputFolder, "objects.js"), "wb+");
$objects = [];
@ -317,7 +318,7 @@ class MemoryManager{
$reflection = new \ReflectionClass($className);
$staticProperties[$className] = [];
foreach($reflection->getProperties() as $property){
if(!$property->isStatic() || $property->getDeclaringClass()->getName() !== $className){
if(!$property->isStatic() or $property->getDeclaringClass()->getName() !== $className){
continue;
}
@ -351,7 +352,7 @@ class MemoryManager{
}
}
file_put_contents(Path::join($outputFolder, "staticProperties.js"), json_encode($staticProperties, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR));
file_put_contents(Path::join($outputFolder, "staticProperties.js"), json_encode($staticProperties, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
$logger->info("Wrote $staticCount static properties");
$globalVariables = [];
@ -378,7 +379,7 @@ class MemoryManager{
$globalVariables[$varName] = self::continueDump($value, $objects, $refCounts, 0, $maxNesting, $maxStringSize);
}
file_put_contents(Path::join($outputFolder, "globalVariables.js"), json_encode($globalVariables, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR));
file_put_contents(Path::join($outputFolder, "globalVariables.js"), json_encode($globalVariables, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
$logger->info("Wrote $globalCount global variables");
foreach(get_defined_functions()["user"] as $function){
@ -393,7 +394,7 @@ class MemoryManager{
$functionStaticVarsCount += count($vars);
}
}
file_put_contents(Path::join($outputFolder, 'functionStaticVars.js'), json_encode($functionStaticVars, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR));
file_put_contents(Path::join($outputFolder, 'functionStaticVars.js'), json_encode($functionStaticVars, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
$logger->info("Wrote $functionStaticVarsCount function static variables");
$data = self::continueDump($startingObject, $objects, $refCounts, 0, $maxNesting, $maxStringSize);
@ -459,7 +460,7 @@ class MemoryManager{
}
}
fwrite($obData, json_encode($info, JSON_UNESCAPED_SLASHES | JSON_THROW_ON_ERROR) . "\n");
fwrite($obData, json_encode($info, JSON_UNESCAPED_SLASHES) . "\n");
}
}while($continue);
@ -468,11 +469,11 @@ class MemoryManager{
fclose($obData);
file_put_contents(Path::join($outputFolder, "serverEntry.js"), json_encode($data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR));
file_put_contents(Path::join($outputFolder, "referenceCounts.js"), json_encode($refCounts, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR));
file_put_contents(Path::join($outputFolder, "serverEntry.js"), json_encode($data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
file_put_contents(Path::join($outputFolder, "referenceCounts.js"), json_encode($refCounts, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
arsort($instanceCounts, SORT_NUMERIC);
file_put_contents(Path::join($outputFolder, "instanceCounts.js"), json_encode($instanceCounts, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR));
file_put_contents(Path::join($outputFolder, "instanceCounts.js"), json_encode($instanceCounts, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
$logger->info("Finished!");

View File

@ -32,16 +32,14 @@ namespace pocketmine {
use pocketmine\utils\ServerKiller;
use pocketmine\utils\Terminal;
use pocketmine\utils\Timezone;
use pocketmine\utils\Utils;
use pocketmine\wizard\SetupWizard;
use Webmozart\PathUtil\Path;
use function defined;
use function extension_loaded;
use function getcwd;
use function phpversion;
use function preg_match;
use function preg_quote;
use function realpath;
use function strpos;
use function version_compare;
require_once __DIR__ . '/VersionInfo.php';
@ -114,7 +112,8 @@ namespace pocketmine {
}
}
if(($pthreads_version = phpversion("pthreads")) !== false){
if(extension_loaded("pthreads")){
$pthreads_version = phpversion("pthreads");
if(substr_count($pthreads_version, ".") < 2){
$pthreads_version = "0.$pthreads_version";
}
@ -123,7 +122,8 @@ namespace pocketmine {
}
}
if(($leveldb_version = phpversion("leveldb")) !== false){
if(extension_loaded("leveldb")){
$leveldb_version = phpversion("leveldb");
if(version_compare($leveldb_version, "0.2.1") < 0){
$messages[] = "php-leveldb >= 0.2.1 is required, while you have $leveldb_version.";
}
@ -253,9 +253,8 @@ JIT_WARNING
$opts = getopt("", ["data:", "plugins:", "no-wizard", "enable-ansi", "disable-ansi"]);
$cwd = Utils::assumeNotFalse(realpath(Utils::assumeNotFalse(getcwd())));
$dataPath = isset($opts["data"]) ? $opts["data"] . DIRECTORY_SEPARATOR : $cwd . DIRECTORY_SEPARATOR;
$pluginPath = isset($opts["plugins"]) ? $opts["plugins"] . DIRECTORY_SEPARATOR : $cwd . DIRECTORY_SEPARATOR . "plugins" . DIRECTORY_SEPARATOR;
$dataPath = isset($opts["data"]) ? $opts["data"] . DIRECTORY_SEPARATOR : realpath(getcwd()) . DIRECTORY_SEPARATOR;
$pluginPath = isset($opts["plugins"]) ? $opts["plugins"] . DIRECTORY_SEPARATOR : realpath(getcwd()) . DIRECTORY_SEPARATOR . "plugins" . DIRECTORY_SEPARATOR;
Filesystem::addCleanedPath($pluginPath, Filesystem::CLEAN_PATH_PLUGINS_PREFIX);
if(!file_exists($dataPath)){
@ -287,7 +286,7 @@ JIT_WARNING
$exitCode = 0;
do{
if(!file_exists(Path::join($dataPath, "server.properties")) && !isset($opts["no-wizard"])){
if(!file_exists(Path::join($dataPath, "server.properties")) and !isset($opts["no-wizard"])){
$installer = new SetupWizard($dataPath);
if(!$installer->run()){
$exitCode = -1;

View File

@ -36,6 +36,7 @@ use pocketmine\crafting\CraftingManager;
use pocketmine\crafting\CraftingManagerFromDataHelper;
use pocketmine\crash\CrashDump;
use pocketmine\crash\CrashDumpRenderer;
use pocketmine\data\java\GameModeIdMap;
use pocketmine\entity\EntityDataHelper;
use pocketmine\entity\Location;
use pocketmine\event\HandlerListManager;
@ -177,12 +178,6 @@ class Server{
public const BROADCAST_CHANNEL_ADMINISTRATIVE = "pocketmine.broadcast.admin";
public const BROADCAST_CHANNEL_USERS = "pocketmine.broadcast.user";
public const DEFAULT_SERVER_NAME = VersionInfo::NAME . " Server";
public const DEFAULT_MAX_PLAYERS = 20;
public const DEFAULT_PORT_IPV4 = 19132;
public const DEFAULT_PORT_IPV6 = 19133;
public const DEFAULT_MAX_VIEW_DISTANCE = 16;
private static ?Server $instance = null;
private SleeperHandler $tickSleeper;
@ -329,15 +324,15 @@ class Server{
}
public function getPort() : int{
return $this->configGroup->getConfigInt("server-port", self::DEFAULT_PORT_IPV4);
return $this->configGroup->getConfigInt("server-port", 19132);
}
public function getPortV6() : int{
return $this->configGroup->getConfigInt("server-portv6", self::DEFAULT_PORT_IPV6);
return $this->configGroup->getConfigInt("server-portv6", 19133);
}
public function getViewDistance() : int{
return max(2, $this->configGroup->getConfigInt("view-distance", self::DEFAULT_MAX_VIEW_DISTANCE));
return max(2, $this->configGroup->getConfigInt("view-distance", 8));
}
/**
@ -362,7 +357,7 @@ class Server{
}
public function getGamemode() : GameMode{
return GameMode::fromString($this->configGroup->getConfigString("gamemode", GameMode::SURVIVAL()->name())) ?? GameMode::SURVIVAL();
return GameModeIdMap::getInstance()->fromId($this->configGroup->getConfigInt("gamemode", 0)) ?? GameMode::SURVIVAL();
}
public function getForceGamemode() : bool{
@ -385,7 +380,7 @@ class Server{
}
public function getMotd() : string{
return $this->configGroup->getConfigString("motd", self::DEFAULT_SERVER_NAME);
return $this->configGroup->getConfigString("motd", VersionInfo::NAME . " Server");
}
public function getLoader() : \DynamicClassLoader{
@ -542,10 +537,13 @@ class Server{
if(!$ev->isCancelled()){
Timings::$syncPlayerDataSave->time(function() use ($name, $ev) : void{
$nbt = new BigEndianNbtSerializer();
$contents = Utils::assumeNotFalse(zlib_encode($nbt->write(new TreeRoot($ev->getSaveData())), ZLIB_ENCODING_GZIP), "zlib_encode() failed unexpectedly");
$contents = zlib_encode($nbt->write(new TreeRoot($ev->getSaveData())), ZLIB_ENCODING_GZIP);
if($contents === false){
throw new AssumptionFailedError("zlib_encode() failed unexpectedly");
}
try{
Filesystem::safeFilePutContents($this->getPlayerDataPath($name), $contents);
}catch(\RuntimeException $e){
}catch(\RuntimeException | \ErrorException $e){
$this->logger->critical($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_data_saveError($name, $e->getMessage())));
$this->logger->logException($e);
}
@ -561,7 +559,7 @@ class Server{
$ev->call();
$class = $ev->getPlayerClass();
if($offlinePlayerData !== null && ($world = $this->worldManager->getWorldByName($offlinePlayerData->getString("Level", ""))) !== null){
if($offlinePlayerData !== null and ($world = $this->worldManager->getWorldByName($offlinePlayerData->getString("Level", ""))) !== null){
$playerPos = EntityDataHelper::parseLocation($offlinePlayerData, $world);
$spawn = $playerPos->asVector3();
}else{
@ -721,7 +719,7 @@ class Server{
}
public function isWhitelisted(string $name) : bool{
return !$this->hasWhitelist() || $this->operators->exists($name, true) || $this->whitelist->exists($name, true);
return !$this->hasWhitelist() or $this->operators->exists($name, true) or $this->whitelist->exists($name, true);
}
public function isOp(string $name) : bool{
@ -799,7 +797,7 @@ class Server{
$this->logger->info("Loading server configuration");
$pocketmineYmlPath = Path::join($this->dataPath, "pocketmine.yml");
if(!file_exists($pocketmineYmlPath)){
$content = Utils::assumeNotFalse(file_get_contents(Path::join(\pocketmine\RESOURCE_PATH, "pocketmine.yml")), "Missing required resource file");
$content = file_get_contents(Path::join(\pocketmine\RESOURCE_PATH, "pocketmine.yml"));
if(VersionInfo::IS_DEVELOPMENT_BUILD){
$content = str_replace("preferred-channel: stable", "preferred-channel: beta", $content);
}
@ -809,13 +807,13 @@ class Server{
$this->configGroup = new ServerConfigGroup(
new Config($pocketmineYmlPath, Config::YAML, []),
new Config(Path::join($this->dataPath, "server.properties"), Config::PROPERTIES, [
"motd" => self::DEFAULT_SERVER_NAME,
"server-port" => self::DEFAULT_PORT_IPV4,
"server-portv6" => self::DEFAULT_PORT_IPV6,
"motd" => VersionInfo::NAME . " Server",
"server-port" => 19132,
"server-portv6" => 19133,
"enable-ipv6" => true,
"white-list" => false,
"max-players" => self::DEFAULT_MAX_PLAYERS,
"gamemode" => GameMode::SURVIVAL()->name(),
"max-players" => 20,
"gamemode" => 0,
"force-gamemode" => false,
"hardcore" => false,
"pvp" => true,
@ -826,7 +824,7 @@ class Server{
"level-type" => "DEFAULT",
"enable-query" => true,
"auto-save" => true,
"view-distance" => self::DEFAULT_MAX_VIEW_DISTANCE,
"view-distance" => 8,
"xbox-auth" => true,
"language" => "eng"
])
@ -895,7 +893,7 @@ class Server{
}
$netCompressionLevel = $this->configGroup->getPropertyInt("network.compression-level", 6);
if($netCompressionLevel < 1 || $netCompressionLevel > 9){
if($netCompressionLevel < 1 or $netCompressionLevel > 9){
$this->logger->warning("Invalid network compression level $netCompressionLevel set, setting to default 6");
$netCompressionLevel = 6;
}
@ -912,7 +910,7 @@ class Server{
$bannedTxt = Path::join($this->dataPath, "banned.txt");
$bannedPlayersTxt = Path::join($this->dataPath, "banned-players.txt");
if(file_exists($bannedTxt) && !file_exists($bannedPlayersTxt)){
if(file_exists($bannedTxt) and !file_exists($bannedPlayersTxt)){
@rename($bannedTxt, $bannedPlayersTxt);
}
@touch($bannedPlayersTxt);
@ -923,7 +921,7 @@ class Server{
$this->banByIP = new BanList($bannedIpsTxt);
$this->banByIP->load();
$this->maxPlayers = $this->configGroup->getConfigInt("max-players", self::DEFAULT_MAX_PLAYERS);
$this->maxPlayers = $this->configGroup->getConfigInt("max-players", 20);
$this->onlineMode = $this->configGroup->getConfigBool("xbox-auth", true);
if($this->onlineMode){
@ -934,7 +932,7 @@ class Server{
$this->logger->warning($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_server_authProperty_disabled()));
}
if($this->configGroup->getConfigBool("hardcore", false) && $this->getDifficulty() < World::DIFFICULTY_HARD){
if($this->configGroup->getConfigBool("hardcore", false) and $this->getDifficulty() < World::DIFFICULTY_HARD){
$this->configGroup->setConfigInt("difficulty", World::DIFFICULTY_HARD);
}
@ -984,7 +982,7 @@ class Server{
$providerManager = new WorldProviderManager();
if(
($format = $providerManager->getProviderByName($formatName = $this->configGroup->getPropertyString("level-settings.default-format", ""))) !== null &&
($format = $providerManager->getProviderByName($formatName = $this->configGroup->getPropertyString("level-settings.default-format", ""))) !== null and
$format instanceof WritableWorldProviderManagerEntry
){
$providerManager->setDefault($format);
@ -1381,7 +1379,7 @@ class Server{
public function enablePlugins(PluginEnableOrder $type) : void{
foreach($this->pluginManager->getPlugins() as $plugin){
if(!$plugin->isEnabled() && $plugin->getDescription()->getOrder()->equals($type)){
if(!$plugin->isEnabled() and $plugin->getDescription()->getOrder()->equals($type)){
$this->pluginManager->enablePlugin($plugin);
}
}
@ -1572,8 +1570,7 @@ class Server{
$stamp = Path::join($this->getDataPath(), "crashdumps", ".last_crash");
$crashInterval = 120; //2 minutes
if(($lastReportTime = @filemtime($stamp)) !== false && $lastReportTime + $crashInterval >= time()){
$report = false;
if(file_exists($stamp) and !($report = (filemtime($stamp) + $crashInterval < time()))){
$this->logger->debug("Not sending crashdump due to last crash less than $crashInterval seconds ago");
}
@touch($stamp); //update file timestamp
@ -1581,7 +1578,7 @@ class Server{
$plugin = $dump->getData()->plugin;
if($plugin !== ""){
$p = $this->pluginManager->getPlugin($plugin);
if($p instanceof Plugin && !($p->getPluginLoader() instanceof PharPluginLoader)){
if($p instanceof Plugin and !($p->getPluginLoader() instanceof PharPluginLoader)){
$this->logger->debug("Not sending crashdump due to caused by non-phar plugin");
$report = false;
}
@ -1591,7 +1588,7 @@ class Server{
$report = false;
}
if(strrpos(VersionInfo::GIT_HASH(), "-dirty") !== false || VersionInfo::GIT_HASH() === str_repeat("00", 20)){
if(strrpos(VersionInfo::GIT_HASH(), "-dirty") !== false or VersionInfo::GIT_HASH() === str_repeat("00", 20)){
$this->logger->debug("Not sending crashdump due to locally modified");
$report = false; //Don't send crashdumps for locally modified builds
}
@ -1606,8 +1603,8 @@ class Server{
"reportPaste" => base64_encode($dump->getEncodedData())
], 10, [], $postUrlError);
if($reply !== null && ($data = json_decode($reply->getBody())) !== null){
if(isset($data->crashId) && isset($data->crashUrl)){
if($reply !== null and ($data = json_decode($reply->getBody())) !== null){
if(isset($data->crashId) and isset($data->crashUrl)){
$reportId = $data->crashId;
$reportUrl = $data->crashUrl;
$this->logger->emergency($this->getLanguage()->translate(KnownTranslationFactory::pocketmine_crash_archive($reportUrl, (string) $reportId)));
@ -1664,7 +1661,7 @@ class Server{
public function addOnlinePlayer(Player $player) : bool{
$ev = new PlayerLoginEvent($player, "Plugin reason");
$ev->call();
if($ev->isCancelled() || !$player->isConnected()){
if($ev->isCancelled() or !$player->isConnected()){
$player->disconnect($ev->getKickMessage());
return false;
@ -1793,7 +1790,7 @@ class Server{
$this->network->getBandwidthTracker()->rotateAverageHistory();
}
if($this->sendUsageTicker > 0 && --$this->sendUsageTicker === 0){
if($this->sendUsageTicker > 0 and --$this->sendUsageTicker === 0){
$this->sendUsageTicker = 6000;
$this->sendUsage(SendUsageTask::TYPE_STATUS);
}

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.0.8";
public const IS_DEVELOPMENT_BUILD = false;
public const BUILD_CHANNEL = "beta";
public const BUILD_CHANNEL = "stable";
private function __construct(){
//NOOP

View File

@ -160,7 +160,7 @@ class Bamboo extends Transparent{
public function onNearbyBlockChange() : void{
$below = $this->position->getWorld()->getBlock($this->position->down());
if(!$this->canBeSupportedBy($below) && !$below->isSameType($this)){
if(!$this->canBeSupportedBy($below) and !$below->isSameType($this)){
$this->position->getWorld()->useBreakOn($this->position);
}
}

View File

@ -130,7 +130,7 @@ abstract class BaseBanner extends Transparent{
public function getDropsForCompatibleTool(Item $item) : array{
$drop = $this->asItem();
if($drop instanceof ItemBanner && count($this->patterns) > 0){
if($drop instanceof ItemBanner and count($this->patterns) > 0){
$drop->setPatterns($this->patterns);
}
@ -139,7 +139,7 @@ abstract class BaseBanner extends Transparent{
public function getPickedItem(bool $addUserData = false) : Item{
$result = $this->asItem();
if($addUserData && $result instanceof ItemBanner && count($this->patterns) > 0){
if($addUserData and $result instanceof ItemBanner and count($this->patterns) > 0){
$result->setPatterns($this->patterns);
}
return $result;

View File

@ -24,17 +24,34 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\CoralType;
use pocketmine\block\utils\CoralTypeTrait;
use pocketmine\item\Item;
abstract class BaseCoral extends Transparent{
use CoralTypeTrait;
protected CoralType $coralType;
protected bool $dead = false;
public function __construct(BlockIdentifier $idInfo, string $name, BlockBreakInfo $breakInfo){
parent::__construct($idInfo, $name, $breakInfo);
$this->coralType = CoralType::TUBE();
}
public function getCoralType() : CoralType{ return $this->coralType; }
/** @return $this */
public function setCoralType(CoralType $coralType) : self{
$this->coralType = $coralType;
return $this;
}
public function isDead() : bool{ return $this->dead; }
/** @return $this */
public function setDead(bool $dead) : self{
$this->dead = $dead;
return $this;
}
public function onNearbyBlockChange() : void{
if(!$this->dead){
$world = $this->position->getWorld();

View File

@ -101,7 +101,7 @@ abstract class BaseRail extends Flowable{
}
if(
$other instanceof BaseRail &&
$other instanceof BaseRail and
in_array($otherConnection, $other->getCurrentShapeConnections(), true)
){
$connections[] = $connection;
@ -179,7 +179,7 @@ abstract class BaseRail extends Flowable{
$otherSide |= RailConnectionInfo::FLAG_ASCEND;
}
if(!($other instanceof BaseRail) || count($otherConnections = $other->getConnectedDirections()) >= 2){
if(!($other instanceof BaseRail) or count($otherConnections = $other->getConnectedDirections()) >= 2){
//we can only connect to a rail that has less than 2 connections
continue;
}
@ -224,7 +224,7 @@ abstract class BaseRail extends Flowable{
$this->position->getWorld()->useBreakOn($this->position);
}else{
foreach($this->getCurrentShapeConnections() as $connection){
if(($connection & RailConnectionInfo::FLAG_ASCEND) !== 0 && $this->getSide($connection & ~RailConnectionInfo::FLAG_ASCEND)->isTransparent()){
if(($connection & RailConnectionInfo::FLAG_ASCEND) !== 0 and $this->getSide($connection & ~RailConnectionInfo::FLAG_ASCEND)->isTransparent()){
$this->position->getWorld()->useBreakOn($this->position);
break;
}

View File

@ -120,7 +120,7 @@ class Bed extends Transparent{
public function getOtherHalf() : ?Bed{
$other = $this->getSide($this->getOtherHalfSide());
if($other instanceof Bed && $other->head !== $this->head && $other->facing === $this->facing){
if($other instanceof Bed and $other->head !== $this->head and $other->facing === $this->facing){
return $other;
}
@ -135,14 +135,14 @@ class Bed extends Transparent{
$player->sendMessage(TextFormat::GRAY . "This bed is incomplete");
return true;
}elseif($playerPos->distanceSquared($this->position) > 4 && $playerPos->distanceSquared($other->position) > 4){
}elseif($playerPos->distanceSquared($this->position) > 4 and $playerPos->distanceSquared($other->position) > 4){
$player->sendMessage(KnownTranslationFactory::tile_bed_tooFar()->prefix(TextFormat::GRAY));
return true;
}
$time = $this->position->getWorld()->getTimeOfDay();
$isNight = ($time >= World::TIME_NIGHT && $time < World::TIME_SUNRISE);
$isNight = ($time >= World::TIME_NIGHT and $time < World::TIME_SUNRISE);
if(!$isNight){
$player->sendMessage(KnownTranslationFactory::tile_bed_noSleep()->prefix(TextFormat::GRAY));
@ -166,7 +166,7 @@ class Bed extends Transparent{
}
public function onNearbyBlockChange() : void{
if(($other = $this->getOtherHalf()) !== null && $other->occupied !== $this->occupied){
if(($other = $this->getOtherHalf()) !== null and $other->occupied !== $this->occupied){
$this->occupied = $other->occupied;
$this->position->getWorld()->setBlock($this->position, $this);
}
@ -186,7 +186,7 @@ class Bed extends Transparent{
$this->facing = $player !== null ? $player->getHorizontalFacing() : Facing::NORTH;
$next = $this->getSide($this->getOtherHalfSide());
if($next->canBeReplaced() && !$next->getSide(Facing::DOWN)->isTransparent()){
if($next->canBeReplaced() and !$next->getSide(Facing::DOWN)->isTransparent()){
$nextState = clone $this;
$nextState->head = true;
$tx->addBlock($blockReplace->position, $this)->addBlock($next->position, $nextState);

View File

@ -148,14 +148,14 @@ class Block{
$tileType = $this->idInfo->getTileClass();
$oldTile = $this->position->getWorld()->getTile($this->position);
if($oldTile !== null){
if($tileType === null || !($oldTile instanceof $tileType)){
if($tileType === null or !($oldTile instanceof $tileType)){
$oldTile->close();
$oldTile = null;
}elseif($oldTile instanceof Spawnable){
$oldTile->setDirty(); //destroy old network cache
}
}
if($oldTile === null && $tileType !== null){
if($oldTile === null and $tileType !== null){
/**
* @var Tile $tile
* @see Tile::__construct()
@ -166,21 +166,13 @@ class Block{
}
/**
* Returns a type ID that identifies this type of block. This does not include information like facing, colour,
* powered/unpowered, etc.
*/
public function getTypeId() : int{
return ($this->idInfo->getBlockId() << Block::INTERNAL_METADATA_BITS) | $this->idInfo->getVariant();
}
/**
* Returns whether the given block has an equivalent type to this one. This compares the type IDs.
* Returns whether the given block has an equivalent type to this one. This compares base legacy ID and variant.
*
* Note: This ignores additional IDs used to represent additional states. This means that, for example, a lit
* furnace and unlit furnace are considered the same type.
*/
public function isSameType(Block $other) : bool{
return $this->getTypeId() === $other->getTypeId();
return $this->idInfo->getBlockId() === $other->idInfo->getBlockId() and $this->idInfo->getVariant() === $other->idInfo->getVariant();
}
/**
@ -361,7 +353,7 @@ class Block{
*/
public function getDrops(Item $item) : array{
if($this->breakInfo->isToolCompatible($item)){
if($this->isAffectedBySilkTouch() && $item->hasEnchantment(VanillaEnchantments::SILK_TOUCH())){
if($this->isAffectedBySilkTouch() and $item->hasEnchantment(VanillaEnchantments::SILK_TOUCH())){
return $this->getSilkTouchDrops($item);
}
@ -402,7 +394,7 @@ class Block{
* Returns how much XP will be dropped by breaking this block with the given item.
*/
public function getXpDropForTool(Item $item) : int{
if($item->hasEnchantment(VanillaEnchantments::SILK_TOUCH()) || !$this->breakInfo->isToolCompatible($item)){
if($item->hasEnchantment(VanillaEnchantments::SILK_TOUCH()) or !$this->breakInfo->isToolCompatible($item)){
return 0;
}
@ -613,7 +605,7 @@ class Block{
public function isFullCube() : bool{
$bb = $this->getCollisionBoxes();
return count($bb) === 1 && $bb[0]->getAverageEdgeLength() >= 1 && $bb[0]->isCube();
return count($bb) === 1 and $bb[0]->getAverageEdgeLength() >= 1 and $bb[0]->isCube();
}
public function calculateIntercept(Vector3 $pos1, Vector3 $pos2) : ?RayTraceResult{

View File

@ -119,8 +119,8 @@ class BlockBreakInfo{
return false;
}
return $this->toolType === BlockToolType::NONE || $this->toolHarvestLevel === 0 || (
($this->toolType & $tool->getBlockToolType()) !== 0 && $tool->getBlockToolHarvestLevel() >= $this->toolHarvestLevel);
return $this->toolType === BlockToolType::NONE or $this->toolHarvestLevel === 0 or (
($this->toolType & $tool->getBlockToolType()) !== 0 and $tool->getBlockToolHarvestLevel() >= $this->toolHarvestLevel);
}
/**

View File

@ -43,7 +43,6 @@ use pocketmine\block\tile\FlowerPot as TileFlowerPot;
use pocketmine\block\tile\Hopper as TileHopper;
use pocketmine\block\tile\ItemFrame as TileItemFrame;
use pocketmine\block\tile\Jukebox as TileJukebox;
use pocketmine\block\tile\Lectern as TileLectern;
use pocketmine\block\tile\MonsterSpawner as TileMonsterSpawner;
use pocketmine\block\tile\NormalFurnace as TileNormalFurnace;
use pocketmine\block\tile\Note as TileNote;
@ -261,7 +260,6 @@ class BlockFactory{
$this->registerAllMeta(new Opaque(new BID(Ids::LAPIS_BLOCK, 0), "Lapis Lazuli Block", new BlockBreakInfo(3.0, BlockToolType::PICKAXE, ToolTier::STONE()->getHarvestLevel())));
$this->registerAllMeta(new LapisOre(new BID(Ids::LAPIS_ORE, 0), "Lapis Lazuli Ore", new BlockBreakInfo(3.0, BlockToolType::PICKAXE, ToolTier::STONE()->getHarvestLevel())));
$this->registerAllMeta(new Lava(new BIDFlattened(Ids::FLOWING_LAVA, [Ids::STILL_LAVA], 0), "Lava", BlockBreakInfo::indestructible(500.0)));
$this->registerAllMeta(new Lectern(new BID(Ids::LECTERN, 0, ItemIds::LECTERN, TileLectern::class), "Lectern", new BlockBreakInfo(2.0, BlockToolType::AXE)));
$this->registerAllMeta(new Lever(new BID(Ids::LEVER, 0), "Lever", new BlockBreakInfo(0.5)));
$this->registerAllMeta(new Loom(new BID(Ids::LOOM, 0), "Loom", new BlockBreakInfo(2.5, BlockToolType::AXE)));
$this->registerAllMeta(new Magma(new BID(Ids::MAGMA, 0), "Magma Block", new BlockBreakInfo(0.5, BlockToolType::PICKAXE, ToolTier::WOOD()->getHarvestLevel())));
@ -300,7 +298,7 @@ class BlockFactory{
$this->registerAllMeta(new Stair(new BID(Ids::PRISMARINE_STAIRS, 0), "Prismarine Stairs", $prismarineBreakInfo));
$pumpkinBreakInfo = new BlockBreakInfo(1.0, BlockToolType::AXE);
$this->registerAllMeta(new Pumpkin(new BID(Ids::PUMPKIN, 0), "Pumpkin", $pumpkinBreakInfo));
$this->registerAllMeta($pumpkin = new Opaque(new BID(Ids::PUMPKIN, 0), "Pumpkin", $pumpkinBreakInfo));
$this->registerAllMeta(new CarvedPumpkin(new BID(Ids::CARVED_PUMPKIN, 0), "Carved Pumpkin", $pumpkinBreakInfo));
$this->registerAllMeta(new LitPumpkin(new BID(Ids::JACK_O_LANTERN, 0), "Jack o'Lantern", $pumpkinBreakInfo));
@ -628,6 +626,7 @@ class BlockFactory{
//TODO: minecraft:jigsaw
//TODO: minecraft:kelp
//TODO: minecraft:lava_cauldron
//TODO: minecraft:lectern
//TODO: minecraft:movingBlock
//TODO: minecraft:observer
//TODO: minecraft:piston
@ -974,7 +973,7 @@ class BlockFactory{
}
foreach($block->getIdInfo()->getAllBlockIds() as $id){
if(!$override && $this->isRegistered($id, $variant)){
if(!$override and $this->isRegistered($id, $variant)){
throw new \InvalidArgumentException("Block registration $id:$variant conflicts with an existing block");
}
@ -983,7 +982,7 @@ class BlockFactory{
continue;
}
if(!$override && $this->isRegistered($id, $m)){
if(!$override and $this->isRegistered($id, $m)){
throw new \InvalidArgumentException("Block registration " . get_class($block) . " has states which conflict with other blocks");
}
@ -1036,7 +1035,7 @@ class BlockFactory{
* Deserializes a block from the provided legacy ID and legacy meta.
*/
public function get(int $id, int $meta) : Block{
if($meta < 0 || $meta >= (1 << Block::INTERNAL_METADATA_BITS)){
if($meta < 0 or $meta >= (1 << Block::INTERNAL_METADATA_BITS)){
throw new \InvalidArgumentException("Block meta value $meta is out of bounds");
}
@ -1062,7 +1061,7 @@ class BlockFactory{
*/
public function isRegistered(int $id, int $meta = 0) : bool{
$b = $this->fullList[($id << Block::INTERNAL_METADATA_BITS) | $meta];
return $b !== null && !($b instanceof UnknownBlock);
return $b !== null and !($b instanceof UnknownBlock);
}
/**

View File

@ -142,8 +142,6 @@ final class BlockLegacyMetadata{
public const LEAVES_FLAG_NO_DECAY = 0x04;
public const LEAVES_FLAG_CHECK_DECAY = 0x08;
public const LECTERN_FLAG_POWERED = 0x04;
public const LEVER_FLAG_POWERED = 0x08;
public const LIQUID_FLAG_FALLING = 0x08;

View File

@ -116,7 +116,7 @@ class BrewingStand extends Transparent{
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($player instanceof Player){
$stand = $this->position->getWorld()->getTile($this->position);
if($stand instanceof TileBrewingStand && $stand->canOpenWith($item->getCustomName())){
if($stand instanceof TileBrewingStand and $stand->canOpenWith($item->getCustomName())){
$player->setCurrentWindow($stand->getInventory());
}
}

View File

@ -82,7 +82,7 @@ class Cactus extends Transparent{
public function onNearbyBlockChange() : void{
$down = $this->getSide(Facing::DOWN);
if($down->getId() !== BlockLegacyIds::SAND && !$down->isSameType($this)){
if($down->getId() !== BlockLegacyIds::SAND and !$down->isSameType($this)){
$this->position->getWorld()->useBreakOn($this->position);
}else{
foreach(Facing::HORIZONTAL as $side){
@ -129,7 +129,7 @@ class Cactus extends Transparent{
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
$down = $this->getSide(Facing::DOWN);
if($down->getId() === BlockLegacyIds::SAND || $down->isSameType($this)){
if($down->getId() === BlockLegacyIds::SAND or $down->isSameType($this)){
foreach(Facing::HORIZONTAL as $side){
if($this->getSide($side)->isSolid()){
return false;

View File

@ -26,7 +26,6 @@ namespace pocketmine\block;
use pocketmine\block\tile\Chest as TileChest;
use pocketmine\block\utils\FacesOppositePlacingPlayerTrait;
use pocketmine\block\utils\NormalHorizontalFacingInMetadataTrait;
use pocketmine\event\block\ChestPairEvent;
use pocketmine\item\Item;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Facing;
@ -48,21 +47,17 @@ class Chest extends Transparent{
public function onPostPlace() : void{
$tile = $this->position->getWorld()->getTile($this->position);
if($tile instanceof TileChest){
foreach([false, true] as $clockwise){
$side = Facing::rotateY($this->facing, $clockwise);
foreach([
Facing::rotateY($this->facing, true),
Facing::rotateY($this->facing, false)
] as $side){
$c = $this->getSide($side);
if($c instanceof Chest && $c->isSameType($this) && $c->facing === $this->facing){
$world = $this->position->getWorld();
$pair = $world->getTile($c->position);
if($pair instanceof TileChest && !$pair->isPaired()){
[$left, $right] = $clockwise ? [$c, $this] : [$this, $c];
$ev = new ChestPairEvent($left, $right);
$ev->call();
if(!$ev->isCancelled() && $world->getBlock($this->position)->isSameType($this) && $world->getBlock($c->position)->isSameType($c)){
$pair->pairWith($tile);
$tile->pairWith($pair);
break;
}
if($c instanceof Chest and $c->isSameType($this) and $c->facing === $this->facing){
$pair = $this->position->getWorld()->getTile($c->position);
if($pair instanceof TileChest and !$pair->isPaired()){
$pair->pairWith($tile);
$tile->pairWith($pair);
break;
}
}
}
@ -75,8 +70,8 @@ class Chest extends Transparent{
$chest = $this->position->getWorld()->getTile($this->position);
if($chest instanceof TileChest){
if(
!$this->getSide(Facing::UP)->isTransparent() ||
(($pair = $chest->getPair()) !== null && !$pair->getBlock()->getSide(Facing::UP)->isTransparent()) ||
!$this->getSide(Facing::UP)->isTransparent() or
(($pair = $chest->getPair()) !== null and !$pair->getBlock()->getSide(Facing::UP)->isTransparent()) or
!$chest->canOpenWith($item->getCustomName())
){
return true;

View File

@ -86,7 +86,7 @@ class CocoaBlock extends Transparent{
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if(Facing::axis($face) !== Axis::Y && $this->canAttachTo($blockClicked)){
if(Facing::axis($face) !== Axis::Y and $this->canAttachTo($blockClicked)){
$this->facing = $face;
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}

View File

@ -27,7 +27,6 @@ use pocketmine\block\utils\ColorInMetadataTrait;
use pocketmine\block\utils\DyeColor;
use pocketmine\block\utils\Fallable;
use pocketmine\block\utils\FallableTrait;
use pocketmine\event\block\BlockFormEvent;
use pocketmine\math\Facing;
class ConcretePowder extends Opaque implements Fallable{
@ -43,11 +42,7 @@ class ConcretePowder extends Opaque implements Fallable{
public function onNearbyBlockChange() : void{
if(($block = $this->checkAdjacentWater()) !== null){
$ev = new BlockFormEvent($this, $block);
$ev->call();
if(!$ev->isCancelled()){
$this->position->getWorld()->setBlock($this->position, $ev->getNewState());
}
$this->position->getWorld()->setBlock($this->position, $block);
}else{
$this->startFalling();
}

View File

@ -24,14 +24,15 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\CoralType;
use pocketmine\block\utils\CoralTypeTrait;
use pocketmine\block\utils\InvalidBlockStateException;
use pocketmine\data\bedrock\CoralTypeIdMap;
use pocketmine\item\Item;
use function mt_rand;
final class CoralBlock extends Opaque{
use CoralTypeTrait;
private CoralType $coralType;
private bool $dead = false;
public function __construct(BlockIdentifier $idInfo, string $name, BlockBreakInfo $breakInfo){
$this->coralType = CoralType::TUBE();
@ -59,6 +60,22 @@ final class CoralBlock extends Opaque{
return 0b1111;
}
public function getCoralType() : CoralType{ return $this->coralType; }
/** @return $this */
public function setCoralType(CoralType $coralType) : self{
$this->coralType = $coralType;
return $this;
}
public function isDead() : bool{ return $this->dead; }
/** @return $this */
public function setDead(bool $dead) : self{
$this->dead = $dead;
return $this;
}
public function onNearbyBlockChange() : void{
if(!$this->dead){
$this->position->getWorld()->scheduleDelayedBlockUpdate($this->position, mt_rand(40, 200));

View File

@ -69,7 +69,7 @@ abstract class Crops extends Flowable{
}
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($this->age < 7 && $item instanceof Fertilizer){
if($this->age < 7 and $item instanceof Fertilizer){
$block = clone $this;
$block->age += mt_rand(2, 5);
if($block->age > 7){
@ -100,7 +100,7 @@ abstract class Crops extends Flowable{
}
public function onRandomTick() : void{
if($this->age < 7 && mt_rand(0, 2) === 1){
if($this->age < 7 and mt_rand(0, 2) === 1){
$block = clone $this;
++$block->age;
$ev = new BlockGrowEvent($this, $block);

View File

@ -28,7 +28,6 @@ use pocketmine\item\Item;
use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\sound\ItemUseOnBlockSound;
class Dirt extends Opaque{
@ -59,12 +58,9 @@ class Dirt extends Opaque{
}
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($face === Facing::UP && $item instanceof Hoe){
if($face === Facing::UP and $item instanceof Hoe){
$item->applyDamage(1);
$newBlock = $this->coarse ? VanillaBlocks::DIRT() : VanillaBlocks::FARMLAND();
$this->position->getWorld()->addSound($this->position->add(0.5, 0.5, 0.5), new ItemUseOnBlockSound($newBlock));
$this->position->getWorld()->setBlock($this->position, $newBlock);
$this->position->getWorld()->setBlock($this->position, $this->coarse ? VanillaBlocks::DIRT() : VanillaBlocks::FARMLAND());
return true;
}

View File

@ -72,7 +72,7 @@ class Door extends Transparent{
//copy door properties from other half
$other = $this->getSide($this->top ? Facing::DOWN : Facing::UP);
if($other instanceof Door && $other->isSameType($this)){
if($other instanceof Door and $other->isSameType($this)){
if($this->top){
$this->facing = $other->facing;
$this->open = $other->open;
@ -129,7 +129,7 @@ class Door extends Transparent{
if($face === Facing::UP){
$blockUp = $this->getSide(Facing::UP);
$blockDown = $this->getSide(Facing::DOWN);
if(!$blockUp->canBeReplaced() || $blockDown->isTransparent()){
if(!$blockUp->canBeReplaced() or $blockDown->isTransparent()){
return false;
}
@ -140,7 +140,7 @@ class Door extends Transparent{
$next = $this->getSide(Facing::rotateY($this->facing, false));
$next2 = $this->getSide(Facing::rotateY($this->facing, true));
if($next->isSameType($this) || (!$next2->isTransparent() && $next->isTransparent())){ //Door hinge
if($next->isSameType($this) or (!$next2->isTransparent() and $next->isTransparent())){ //Door hinge
$this->hingeRight = true;
}
@ -158,7 +158,7 @@ class Door extends Transparent{
$this->open = !$this->open;
$other = $this->getSide($this->top ? Facing::DOWN : Facing::UP);
if($other instanceof Door && $other->isSameType($this)){
if($other instanceof Door and $other->isSameType($this)){
$other->open = $this->open;
$this->position->getWorld()->setBlock($other->position, $other);
}

View File

@ -55,7 +55,7 @@ class DoublePlant extends Flowable{
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
$id = $blockReplace->getSide(Facing::DOWN)->getId();
if(($id === BlockLegacyIds::GRASS || $id === BlockLegacyIds::DIRT) && $blockReplace->getSide(Facing::UP)->canBeReplaced()){
if(($id === BlockLegacyIds::GRASS or $id === BlockLegacyIds::DIRT) and $blockReplace->getSide(Facing::UP)->canBeReplaced()){
$top = clone $this;
$top->top = true;
$tx->addBlock($blockReplace->position, $this)->addBlock($blockReplace->position->getSide(Facing::UP), $top);
@ -72,14 +72,14 @@ class DoublePlant extends Flowable{
$other = $this->getSide($this->top ? Facing::DOWN : Facing::UP);
return (
$other instanceof DoublePlant &&
$other->isSameType($this) &&
$other instanceof DoublePlant and
$other->isSameType($this) and
$other->top !== $this->top
);
}
public function onNearbyBlockChange() : void{
if(!$this->isValidHalfPlant() || (!$this->top && $this->getSide(Facing::DOWN)->isTransparent())){
if(!$this->isValidHalfPlant() or (!$this->top and $this->getSide(Facing::DOWN)->isTransparent())){
$this->position->getWorld()->useBreakOn($this->position);
}
}

View File

@ -34,7 +34,7 @@ class DoubleTallGrass extends DoublePlant{
}
public function getDropsForIncompatibleTool(Item $item) : array{
if($this->top && mt_rand(0, 7) === 0){
if($this->top and mt_rand(0, 7) === 0){
return [VanillaItems::WHEAT_SEEDS()];
}
return [];

View File

@ -46,7 +46,7 @@ class EndRod extends Flowable{
}
public function readStateFromData(int $id, int $stateMeta) : void{
if($stateMeta !== 0 && $stateMeta !== 1){
if($stateMeta !== 0 and $stateMeta !== 1){
$stateMeta ^= 1;
}
@ -59,7 +59,7 @@ class EndRod extends Flowable{
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
$this->facing = $face;
if($blockClicked instanceof EndRod && $blockClicked->facing === $this->facing){
if($blockClicked instanceof EndRod and $blockClicked->facing === $this->facing){
$this->facing = Facing::opposite($face);
}

View File

@ -52,7 +52,7 @@ class EnderChest extends Transparent{
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($player instanceof Player){
$enderChest = $this->position->getWorld()->getTile($this->position);
if($enderChest instanceof TileEnderChest && $this->getSide(Facing::UP)->isTransparent()){
if($enderChest instanceof TileEnderChest and $this->getSide(Facing::UP)->isTransparent()){
$enderChest->setViewerCount($enderChest->getViewerCount() + 1);
$player->setCurrentWindow(new EnderChestInventory($this->position, $player->getEnderInventory()));
}
@ -66,4 +66,8 @@ class EnderChest extends Transparent{
VanillaBlocks::OBSIDIAN()->asItem()->setCount(8)
];
}
public function isAffectedBySilkTouch() : bool{
return true;
}
}

View File

@ -41,7 +41,7 @@ class Fence extends Transparent{
foreach(Facing::HORIZONTAL as $facing){
$block = $this->getSide($facing);
if($block instanceof static || $block instanceof FenceGate || ($block->isSolid() && !$block->isTransparent())){
if($block instanceof static or $block instanceof FenceGate or ($block->isSolid() and !$block->isTransparent())){
$this->connections[$facing] = true;
}else{
unset($this->connections[$facing]);
@ -61,7 +61,7 @@ class Fence extends Transparent{
$connectWest = isset($this->connections[Facing::WEST]);
$connectEast = isset($this->connections[Facing::EAST]);
if($connectWest || $connectEast){
if($connectWest or $connectEast){
//X axis (west/east)
$bbs[] = AxisAlignedBB::one()
->squash(Axis::Z, $inset)
@ -73,7 +73,7 @@ class Fence extends Transparent{
$connectNorth = isset($this->connections[Facing::NORTH]);
$connectSouth = isset($this->connections[Facing::SOUTH]);
if($connectNorth || $connectSouth){
if($connectNorth or $connectSouth){
//Z axis (north/south)
$bbs[] = AxisAlignedBB::one()
->squash(Axis::X, $inset)

View File

@ -80,7 +80,7 @@ class FenceGate extends Transparent{
private function checkInWall() : bool{
return (
$this->getSide(Facing::rotateY($this->facing, false)) instanceof Wall ||
$this->getSide(Facing::rotateY($this->facing, false)) instanceof Wall or
$this->getSide(Facing::rotateY($this->facing, true)) instanceof Wall
);
}
@ -105,7 +105,7 @@ class FenceGate extends Transparent{
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
$this->open = !$this->open;
if($this->open && $player !== null){
if($this->open and $player !== null){
$playerFacing = $player->getHorizontalFacing();
if($playerFacing === Facing::opposite($this->facing)){
$this->facing = $playerFacing;

View File

@ -27,16 +27,11 @@ use pocketmine\block\utils\BlockDataSerializer;
use pocketmine\entity\Entity;
use pocketmine\entity\projectile\Arrow;
use pocketmine\event\block\BlockBurnEvent;
use pocketmine\event\block\BlockSpreadEvent;
use pocketmine\event\entity\EntityCombustByBlockEvent;
use pocketmine\event\entity\EntityDamageByBlockEvent;
use pocketmine\event\entity\EntityDamageEvent;
use pocketmine\item\Item;
use pocketmine\math\Facing;
use pocketmine\world\format\Chunk;
use pocketmine\world\World;
use function intdiv;
use function max;
use function min;
use function mt_rand;
@ -99,7 +94,7 @@ class Fire extends Flowable{
}
public function onNearbyBlockChange() : void{
if(!$this->getSide(Facing::DOWN)->isSolid() && !$this->hasAdjacentFlammableBlocks()){
if(!$this->getSide(Facing::DOWN)->isSolid() and !$this->hasAdjacentFlammableBlocks()){
$this->position->getWorld()->setBlock($this->position, VanillaBlocks::AIR());
}else{
$this->position->getWorld()->scheduleDelayedBlockUpdate($this->position, mt_rand(30, 40));
@ -114,7 +109,7 @@ class Fire extends Flowable{
$down = $this->getSide(Facing::DOWN);
$result = null;
if($this->age < 15 && mt_rand(0, 2) === 0){
if($this->age < 15 and mt_rand(0, 2) === 0){
$this->age++;
$result = $this;
}
@ -123,13 +118,13 @@ class Fire extends Flowable{
if(!$down->burnsForever()){
//TODO: check rain
if($this->age === 15){
if(!$down->isFlammable() && mt_rand(0, 3) === 3){ //1/4 chance to extinguish
if(!$down->isFlammable() and mt_rand(0, 3) === 3){ //1/4 chance to extinguish
$canSpread = false;
$result = VanillaBlocks::AIR();
}
}elseif(!$this->hasAdjacentFlammableBlocks()){
$canSpread = false;
if(!$down->isSolid() || $this->age > 3){
if(!$down->isSolid() or $this->age > 3){
$result = VanillaBlocks::AIR();
}
}
@ -142,8 +137,17 @@ class Fire extends Flowable{
$this->position->getWorld()->scheduleDelayedBlockUpdate($this->position, mt_rand(30, 40));
if($canSpread){
$this->burnBlocksAround();
$this->spreadFire();
//TODO: raise upper bound for chance in humid biomes
foreach($this->getHorizontalSides() as $side){
$this->burnBlock($side, 300);
}
//vanilla uses a 250 upper bound here, but I don't think they intended to increase the chance of incineration
$this->burnBlock($this->getSide(Facing::UP), 350);
$this->burnBlock($this->getSide(Facing::DOWN), 350);
//TODO: fire spread
}
}
@ -161,18 +165,6 @@ class Fire extends Flowable{
return false;
}
private function burnBlocksAround() : void{
//TODO: raise upper bound for chance in humid biomes
foreach($this->getHorizontalSides() as $side){
$this->burnBlock($side, 300);
}
//vanilla uses a 250 upper bound here, but I don't think they intended to increase the chance of incineration
$this->burnBlock($this->getSide(Facing::UP), 350);
$this->burnBlock($this->getSide(Facing::DOWN), 350);
}
private function burnBlock(Block $block, int $chanceBound) : void{
if(mt_rand(0, $chanceBound) < $block->getFlammability()){
$ev = new BlockBurnEvent($block, $this);
@ -180,85 +172,14 @@ class Fire extends Flowable{
if(!$ev->isCancelled()){
$block->onIncinerate();
$spreadedFire = false;
if(mt_rand(0, $this->age + 9) < 5){ //TODO: check rain
$fire = clone $this;
$fire->age = min(15, $fire->age + (mt_rand(0, 4) >> 2));
$spreadedFire = $this->spreadBlock($block, $fire);
}
if(!$spreadedFire){
$this->position->getWorld()->setBlock($block->position, $fire);
}else{
$this->position->getWorld()->setBlock($block->position, VanillaBlocks::AIR());
}
}
}
}
private function spreadFire() : void{
$world = $this->position->getWorld();
$difficultyChanceIncrease = $world->getDifficulty() * 7;
$ageDivisor = $this->age + 30;
for($y = -1; $y <= 4; ++$y){
$targetY = $y + (int) $this->position->y;
if($targetY < World::Y_MIN || $targetY >= World::Y_MAX){
continue;
}
//Higher blocks have a lower chance of catching fire
$randomBound = 100 + ($y > 1 ? ($y - 1) * 100 : 0);
for($z = -1; $z <= 1; ++$z){
$targetZ = $z + (int) $this->position->z;
for($x = -1; $x <= 1; ++$x){
if($x === 0 && $y === 0 && $z === 0){
continue;
}
$targetX = $x + (int) $this->position->x;
if(!$world->isInWorld($targetX, $targetY, $targetZ)){
continue;
}
if(!$world->isChunkLoaded($targetX >> Chunk::COORD_BIT_SIZE, $targetZ >> Chunk::COORD_BIT_SIZE)){
continue;
}
$block = $world->getBlockAt($targetX, $targetY, $targetZ);
if($block->getId() !== BlockLegacyIds::AIR){
continue;
}
//TODO: fire can't spread if it's raining in any horizontally adjacent block, or the current one
$encouragement = 0;
foreach($block->position->sides() as $vector3){
if($world->isInWorld($vector3->x, $vector3->y, $vector3->z)){
$encouragement = max($encouragement, $world->getBlockAt($vector3->x, $vector3->y, $vector3->z)->getFlameEncouragement());
}
}
if($encouragement <= 0){
continue;
}
$maxChance = intdiv($encouragement + 40 + $difficultyChanceIncrease, $ageDivisor);
//TODO: max chance is lowered by half in humid biomes
if($maxChance > 0 && mt_rand(0, $randomBound - 1) <= $maxChance){
$new = clone $this;
$new->age = min(15, $this->age + (mt_rand(0, 4) >> 2));
$this->spreadBlock($block, $new);
}
}
}
}
}
private function spreadBlock(Block $block, Block $newState) : bool{
$ev = new BlockSpreadEvent($block, $this, $newState);
$ev->call();
if(!$ev->isCancelled()){
$block->position->getWorld()->setBlock($block->position, $ev->getNewState());
return true;
}
return false;
}
}

View File

@ -33,7 +33,7 @@ class Flower extends Flowable{
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
$down = $this->getSide(Facing::DOWN);
if($down->getId() === BlockLegacyIds::GRASS || $down->getId() === BlockLegacyIds::DIRT || $down->getId() === BlockLegacyIds::FARMLAND){
if($down->getId() === BlockLegacyIds::GRASS or $down->getId() === BlockLegacyIds::DIRT or $down->getId() === BlockLegacyIds::FARMLAND){
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}

View File

@ -69,7 +69,7 @@ class FlowerPot extends Flowable{
/** @return $this */
public function setPlant(?Block $plant) : self{
if($plant === null || $plant instanceof Air){
if($plant === null or $plant instanceof Air){
$this->plant = null;
}else{
$this->plant = clone $plant;
@ -83,12 +83,12 @@ class FlowerPot extends Flowable{
}
return
$block instanceof Cactus ||
$block instanceof DeadBush ||
$block instanceof Flower ||
$block instanceof RedMushroom ||
$block instanceof Sapling ||
($block instanceof TallGrass && $block->getIdInfo()->getVariant() === BlockLegacyMetadata::TALLGRASS_FERN); //TODO: clean up
$block instanceof Cactus or
$block instanceof DeadBush or
$block instanceof Flower or
$block instanceof RedMushroom or
$block instanceof Sapling or
($block instanceof TallGrass and $block->getIdInfo()->getVariant() === BlockLegacyMetadata::TALLGRASS_FERN); //TODO: clean up
//TODO: bamboo
}

View File

@ -24,7 +24,6 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\utils\BlockDataSerializer;
use pocketmine\event\block\BlockMeltEvent;
use function mt_rand;
class FrostedIce extends Ice{
@ -63,7 +62,7 @@ class FrostedIce extends Ice{
}
public function onRandomTick() : void{
if((!$this->checkAdjacentBlocks(4) || mt_rand(0, 2) === 0) &&
if((!$this->checkAdjacentBlocks(4) or mt_rand(0, 2) === 0) and
$this->position->getWorld()->getHighestAdjacentFullLightAt($this->position->x, $this->position->y, $this->position->z) >= 12 - $this->age){
if($this->tryMelt()){
foreach($this->getAllSides() as $block){
@ -85,11 +84,11 @@ class FrostedIce extends Ice{
$found = 0;
for($x = -1; $x <= 1; ++$x){
for($z = -1; $z <= 1; ++$z){
if($x === 0 && $z === 0){
if($x === 0 and $z === 0){
continue;
}
if(
$this->position->getWorld()->getBlockAt($this->position->x + $x, $this->position->y, $this->position->z + $z) instanceof FrostedIce &&
$this->position->getWorld()->getBlockAt($this->position->x + $x, $this->position->y, $this->position->z + $z) instanceof FrostedIce and
++$found >= $requirement
){
return true;
@ -106,11 +105,7 @@ class FrostedIce extends Ice{
*/
private function tryMelt() : bool{
if($this->age >= 3){
$ev = new BlockMeltEvent($this, VanillaBlocks::WATER());
$ev->call();
if(!$ev->isCancelled()){
$this->position->getWorld()->setBlock($this->position, $ev->getNewState());
}
$this->position->getWorld()->useBreakOn($this->position);
return true;
}

View File

@ -73,7 +73,7 @@ class Furnace extends Opaque{
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($player instanceof Player){
$furnace = $this->position->getWorld()->getTile($this->position);
if($furnace instanceof TileFurnace && $furnace->canOpenWith($item->getCustomName())){
if($furnace instanceof TileFurnace and $furnace->canOpenWith($item->getCustomName())){
$player->setCurrentWindow($furnace->getInventory());
}
}
@ -83,7 +83,7 @@ class Furnace extends Opaque{
public function onScheduledUpdate() : void{
$furnace = $this->position->getWorld()->getTile($this->position);
if($furnace instanceof TileFurnace && $furnace->onUpdate()){
if($furnace instanceof TileFurnace and $furnace->onUpdate()){
$this->position->getWorld()->scheduleDelayedBlockUpdate($this->position, 1); //TODO: check this
}
}

View File

@ -33,7 +33,6 @@ use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\utils\Random;
use pocketmine\world\generator\object\TallGrass as TallGrassObject;
use pocketmine\world\sound\ItemUseOnBlockSound;
use function mt_rand;
class Grass extends Opaque{
@ -54,7 +53,7 @@ class Grass extends Opaque{
public function onRandomTick() : void{
$lightAbove = $this->position->getWorld()->getFullLightAt($this->position->x, $this->position->y + 1, $this->position->z);
if($lightAbove < 4 && $this->position->getWorld()->getBlockAt($this->position->x, $this->position->y + 1, $this->position->z)->getLightFilter() >= 2){
if($lightAbove < 4 and $this->position->getWorld()->getBlockAt($this->position->x, $this->position->y + 1, $this->position->z)->getLightFilter() >= 2){
//grass dies
$ev = new BlockSpreadEvent($this, $this, VanillaBlocks::DIRT());
$ev->call();
@ -70,9 +69,9 @@ class Grass extends Opaque{
$b = $this->position->getWorld()->getBlockAt($x, $y, $z);
if(
!($b instanceof Dirt) ||
$b->isCoarse() ||
$this->position->getWorld()->getFullLightAt($x, $y + 1, $z) < 4 ||
!($b instanceof Dirt) or
$b->isCoarse() or
$this->position->getWorld()->getFullLightAt($x, $y + 1, $z) < 4 or
$this->position->getWorld()->getBlockAt($x, $y + 1, $z)->getLightFilter() >= 2
){
continue;
@ -98,16 +97,12 @@ class Grass extends Opaque{
return true;
}elseif($item instanceof Hoe){
$item->applyDamage(1);
$newBlock = VanillaBlocks::FARMLAND();
$this->position->getWorld()->addSound($this->position->add(0.5, 0.5, 0.5), new ItemUseOnBlockSound($newBlock));
$this->position->getWorld()->setBlock($this->position, $newBlock);
$this->position->getWorld()->setBlock($this->position, VanillaBlocks::FARMLAND());
return true;
}elseif($item instanceof Shovel && $this->getSide(Facing::UP)->getId() === BlockLegacyIds::AIR){
}elseif($item instanceof Shovel and $this->getSide(Facing::UP)->getId() === BlockLegacyIds::AIR){
$item->applyDamage(1);
$newBlock = VanillaBlocks::GRASS_PATH();
$this->position->getWorld()->addSound($this->position->add(0.5, 0.5, 0.5), new ItemUseOnBlockSound($newBlock));
$this->position->getWorld()->setBlock($this->position, $newBlock);
$this->position->getWorld()->setBlock($this->position, VanillaBlocks::GRASS_PATH());
return true;
}

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

@ -23,7 +23,6 @@ declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\event\block\BlockMeltEvent;
use pocketmine\item\enchantment\VanillaEnchantments;
use pocketmine\item\Item;
use pocketmine\player\Player;
@ -39,7 +38,7 @@ class Ice extends Transparent{
}
public function onBreak(Item $item, ?Player $player = null) : bool{
if(($player === null || $player->isSurvival()) && !$item->hasEnchantment(VanillaEnchantments::SILK_TOUCH())){
if(($player === null or $player->isSurvival()) and !$item->hasEnchantment(VanillaEnchantments::SILK_TOUCH())){
$this->position->getWorld()->setBlock($this->position, VanillaBlocks::WATER());
return true;
}
@ -52,11 +51,7 @@ class Ice extends Transparent{
public function onRandomTick() : void{
if($this->position->getWorld()->getHighestAdjacentBlockLight($this->position->x, $this->position->y, $this->position->z) >= 12){
$ev = new BlockMeltEvent($this, VanillaBlocks::WATER());
$ev->call();
if(!$ev->isCancelled()){
$this->position->getWorld()->setBlock($this->position, $ev->getNewState());
}
$this->position->getWorld()->useBreakOn($this->position);
}
}

View File

@ -86,7 +86,7 @@ class ItemFrame extends Flowable{
/** @return $this */
public function setFramedItem(?Item $item) : self{
if($item === null || $item->isNull()){
if($item === null or $item->isNull()){
$this->framedItem = null;
$this->itemRotation = 0;
}else{
@ -161,7 +161,7 @@ class ItemFrame extends Flowable{
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($face === Facing::DOWN || $face === Facing::UP || !$blockClicked->isSolid()){
if($face === Facing::DOWN or $face === Facing::UP or !$blockClicked->isSolid()){
return false;
}
@ -172,7 +172,7 @@ class ItemFrame extends Flowable{
public function getDropsForCompatibleTool(Item $item) : array{
$drops = parent::getDropsForCompatibleTool($item);
if($this->framedItem !== null && lcg_value() <= $this->itemDropChance){
if($this->framedItem !== null and lcg_value() <= $this->itemDropChance){
$drops[] = clone $this->framedItem;
}

View File

@ -65,7 +65,7 @@ class Ladder extends Transparent{
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if(!$blockClicked->isTransparent() && Facing::axis($face) !== Axis::Y){
if(!$blockClicked->isTransparent() and Facing::axis($face) !== Axis::Y){
$this->facing = $face;
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}

View File

@ -77,11 +77,11 @@ class Lantern extends Transparent{
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if(!$this->canAttachTo($this->position->getWorld()->getBlock($blockReplace->getPosition()->up())) && !$this->canAttachTo($this->position->getWorld()->getBlock($blockReplace->getPosition()->down()))){
if(!$this->canAttachTo($this->position->getWorld()->getBlock($blockReplace->getPosition()->up())) and !$this->canAttachTo($this->position->getWorld()->getBlock($blockReplace->getPosition()->down()))){
return false;
}
$this->hanging = ($face === Facing::DOWN || !$this->canAttachTo($this->position->getWorld()->getBlock($blockReplace->getPosition()->down())));
$this->hanging = ($face === Facing::DOWN or !$this->canAttachTo($this->position->getWorld()->getBlock($blockReplace->getPosition()->down())));
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}

View File

@ -91,6 +91,8 @@ class Lava extends Liquid{
}
public function onEntityInside(Entity $entity) : bool{
$entity->fallDistance *= 0.5;
$ev = new EntityDamageByBlockEvent($this, $entity, EntityDamageEvent::CAUSE_LAVA, 4);
$entity->attack($ev);

View File

@ -96,7 +96,7 @@ class Leaves extends Transparent{
return true;
}
if($block->getId() === $this->getId() && $distance <= 4){
if($block->getId() === $this->getId() and $distance <= 4){
foreach(Facing::ALL as $side){
if($this->findLog($pos->getSide($side), $visited, $distance + 1)){
return true;
@ -108,7 +108,7 @@ class Leaves extends Transparent{
}
public function onNearbyBlockChange() : void{
if(!$this->noDecay && !$this->checkDecay){
if(!$this->noDecay and !$this->checkDecay){
$this->checkDecay = true;
$this->position->getWorld()->setBlock($this->position, $this, false);
}
@ -119,10 +119,10 @@ class Leaves extends Transparent{
}
public function onRandomTick() : void{
if(!$this->noDecay && $this->checkDecay){
if(!$this->noDecay and $this->checkDecay){
$ev = new LeavesDecayEvent($this);
$ev->call();
if($ev->isCancelled() || $this->findLog($this->position)){
if($ev->isCancelled() or $this->findLog($this->position)){
$this->checkDecay = false;
$this->position->getWorld()->setBlock($this->position, $this, false);
}else{
@ -145,7 +145,7 @@ class Leaves extends Transparent{
if(mt_rand(1, 20) === 1){ //Saplings
$drops[] = ItemFactory::getInstance()->get(ItemIds::SAPLING, $this->treeType->getMagicNumber());
}
if(($this->treeType->equals(TreeType::OAK()) || $this->treeType->equals(TreeType::DARK_OAK())) && mt_rand(1, 200) === 1){ //Apples
if(($this->treeType->equals(TreeType::OAK()) or $this->treeType->equals(TreeType::DARK_OAK())) and mt_rand(1, 200) === 1){ //Apples
$drops[] = VanillaItems::APPLE();
}

View File

@ -1,166 +0,0 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\block\tile\Lectern as TileLectern;
use pocketmine\block\utils\BlockDataSerializer;
use pocketmine\block\utils\FacesOppositePlacingPlayerTrait;
use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\item\Item;
use pocketmine\item\WritableBookBase;
use pocketmine\math\AxisAlignedBB;
use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\sound\LecternPlaceBookSound;
use function count;
class Lectern extends Transparent{
use FacesOppositePlacingPlayerTrait;
use HorizontalFacingTrait;
protected int $viewedPage = 0;
protected ?WritableBookBase $book = null;
protected bool $producingSignal = false;
public function readStateFromData(int $id, int $stateMeta) : void{
$this->facing = BlockDataSerializer::readLegacyHorizontalFacing($stateMeta & 0x03);
$this->producingSignal = ($stateMeta & BlockLegacyMetadata::LECTERN_FLAG_POWERED) !== 0;
}
public function writeStateToMeta() : int{
return BlockDataSerializer::writeLegacyHorizontalFacing($this->facing) | ($this->producingSignal ? BlockLegacyMetadata::LECTERN_FLAG_POWERED : 0);
}
public function readStateFromWorld() : void{
parent::readStateFromWorld();
$tile = $this->position->getWorld()->getTile($this->position);
if($tile instanceof TileLectern){
$this->viewedPage = $tile->getViewedPage();
$this->book = $tile->getBook();
}
}
public function writeStateToWorld() : void{
parent::writeStateToWorld();
$tile = $this->position->getWorld()->getTile($this->position);
if($tile instanceof TileLectern){
$tile->setViewedPage($this->viewedPage);
$tile->setBook($this->book);
}
}
public function getStateBitmask() : int{
return 0b111;
}
public function getFlammability() : int{
return 30;
}
public function getDrops(Item $item) : array{
$drops = parent::getDrops($item);
if($this->book !== null){
$drops[] = clone $this->book;
}
return $drops;
}
protected function recalculateCollisionBoxes() : array{
return [AxisAlignedBB::one()->trim(Facing::UP, 0.1)];
}
public function isProducingSignal() : bool{ return $this->producingSignal; }
/** @return $this */
public function setProducingSignal(bool $producingSignal) : self{
$this->producingSignal = $producingSignal;
return $this;
}
public function getViewedPage() : int{
return $this->viewedPage;
}
/** @return $this */
public function setViewedPage(int $viewedPage) : self{
$this->viewedPage = $viewedPage;
return $this;
}
public function getBook() : ?WritableBookBase{
return $this->book !== null ? clone $this->book : null;
}
/** @return $this */
public function setBook(?WritableBookBase $book) : self{
$this->book = $book !== null && !$book->isNull() ? (clone $book)->setCount(1) : null;
$this->viewedPage = 0;
return $this;
}
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($this->book === null && $item instanceof WritableBookBase){
$this->position->getWorld()->setBlock($this->position, $this->setBook($item));
$this->position->getWorld()->addSound($this->position, new LecternPlaceBookSound());
$item->pop();
}
return true;
}
public function onAttack(Item $item, int $face, ?Player $player = null) : bool{
if($this->book !== null){
$this->position->getWorld()->dropItem($this->position->up(), $this->book);
$this->position->getWorld()->setBlock($this->position, $this->setBook(null));
}
return false;
}
public function onPageTurn(int $newPage) : bool{
if($newPage === $this->viewedPage){
return true;
}
if($this->book === null || $newPage >= count($this->book->getPages()) || $newPage < 0){
return false;
}
$this->viewedPage = $newPage;
if(!$this->producingSignal){
$this->producingSignal = true;
$this->position->getWorld()->scheduleDelayedBlockUpdate($this->position, 1);
}
$this->position->getWorld()->setBlock($this->position, $this);
return true;
}
public function onScheduledUpdate() : void{
if($this->producingSignal){
$this->producingSignal = false;
$this->position->getWorld()->setBlock($this->position, $this);
}
}
}

View File

@ -131,7 +131,7 @@ abstract class Liquid extends Transparent{
abstract public function getBucketEmptySound() : Sound;
public function isSource() : bool{
return !$this->falling && $this->decay === 0;
return !$this->falling and $this->decay === 0;
}
/**
@ -154,7 +154,7 @@ abstract class Liquid extends Transparent{
}
protected function getEffectiveFlowDecay(Block $block) : int{
if(!($block instanceof Liquid) || !$block->isSameType($this)){
if(!($block instanceof Liquid) or !$block->isSameType($this)){
return -1;
}
@ -279,7 +279,7 @@ abstract class Liquid extends Transparent{
$newDecay = $smallestFlowDecay + $multiplier;
$falling = false;
if($newDecay >= 8 || $smallestFlowDecay < 0){
if($newDecay >= 8 or $smallestFlowDecay < 0){
$newDecay = -1;
}
@ -290,14 +290,14 @@ abstract class Liquid extends Transparent{
$minAdjacentSources = $this->getMinAdjacentSourcesToFormSource();
if($minAdjacentSources !== null && $this->adjacentSources >= $minAdjacentSources){
$bottomBlock = $world->getBlockAt($this->position->x, $this->position->y - 1, $this->position->z);
if($bottomBlock->isSolid() || ($bottomBlock instanceof Liquid && $bottomBlock->isSameType($this) && $bottomBlock->isSource())){
if($bottomBlock->isSolid() or ($bottomBlock instanceof Liquid and $bottomBlock->isSameType($this) and $bottomBlock->isSource())){
$newDecay = 0;
$falling = false;
}
}
if($falling !== $this->falling || (!$falling && $newDecay !== $this->decay)){
if(!$falling && $newDecay < 0){
if($falling !== $this->falling or (!$falling and $newDecay !== $this->decay)){
if(!$falling and $newDecay < 0){
$world->setBlock($this->position, VanillaBlocks::AIR());
return;
}
@ -312,7 +312,7 @@ abstract class Liquid extends Transparent{
$this->flowIntoBlock($bottomBlock, 0, true);
if($this->isSource() || !$bottomBlock->canBeFlowedInto()){
if($this->isSource() or !$bottomBlock->canBeFlowedInto()){
if($this->falling){
$adjacentDecay = 1; //falling liquid behaves like source block
}else{
@ -331,7 +331,7 @@ abstract class Liquid extends Transparent{
}
protected function flowIntoBlock(Block $block, int $newFlowDecay, bool $falling) : void{
if($this->canFlowInto($block) && !($block instanceof Liquid)){
if($this->canFlowInto($block) and !($block instanceof Liquid)){
$new = clone $this;
$new->falling = $falling;
$new->decay = $falling ? 0 : $newFlowDecay;
@ -350,7 +350,7 @@ abstract class Liquid extends Transparent{
/** @phpstan-impure */
private function getSmallestFlowDecay(Block $block, int $decay) : int{
if(!($block instanceof Liquid) || !$block->isSameType($this)){
if(!($block instanceof Liquid) or !$block->isSameType($this)){
return $decay;
}
@ -381,8 +381,8 @@ abstract class Liquid extends Transparent{
protected function canFlowInto(Block $block) : bool{
return
$this->position->getWorld()->isInWorld($block->position->x, $block->position->y, $block->position->z) &&
$block->canBeFlowedInto() &&
!($block instanceof Liquid && $block->isSource()); //TODO: I think this should only be liquids of the same type
$this->position->getWorld()->isInWorld($block->position->x, $block->position->y, $block->position->z) and
$block->canBeFlowedInto() and
!($block instanceof Liquid and $block->isSource()); //TODO: I think this should only be liquids of the same type
}
}

View File

@ -39,7 +39,7 @@ class Magma extends Opaque{
}
public function onEntityInside(Entity $entity) : bool{
if($entity instanceof Living && !$entity->isSneaking()){
if($entity instanceof Living and !$entity->isSneaking()){
$ev = new EntityDamageByBlockEvent($this, $entity, EntityDamageEvent::CAUSE_FIRE, 1);
$entity->attack($ev);
}

View File

@ -53,7 +53,7 @@ class NetherPortal extends Transparent{
* @return $this
*/
public function setAxis(int $axis) : self{
if($axis !== Axis::X && $axis !== Axis::Z){
if($axis !== Axis::X and $axis !== Axis::Z){
throw new \InvalidArgumentException("Invalid axis");
}
$this->axis = $axis;

View File

@ -79,7 +79,7 @@ class NetherWartPlant extends Flowable{
}
public function onRandomTick() : void{
if($this->age < 3 && mt_rand(0, 10) === 0){ //Still growing
if($this->age < 3 and mt_rand(0, 10) === 0){ //Still growing
$block = clone $this;
$block->age++;
$ev = new BlockGrowEvent($this, $block);

View File

@ -59,7 +59,7 @@ class Note extends Opaque{
/** @return $this */
public function setPitch(int $pitch) : self{
if($pitch < self::MIN_PITCH || $pitch > self::MAX_PITCH){
if($pitch < self::MIN_PITCH or $pitch > self::MAX_PITCH){
throw new \InvalidArgumentException("Pitch must be in range " . self::MIN_PITCH . " - " . self::MAX_PITCH);
}
$this->pitch = $pitch;

View File

@ -1,45 +0,0 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\item\Shears;
use pocketmine\item\VanillaItems;
use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use function in_array;
class Pumpkin extends Opaque{
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($item instanceof Shears && in_array($face, Facing::HORIZONTAL, true)){
$item->applyDamage(1);
$this->position->getWorld()->setBlock($this->position, VanillaBlocks::CARVED_PUMPKIN()->setFacing($face));
$this->position->getWorld()->dropItem($this->position->add(0.5, 0.5, 0.5), VanillaItems::PUMPKIN_SEEDS()->setCount(1));
return true;
}
return false;
}
}

View File

@ -57,7 +57,7 @@ class RedstoneComparator extends Flowable{
public function readStateFromData(int $id, int $stateMeta) : void{
$this->facing = BlockDataSerializer::readLegacyHorizontalFacing($stateMeta & 0x03);
$this->isSubtractMode = ($stateMeta & BlockLegacyMetadata::REDSTONE_COMPARATOR_FLAG_SUBTRACT) !== 0;
$this->powered = ($id === $this->idInfoFlattened->getSecondId() || ($stateMeta & BlockLegacyMetadata::REDSTONE_COMPARATOR_FLAG_POWERED) !== 0);
$this->powered = ($id === $this->idInfoFlattened->getSecondId() or ($stateMeta & BlockLegacyMetadata::REDSTONE_COMPARATOR_FLAG_POWERED) !== 0);
}
public function writeStateToMeta() : int{

View File

@ -68,7 +68,7 @@ class Sapling extends Flowable{
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
$down = $this->getSide(Facing::DOWN);
if($down->getId() === BlockLegacyIds::GRASS || $down->getId() === BlockLegacyIds::DIRT || $down->getId() === BlockLegacyIds::FARMLAND){
if($down->getId() === BlockLegacyIds::GRASS or $down->getId() === BlockLegacyIds::DIRT or $down->getId() === BlockLegacyIds::FARMLAND){
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}
@ -96,7 +96,7 @@ class Sapling extends Flowable{
}
public function onRandomTick() : void{
if($this->position->getWorld()->getFullLightAt($this->position->getFloorX(), $this->position->getFloorY(), $this->position->getFloorZ()) >= 8 && mt_rand(1, 7) === 1){
if($this->position->getWorld()->getFullLightAt($this->position->getFloorX(), $this->position->getFloorY(), $this->position->getFloorZ()) >= 8 and mt_rand(1, 7) === 1){
if($this->ready){
$this->grow(null);
}else{

View File

@ -83,12 +83,12 @@ class SeaPickle extends Transparent{
public function canBePlacedAt(Block $blockReplace, Vector3 $clickVector, int $face, bool $isClickedBlock) : bool{
//TODO: proper placement logic (needs a supporting face below)
return ($blockReplace instanceof SeaPickle && $blockReplace->count < 4) || parent::canBePlacedAt($blockReplace, $clickVector, $face, $isClickedBlock);
return ($blockReplace instanceof SeaPickle and $blockReplace->count < 4) or parent::canBePlacedAt($blockReplace, $clickVector, $face, $isClickedBlock);
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
$this->underwater = false; //TODO: implement this once we have new water logic in place
if($blockReplace instanceof SeaPickle && $blockReplace->count < 4){
if($blockReplace instanceof SeaPickle and $blockReplace->count < 4){
$this->count = $blockReplace->count + 1;
}

View File

@ -91,7 +91,7 @@ class ShulkerBox extends Opaque{
$shulker = $this->position->getWorld()->getTile($this->position);
if($shulker instanceof TileShulkerBox){
if(
$this->getSide($this->facing)->getId() !== BlockLegacyIds::AIR ||
$this->getSide($this->facing)->getId() !== BlockLegacyIds::AIR or
!$shulker->canOpenWith($item->getCustomName())
){
return true;

View File

@ -140,7 +140,7 @@ class Skull extends Flowable{
}
$this->facing = $face;
if($player !== null && $face === Facing::UP){
if($player !== null and $face === Facing::UP){
$this->rotation = ((int) floor(($player->getLocation()->getYaw() * 16 / 360) + 0.5)) & 0xf;
}
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);

View File

@ -90,11 +90,11 @@ class Slab extends Transparent{
return true;
}
if($blockReplace instanceof Slab && !$blockReplace->slabType->equals(SlabType::DOUBLE()) && $blockReplace->isSameType($this)){
if($blockReplace instanceof Slab and !$blockReplace->slabType->equals(SlabType::DOUBLE()) and $blockReplace->isSameType($this)){
if($blockReplace->slabType->equals(SlabType::TOP())){ //Trying to combine with top slab
return $clickVector->y <= 0.5 || (!$isClickedBlock && $face === Facing::UP);
return $clickVector->y <= 0.5 or (!$isClickedBlock and $face === Facing::UP);
}else{
return $clickVector->y >= 0.5 || (!$isClickedBlock && $face === Facing::DOWN);
return $clickVector->y >= 0.5 or (!$isClickedBlock and $face === Facing::DOWN);
}
}
@ -102,9 +102,9 @@ class Slab extends Transparent{
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($blockReplace instanceof Slab && !$blockReplace->slabType->equals(SlabType::DOUBLE()) && $blockReplace->isSameType($this) && (
($blockReplace->slabType->equals(SlabType::TOP()) && ($clickVector->y <= 0.5 || $face === Facing::UP)) ||
($blockReplace->slabType->equals(SlabType::BOTTOM()) && ($clickVector->y >= 0.5 || $face === Facing::DOWN))
if($blockReplace instanceof Slab and !$blockReplace->slabType->equals(SlabType::DOUBLE()) and $blockReplace->isSameType($this) and (
($blockReplace->slabType->equals(SlabType::TOP()) and ($clickVector->y <= 0.5 or $face === Facing::UP)) or
($blockReplace->slabType->equals(SlabType::BOTTOM()) and ($clickVector->y >= 0.5 or $face === Facing::DOWN))
)){
//Clicked in empty half of existing slab
$this->slabType = SlabType::DOUBLE();

View File

@ -26,7 +26,6 @@ namespace pocketmine\block;
use pocketmine\block\utils\BlockDataSerializer;
use pocketmine\block\utils\Fallable;
use pocketmine\block\utils\FallableTrait;
use pocketmine\event\block\BlockMeltEvent;
use pocketmine\item\Item;
use pocketmine\item\VanillaItems;
use pocketmine\math\AxisAlignedBB;
@ -78,7 +77,7 @@ class SnowLayer extends Flowable implements Fallable{
}
private function canBeSupportedBy(Block $b) : bool{
return $b->isSolid() || ($b instanceof SnowLayer && $b->isSameType($this) && $b->layers === 8);
return $b->isSolid() or ($b instanceof SnowLayer and $b->isSameType($this) and $b->layers === 8);
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
@ -101,11 +100,7 @@ class SnowLayer extends Flowable implements Fallable{
public function onRandomTick() : void{
if($this->position->getWorld()->getBlockLightAt($this->position->x, $this->position->y, $this->position->z) >= 12){
$ev = new BlockMeltEvent($this, VanillaBlocks::AIR());
$ev->call();
if(!$ev->isCancelled()){
$this->position->getWorld()->setBlock($this->position, $ev->getNewState());
}
$this->position->getWorld()->setBlock($this->position, VanillaBlocks::AIR(), false);
}
}

View File

@ -96,9 +96,9 @@ class Stair extends Transparent{
->trim(Facing::opposite($topStepFace), 0.5)
->trim(Facing::opposite($this->facing), 0.5);
if($this->shape->equals(StairShape::OUTER_LEFT()) || $this->shape->equals(StairShape::OUTER_RIGHT())){
if($this->shape->equals(StairShape::OUTER_LEFT()) or $this->shape->equals(StairShape::OUTER_RIGHT())){
$topStep->trim(Facing::rotateY($this->facing, $this->shape->equals(StairShape::OUTER_LEFT())), 0.5);
}elseif($this->shape->equals(StairShape::INNER_LEFT()) || $this->shape->equals(StairShape::INNER_RIGHT())){
}elseif($this->shape->equals(StairShape::INNER_LEFT()) or $this->shape->equals(StairShape::INNER_RIGHT())){
//add an extra cube
$bbs[] = AxisAlignedBB::one()
->trim(Facing::opposite($topStepFace), 0.5)
@ -114,8 +114,8 @@ class Stair extends Transparent{
private function getPossibleCornerFacing(bool $oppositeFacing) : ?int{
$side = $this->getSide($oppositeFacing ? Facing::opposite($this->facing) : $this->facing);
return (
$side instanceof Stair &&
$side->upsideDown === $this->upsideDown &&
$side instanceof Stair and
$side->upsideDown === $this->upsideDown and
Facing::axis($side->facing) !== Facing::axis($this->facing) //perpendicular
) ? $side->facing : null;
}
@ -124,7 +124,7 @@ class Stair extends Transparent{
if($player !== null){
$this->facing = $player->getHorizontalFacing();
}
$this->upsideDown = (($clickVector->y > 0.5 && $face !== Facing::UP) || $face === Facing::DOWN);
$this->upsideDown = (($clickVector->y > 0.5 and $face !== Facing::UP) or $face === Facing::DOWN);
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}

View File

@ -53,7 +53,7 @@ abstract class Stem extends Crops{
$side = $this->getSide(Facing::HORIZONTAL[array_rand(Facing::HORIZONTAL)]);
$d = $side->getSide(Facing::DOWN);
if($side->getId() === BlockLegacyIds::AIR && ($d->getId() === BlockLegacyIds::FARMLAND || $d->getId() === BlockLegacyIds::GRASS || $d->getId() === BlockLegacyIds::DIRT)){
if($side->getId() === BlockLegacyIds::AIR and ($d->getId() === BlockLegacyIds::FARMLAND or $d->getId() === BlockLegacyIds::GRASS or $d->getId() === BlockLegacyIds::DIRT)){
$ev = new BlockGrowEvent($side, $grow);
$ev->call();
if(!$ev->isCancelled()){

View File

@ -97,7 +97,7 @@ class Sugarcane extends Flowable{
public function onNearbyBlockChange() : void{
$down = $this->getSide(Facing::DOWN);
if($down->isTransparent() && !$down->isSameType($this)){
if($down->isTransparent() and !$down->isSameType($this)){
$this->position->getWorld()->useBreakOn($this->position);
}
}
@ -121,7 +121,7 @@ class Sugarcane extends Flowable{
$down = $this->getSide(Facing::DOWN);
if($down->isSameType($this)){
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}elseif($down->getId() === BlockLegacyIds::GRASS || $down->getId() === BlockLegacyIds::DIRT || $down->getId() === BlockLegacyIds::SAND || $down->getId() === BlockLegacyIds::PODZOL){
}elseif($down->getId() === BlockLegacyIds::GRASS or $down->getId() === BlockLegacyIds::DIRT or $down->getId() === BlockLegacyIds::SAND or $down->getId() === BlockLegacyIds::PODZOL){
foreach(Facing::HORIZONTAL as $side){
if($down->getSide($side) instanceof Water){
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);

View File

@ -135,7 +135,7 @@ class SweetBerryBush extends Flowable{
}
public function onRandomTick() : void{
if($this->age < self::STAGE_MATURE && mt_rand(0, 2) === 1){
if($this->age < self::STAGE_MATURE and mt_rand(0, 2) === 1){
$block = clone $this;
++$block->age;
$ev = new BlockGrowEvent($this, $block);

View File

@ -86,7 +86,7 @@ class TNT extends Opaque{
}
public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($item instanceof FlintSteel || $item->hasEnchantment(VanillaEnchantments::FIRE_ASPECT())){
if($item instanceof FlintSteel or $item->hasEnchantment(VanillaEnchantments::FIRE_ASPECT())){
if($item instanceof Durable){
$item->applyDamage(1);
}
@ -102,7 +102,7 @@ class TNT extends Opaque{
}
public function onEntityInside(Entity $entity) : bool{
if($entity instanceof Arrow && $entity->isOnFire()){
if($entity instanceof Arrow and $entity->isOnFire()){
$this->ignite();
return false;
}

View File

@ -39,7 +39,7 @@ class TallGrass extends Flowable{
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
$down = $this->getSide(Facing::DOWN)->getId();
if($down === BlockLegacyIds::GRASS || $down === BlockLegacyIds::DIRT){
if($down === BlockLegacyIds::GRASS or $down === BlockLegacyIds::DIRT){
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}

View File

@ -37,7 +37,7 @@ class Thin extends Transparent{
foreach(Facing::HORIZONTAL as $facing){
$side = $this->getSide($facing);
if($side instanceof Thin || $side->isFullCube()){
if($side instanceof Thin or $side->isFullCube()){
$this->connections[$facing] = true;
}else{
unset($this->connections[$facing]);
@ -51,7 +51,7 @@ class Thin extends Transparent{
/** @var AxisAlignedBB[] $bbs */
$bbs = [];
if(isset($this->connections[Facing::WEST]) || isset($this->connections[Facing::EAST])){
if(isset($this->connections[Facing::WEST]) or isset($this->connections[Facing::EAST])){
$bb = AxisAlignedBB::one()->squash(Axis::Z, $inset);
if(!isset($this->connections[Facing::WEST])){
@ -62,7 +62,7 @@ class Thin extends Transparent{
$bbs[] = $bb;
}
if(isset($this->connections[Facing::NORTH]) || isset($this->connections[Facing::SOUTH])){
if(isset($this->connections[Facing::NORTH]) or isset($this->connections[Facing::SOUTH])){
$bb = AxisAlignedBB::one()->squash(Axis::X, $inset);
if(!isset($this->connections[Facing::NORTH])){

View File

@ -66,16 +66,16 @@ class Torch extends Flowable{
$below = $this->getSide(Facing::DOWN);
$face = Facing::opposite($this->facing);
if($this->getSide($face)->isTransparent() && !($face === Facing::DOWN && ($below->getId() === BlockLegacyIds::FENCE || $below->getId() === BlockLegacyIds::COBBLESTONE_WALL))){
if($this->getSide($face)->isTransparent() and !($face === Facing::DOWN and ($below->getId() === BlockLegacyIds::FENCE or $below->getId() === BlockLegacyIds::COBBLESTONE_WALL))){
$this->position->getWorld()->useBreakOn($this->position);
}
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if($blockClicked->canBeReplaced() && !$blockClicked->getSide(Facing::DOWN)->isTransparent()){
if($blockClicked->canBeReplaced() and !$blockClicked->getSide(Facing::DOWN)->isTransparent()){
$this->facing = Facing::UP;
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}elseif($face !== Facing::DOWN && (!$blockClicked->isTransparent() || ($face === Facing::UP && ($blockClicked->getId() === BlockLegacyIds::FENCE || $blockClicked->getId() === BlockLegacyIds::COBBLESTONE_WALL)))){
}elseif($face !== Facing::DOWN and (!$blockClicked->isTransparent() or ($face === Facing::UP and ($blockClicked->getId() === BlockLegacyIds::FENCE or $blockClicked->getId() === BlockLegacyIds::COBBLESTONE_WALL)))){
$this->facing = $face;
return parent::place($tx, $item, $blockReplace, $blockClicked, $face, $clickVector, $player);
}else{

View File

@ -82,7 +82,7 @@ class Trapdoor extends Transparent{
if($player !== null){
$this->facing = Facing::opposite($player->getHorizontalFacing());
}
if(($clickVector->y > 0.5 && $face !== Facing::UP) || $face === Facing::DOWN){
if(($clickVector->y > 0.5 and $face !== Facing::UP) or $face === Facing::DOWN){
$this->top = true;
}

View File

@ -363,7 +363,6 @@ use pocketmine\utils\CloningRegistryTrait;
* @method static LapisOre LAPIS_LAZULI_ORE()
* @method static DoubleTallGrass LARGE_FERN()
* @method static Lava LAVA()
* @method static Lectern LECTERN()
* @method static Opaque LEGACY_STONECUTTER()
* @method static Lever LEVER()
* @method static GlazedTerracotta LIGHT_BLUE_GLAZED_TERRACOTTA()
@ -446,7 +445,7 @@ use pocketmine\utils\CloningRegistryTrait;
* @method static Slab PRISMARINE_SLAB()
* @method static Stair PRISMARINE_STAIRS()
* @method static Wall PRISMARINE_WALL()
* @method static Pumpkin PUMPKIN()
* @method static Opaque PUMPKIN()
* @method static PumpkinStem PUMPKIN_STEM()
* @method static GlazedTerracotta PURPLE_GLAZED_TERRACOTTA()
* @method static Torch PURPLE_TORCH()
@ -925,7 +924,6 @@ final class VanillaBlocks{
self::register("lapis_lazuli_ore", $factory->get(21, 0));
self::register("large_fern", $factory->get(175, 3));
self::register("lava", $factory->get(10, 0));
self::register("lectern", $factory->get(449, 0));
self::register("legacy_stonecutter", $factory->get(245, 0));
self::register("lever", $factory->get(69, 0));
self::register("light_blue_glazed_terracotta", $factory->get(223, 2));

View File

@ -116,7 +116,7 @@ class Vine extends Flowable{
}
public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{
if(!$blockClicked->isSolid() || Facing::axis($face) === Axis::Y){
if(!$blockClicked->isSolid() or Facing::axis($face) === Axis::Y){
return false;
}
@ -134,7 +134,7 @@ class Vine extends Flowable{
$supportedFaces = $up instanceof Vine ? array_intersect_key($this->faces, $up->faces) : [];
foreach($this->faces as $face){
if(!isset($supportedFaces[$face]) && !$this->getSide($face)->isSolid()){
if(!isset($supportedFaces[$face]) and !$this->getSide($face)->isSolid()){
unset($this->faces[$face]);
$changed = true;
}

View File

@ -37,7 +37,7 @@ class Wall extends Transparent{
foreach(Facing::HORIZONTAL as $facing){
$block = $this->getSide($facing);
if($block instanceof static || $block instanceof FenceGate || ($block->isSolid() && !$block->isTransparent())){
if($block instanceof static or $block instanceof FenceGate or ($block->isSolid() and !$block->isTransparent())){
$this->connections[$facing] = $facing;
}else{
unset($this->connections[$facing]);
@ -57,10 +57,10 @@ class Wall extends Transparent{
$inset = 0.25;
if(
!$this->up && //if there is a block on top, it stays as a post
!$this->up and //if there is a block on top, it stays as a post
(
($north && $south && !$west && !$east) ||
(!$north && !$south && $west && $east)
($north and $south and !$west and !$east) or
(!$north and !$south and $west and $east)
)
){
//If connected to two sides on the same axis but not any others, AND there is not a block on top, there is no post and the wall is thinner

View File

@ -47,7 +47,7 @@ trait AnimatedBlockInventoryTrait{
public function onOpen(Player $who) : void{
parent::onOpen($who);
if($this->getHolder()->isValid() && $this->getViewerCount() === 1){
if($this->getHolder()->isValid() and $this->getViewerCount() === 1){
//TODO: this crap really shouldn't be managed by the inventory
$this->animateBlock(true);
$this->getHolder()->getWorld()->addSound($this->getHolder()->add(0.5, 0.5, 0.5), $this->getOpenSound());
@ -57,7 +57,7 @@ trait AnimatedBlockInventoryTrait{
abstract protected function animateBlock(bool $isOpen) : void;
public function onClose(Player $who) : void{
if($this->getHolder()->isValid() && $this->getViewerCount() === 1){
if($this->getHolder()->isValid() and $this->getViewerCount() === 1){
//TODO: this crap really shouldn't be managed by the inventory
$this->animateBlock(false);
$this->getHolder()->getWorld()->addSound($this->getHolder()->add(0.5, 0.5, 0.5), $this->getCloseSound());

View File

@ -60,12 +60,12 @@ class Chest extends Spawnable implements Container, Nameable{
}
public function readSaveData(CompoundTag $nbt) : void{
if(($pairXTag = $nbt->getTag(self::TAG_PAIRX)) instanceof IntTag && ($pairZTag = $nbt->getTag(self::TAG_PAIRZ)) instanceof IntTag){
if(($pairXTag = $nbt->getTag(self::TAG_PAIRX)) instanceof IntTag and ($pairZTag = $nbt->getTag(self::TAG_PAIRZ)) instanceof IntTag){
$pairX = $pairXTag->getValue();
$pairZ = $pairZTag->getValue();
if(
($this->position->x === $pairX && abs($this->position->z - $pairZ) === 1) ||
($this->position->z === $pairZ && abs($this->position->x - $pairX) === 1)
($this->position->x === $pairX and abs($this->position->z - $pairZ) === 1) or
($this->position->z === $pairZ and abs($this->position->x - $pairX) === 1)
){
$this->pairX = $pairX;
$this->pairZ = $pairZ;
@ -100,7 +100,7 @@ class Chest extends Spawnable implements Container, Nameable{
$this->inventory->removeAllViewers();
if($this->doubleInventory !== null){
if($this->isPaired() && $this->position->getWorld()->isChunkLoaded($this->pairX >> Chunk::COORD_BIT_SIZE, $this->pairZ >> Chunk::COORD_BIT_SIZE)){
if($this->isPaired() and $this->position->getWorld()->isChunkLoaded($this->pairX >> Chunk::COORD_BIT_SIZE, $this->pairZ >> Chunk::COORD_BIT_SIZE)){
$this->doubleInventory->removeAllViewers();
if(($pair = $this->getPair()) !== null){
$pair->doubleInventory = null;
@ -122,7 +122,7 @@ class Chest extends Spawnable implements Container, Nameable{
* @return ChestInventory|DoubleChestInventory
*/
public function getInventory(){
if($this->isPaired() && $this->doubleInventory === null){
if($this->isPaired() and $this->doubleInventory === null){
$this->checkPairing();
}
return $this->doubleInventory instanceof DoubleChestInventory ? $this->doubleInventory : $this->inventory;
@ -136,7 +136,7 @@ class Chest extends Spawnable implements Container, Nameable{
}
protected function checkPairing() : void{
if($this->isPaired() && !$this->position->getWorld()->isInLoadedTerrain(new Vector3($this->pairX, $this->position->y, $this->pairZ))){
if($this->isPaired() and !$this->position->getWorld()->isInLoadedTerrain(new Vector3($this->pairX, $this->position->y, $this->pairZ))){
//paired to a tile in an unloaded chunk
$this->doubleInventory = null;
@ -167,7 +167,7 @@ class Chest extends Spawnable implements Container, Nameable{
}
public function isPaired() : bool{
return $this->pairX !== null && $this->pairZ !== null;
return $this->pairX !== null and $this->pairZ !== null;
}
public function getPair() : ?Chest{
@ -182,7 +182,7 @@ class Chest extends Spawnable implements Container, Nameable{
}
public function pairWith(Chest $tile) : bool{
if($this->isPaired() || $tile->isPaired()){
if($this->isPaired() or $tile->isPaired()){
return false;
}

View File

@ -81,7 +81,7 @@ trait ContainerTrait{
* @see Container::canOpenWith()
*/
public function canOpenWith(string $key) : bool{
return $this->lock === null || $this->lock === $key;
return $this->lock === null or $this->lock === $key;
}
/**

View File

@ -42,7 +42,7 @@ class FlowerPot extends Spawnable{
private $plant = null;
public function readSaveData(CompoundTag $nbt) : void{
if(($itemIdTag = $nbt->getTag(self::TAG_ITEM)) instanceof ShortTag && ($itemMetaTag = $nbt->getTag(self::TAG_ITEM_DATA)) instanceof IntTag){
if(($itemIdTag = $nbt->getTag(self::TAG_ITEM)) instanceof ShortTag and ($itemMetaTag = $nbt->getTag(self::TAG_ITEM_DATA)) instanceof IntTag){
try{
$this->setPlant(BlockFactory::getInstance()->get($itemIdTag->getValue(), $itemMetaTag->getValue()));
}catch(\InvalidArgumentException $e){
@ -65,7 +65,7 @@ class FlowerPot extends Spawnable{
}
public function setPlant(?Block $plant) : void{
if($plant === null || $plant instanceof Air){
if($plant === null or $plant instanceof Air){
$this->plant = null;
}else{
$this->plant = clone $plant;

View File

@ -132,14 +132,14 @@ abstract class Furnace extends Spawnable implements Container, Nameable{
$this->maxFuelTime = $this->remainingFuelTime = $ev->getBurnTime();
$this->onStartSmelting();
if($this->remainingFuelTime > 0 && $ev->isBurning()){
if($this->remainingFuelTime > 0 and $ev->isBurning()){
$this->inventory->setFuel($fuel->getFuelResidue());
}
}
protected function onStartSmelting() : void{
$block = $this->getBlock();
if($block instanceof BlockFurnace && !$block->isLit()){
if($block instanceof BlockFurnace and !$block->isLit()){
$block->setLit(true);
$this->position->getWorld()->setBlock($block->getPosition(), $block);
}
@ -147,7 +147,7 @@ abstract class Furnace extends Spawnable implements Container, Nameable{
protected function onStopSmelting() : void{
$block = $this->getBlock();
if($block instanceof BlockFurnace && $block->isLit()){
if($block instanceof BlockFurnace and $block->isLit()){
$block->setLit(false);
$this->position->getWorld()->setBlock($block->getPosition(), $block);
}
@ -175,16 +175,16 @@ abstract class Furnace extends Spawnable implements Container, Nameable{
$furnaceType = $this->getFurnaceType();
$smelt = $this->position->getWorld()->getServer()->getCraftingManager()->getFurnaceRecipeManager($furnaceType)->match($raw);
$canSmelt = ($smelt instanceof FurnaceRecipe && $raw->getCount() > 0 && (($smelt->getResult()->equals($product) && $product->getCount() < $product->getMaxStackSize()) || $product->isNull()));
$canSmelt = ($smelt instanceof FurnaceRecipe and $raw->getCount() > 0 and (($smelt->getResult()->equals($product) and $product->getCount() < $product->getMaxStackSize()) or $product->isNull()));
if($this->remainingFuelTime <= 0 && $canSmelt && $fuel->getFuelTime() > 0 && $fuel->getCount() > 0){
if($this->remainingFuelTime <= 0 and $canSmelt and $fuel->getFuelTime() > 0 and $fuel->getCount() > 0){
$this->checkFuel($fuel);
}
if($this->remainingFuelTime > 0){
--$this->remainingFuelTime;
if($smelt instanceof FurnaceRecipe && $canSmelt){
if($smelt instanceof FurnaceRecipe and $canSmelt){
++$this->cookTime;
if($this->cookTime >= $furnaceType->getCookDurationTicks()){

View File

@ -24,7 +24,7 @@ declare(strict_types=1);
namespace pocketmine\block\tile;
use pocketmine\item\Item;
use pocketmine\item\VanillaItems;
use pocketmine\item\ItemFactory;
use pocketmine\math\Vector3;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\world\World;
@ -46,7 +46,7 @@ class ItemFrame extends Spawnable{
private $itemDropChance = 1.0;
public function __construct(World $world, Vector3 $pos){
$this->item = VanillaItems::AIR();
$this->item = ItemFactory::air();
parent::__construct($world, $pos);
}
@ -73,10 +73,10 @@ class ItemFrame extends Spawnable{
}
public function setItem(?Item $item) : void{
if($item !== null && !$item->isNull()){
if($item !== null and !$item->isNull()){
$this->item = clone $item;
}else{
$this->item = VanillaItems::AIR();
$this->item = ItemFactory::air();
}
}

View File

@ -1,87 +0,0 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\block\tile;
use pocketmine\item\Item;
use pocketmine\item\WritableBookBase;
use pocketmine\nbt\tag\CompoundTag;
use function count;
/**
* @deprecated
* @see \pocketmine\block\Lectern
*/
class Lectern extends Spawnable{
public const TAG_HAS_BOOK = "hasBook";
public const TAG_PAGE = "page";
public const TAG_TOTAL_PAGES = "totalPages";
public const TAG_BOOK = "book";
private int $viewedPage = 0;
private ?WritableBookBase $book = null;
public function readSaveData(CompoundTag $nbt) : void{
$this->viewedPage = $nbt->getInt(self::TAG_PAGE, 0);
if(($itemTag = $nbt->getCompoundTag(self::TAG_BOOK)) !== null){
$book = Item::nbtDeserialize($itemTag);
if($book instanceof WritableBookBase && !$book->isNull()){
$this->book = $book;
}
}
}
protected function writeSaveData(CompoundTag $nbt) : void{
$nbt->setByte(self::TAG_HAS_BOOK, $this->book !== null ? 1 : 0);
$nbt->setInt(self::TAG_PAGE, $this->viewedPage);
if($this->book !== null){
$nbt->setTag(self::TAG_BOOK, $this->book->nbtSerialize());
$nbt->setInt(self::TAG_TOTAL_PAGES, count($this->book->getPages()));
}
}
public function getViewedPage() : int{
return $this->viewedPage;
}
public function setViewedPage(int $viewedPage) : void{
$this->viewedPage = $viewedPage;
}
public function getBook() : ?WritableBookBase{
return $this->book !== null ? clone $this->book : null;
}
public function setBook(?WritableBookBase $book) : void{
$this->book = $book !== null && !$book->isNull() ? clone $book : null;
}
protected function addAdditionalSpawnData(CompoundTag $nbt) : void{
$nbt->setByte(self::TAG_HAS_BOOK, $this->book !== null ? 1 : 0);
$nbt->setInt(self::TAG_PAGE, $this->viewedPage);
if($this->book !== null){
$nbt->setTag(self::TAG_BOOK, $this->book->nbtSerialize());
$nbt->setInt(self::TAG_TOTAL_PAGES, count($this->book->getPages()));
}
}
}

View File

@ -34,7 +34,7 @@ class Note extends Tile{
private $pitch = 0;
public function readSaveData(CompoundTag $nbt) : void{
if(($pitch = $nbt->getByte("note", $this->pitch)) > BlockNote::MIN_PITCH && $pitch <= BlockNote::MAX_PITCH){
if(($pitch = $nbt->getByte("note", $this->pitch)) > BlockNote::MIN_PITCH and $pitch <= BlockNote::MAX_PITCH){
$this->pitch = $pitch;
}
}
@ -48,7 +48,7 @@ class Note extends Tile{
}
public function setPitch(int $pitch) : void{
if($pitch < BlockNote::MIN_PITCH || $pitch > BlockNote::MAX_PITCH){
if($pitch < BlockNote::MIN_PITCH or $pitch > BlockNote::MAX_PITCH){
throw new \InvalidArgumentException("Pitch must be in range " . BlockNote::MIN_PITCH . " - " . BlockNote::MAX_PITCH);
}
$this->pitch = $pitch;

View File

@ -59,7 +59,7 @@ class Skull extends Spawnable{
}
}
$rotation = $nbt->getByte(self::TAG_ROT, 0);
if($rotation >= 0 && $rotation <= 15){
if($rotation >= 0 and $rotation <= 15){
$this->skullRotation = $rotation;
}
}

View File

@ -67,7 +67,6 @@ final class TileFactory{
$this->register(Hopper::class, ["Hopper", "minecraft:hopper"]);
$this->register(ItemFrame::class, ["ItemFrame"]); //this is an entity in PC
$this->register(Jukebox::class, ["Jukebox", "RecordPlayer", "minecraft:jukebox"]);
$this->register(Lectern::class, ["Lectern", "minecraft:lectern"]);
$this->register(MonsterSpawner::class, ["MobSpawner", "minecraft:mob_spawner"]);
$this->register(Note::class, ["Music", "minecraft:noteblock"]);
$this->register(ShulkerBox::class, ["ShulkerBox", "minecraft:shulker_box"]);
@ -86,6 +85,7 @@ final class TileFactory{
//TODO: EndGateway
//TODO: EndPortal
//TODO: JigsawBlock
//TODO: Lectern
//TODO: MovingBlock
//TODO: NetherReactor
//TODO: PistonArm

View File

@ -150,7 +150,7 @@ final class BlockDataSerializer{
}
public static function readBoundedInt(string $name, int $v, int $min, int $max) : int{
if($v < $min || $v > $max){
if($v < $min or $v > $max){
throw new InvalidBlockStateException("$name should be in range $min - $max, got $v");
}
return $v;

View File

@ -1,46 +0,0 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\block\utils;
trait CoralTypeTrait{
protected CoralType $coralType;
protected bool $dead = false;
public function getCoralType() : CoralType{ return $this->coralType; }
/** @return $this */
public function setCoralType(CoralType $coralType) : self{
$this->coralType = $coralType;
return $this;
}
public function isDead() : bool{ return $this->dead; }
/** @return $this */
public function setDead(bool $dead) : self{
$this->dead = $dead;
return $this;
}
}

View File

@ -50,7 +50,7 @@ trait FallableTrait{
public function onNearbyBlockChange() : void{
$pos = $this->getPosition();
$down = $pos->getWorld()->getBlock($pos->getSide(Facing::DOWN));
if($down->getId() === BlockLegacyIds::AIR || $down instanceof Liquid || $down instanceof Fire){
if($down->getId() === BlockLegacyIds::AIR or $down instanceof Liquid or $down instanceof Fire){
$pos->getWorld()->setBlock($pos, VanillaBlocks::AIR());
$block = $this;

View File

@ -55,7 +55,7 @@ final class MinimumCostFlowCalculator{
$cost = 1000;
foreach(Facing::HORIZONTAL as $j){
if($j === $originOpposite || $j === $lastOpposite){
if($j === $originOpposite or $j === $lastOpposite){
continue;
}

View File

@ -89,7 +89,7 @@ class SignText{
if(!is_int($index)){
throw new \InvalidArgumentException("Index must be an integer");
}
if($index < 0 || $index >= self::LINE_COUNT){
if($index < 0 or $index >= self::LINE_COUNT){
throw new \InvalidArgumentException("Line index is out of bounds");
}
}

View File

@ -127,7 +127,7 @@ abstract class Command{
public function testPermissionSilent(CommandSender $target, ?string $permission = null) : bool{
$permission ??= $this->permission;
if($permission === null || $permission === ""){
if($permission === null or $permission === ""){
return true;
}
@ -182,7 +182,7 @@ abstract class Command{
}
private function allowChangesFrom(CommandMap $commandMap) : bool{
return $this->commandMap === null || $this->commandMap === $commandMap;
return $this->commandMap === null or $this->commandMap === $commandMap;
}
public function isRegistered() : bool{
@ -235,7 +235,7 @@ abstract class Command{
$result = KnownTranslationFactory::chat_type_admin($source->getName(), $message);
$colored = $result->prefix(TextFormat::GRAY . TextFormat::ITALIC);
if($sendToSource && !($source instanceof ConsoleCommandSender)){
if($sendToSource and !($source instanceof ConsoleCommandSender)){
$source->sendMessage($message);
}

View File

@ -71,7 +71,7 @@ class FormattedCommandAlias extends Command{
$index = strpos($formatString, '$');
while($index !== false){
$start = $index;
if($index > 0 && $formatString[$start - 1] === "\\"){
if($index > 0 and $formatString[$start - 1] === "\\"){
$formatString = substr($formatString, 0, $start - 1) . substr($formatString, $start);
$index = strpos($formatString, '$', $index);
continue;
@ -88,7 +88,7 @@ class FormattedCommandAlias extends Command{
$argStart = $index;
while($index < strlen($formatString) && self::inRange(ord($formatString[$index]) - 48, 0, 9)){
while($index < strlen($formatString) and self::inRange(ord($formatString[$index]) - 48, 0, 9)){
++$index;
}
@ -106,19 +106,19 @@ class FormattedCommandAlias extends Command{
$rest = false;
if($index < strlen($formatString) && $formatString[$index] === "-"){
if($index < strlen($formatString) and $formatString[$index] === "-"){
$rest = true;
++$index;
}
$end = $index;
if($required && $position >= count($args)){
if($required and $position >= count($args)){
throw new \InvalidArgumentException("Missing required argument " . ($position + 1));
}
$replacement = "";
if($rest && $position < count($args)){
if($rest and $position < count($args)){
for($i = $position, $c = count($args); $i < $c; ++$i){
if($i !== $position){
$replacement .= " ";
@ -141,6 +141,6 @@ class FormattedCommandAlias extends Command{
}
private static function inRange(int $i, int $j, int $k) : bool{
return $i >= $j && $i <= $k;
return $i >= $j and $i <= $k;
}
}

View File

@ -53,7 +53,7 @@ final class PluginCommand extends Command implements PluginOwned{
$success = $this->executor->onCommand($sender, $this, $commandLabel, $args);
if(!$success && $this->usageMessage !== ""){
if(!$success and $this->usageMessage !== ""){
throw new InvalidCommandSyntaxException();
}

View File

@ -183,11 +183,11 @@ class SimpleCommandMap implements CommandMap{
private function registerAlias(Command $command, bool $isAlias, string $fallbackPrefix, string $label) : bool{
$this->knownCommands[$fallbackPrefix . ":" . $label] = $command;
if(($command instanceof VanillaCommand || $isAlias) && isset($this->knownCommands[$label])){
if(($command instanceof VanillaCommand or $isAlias) and isset($this->knownCommands[$label])){
return false;
}
if(isset($this->knownCommands[$label]) && $this->knownCommands[$label]->getLabel() === $label){
if(isset($this->knownCommands[$label]) and $this->knownCommands[$label]->getLabel() === $label){
return false;
}

View File

@ -26,8 +26,6 @@ namespace pocketmine\command\defaults;
use pocketmine\command\Command;
use pocketmine\command\CommandSender;
use pocketmine\command\utils\InvalidCommandSyntaxException;
use pocketmine\inventory\Inventory;
use pocketmine\item\Item;
use pocketmine\item\LegacyStringToItemParser;
use pocketmine\item\LegacyStringToItemParserException;
use pocketmine\item\StringToItemParser;
@ -35,9 +33,9 @@ use pocketmine\lang\KnownTranslationFactory;
use pocketmine\permission\DefaultPermissionNames;
use pocketmine\player\Player;
use pocketmine\utils\TextFormat;
use function array_merge;
use function count;
use function implode;
use function min;
class ClearCommand extends VanillaCommand{
@ -59,6 +57,7 @@ class ClearCommand extends VanillaCommand{
throw new InvalidCommandSyntaxException();
}
$target = null;
if(isset($args[0])){
$target = $sender->getServer()->getPlayerByPrefix($args[0]);
if($target === null){
@ -78,14 +77,14 @@ class ClearCommand extends VanillaCommand{
throw new InvalidCommandSyntaxException();
}
$targetItem = null;
$item = null;
$maxCount = -1;
if(isset($args[1])){
try{
$targetItem = StringToItemParser::getInstance()->parse($args[1]) ?? LegacyStringToItemParser::getInstance()->parse($args[1]);
$item = StringToItemParser::getInstance()->parse($args[1]) ?? LegacyStringToItemParser::getInstance()->parse($args[1]);
if(isset($args[2])){
$targetItem->setCount($maxCount = $this->getInteger($sender, $args[2], -1));
$item->setCount($maxCount = $this->getInteger($sender, $args[2], 0));
}
}catch(LegacyStringToItemParserException $e){
//vanilla checks this at argument parsing layer, can't come up with a better alternative
@ -94,19 +93,14 @@ class ClearCommand extends VanillaCommand{
}
}
/**
* @var Inventory[] $inventories - This is the order that vanilla would clear items in.
*/
$inventories = [
$target->getInventory(),
$target->getCursorInventory(),
$target->getArmorInventory(),
$target->getOffHandInventory()
];
//checking players inventory for all the items matching the criteria
if($item !== null and $maxCount === 0){
$count = 0;
$contents = array_merge($target->getInventory()->all($item), $target->getArmorInventory()->all($item));
foreach($contents as $content){
$count += $content->getCount();
}
// Checking player's inventory for all the items matching the criteria
if($targetItem !== null && $maxCount === 0){
$count = $this->countItems($inventories, $targetItem);
if($count > 0){
$sender->sendMessage(KnownTranslationFactory::commands_clear_testing($target->getName(), (string) $count));
}else{
@ -116,59 +110,65 @@ class ClearCommand extends VanillaCommand{
return true;
}
$clearedCount = 0;
if($targetItem === null){
// Clear all items from the inventories
$clearedCount += $this->countItems($inventories, null);
foreach($inventories as $inventory){
$inventory->clearAll();
$cleared = 0;
//clear everything from the targets inventory
if($item === null){
$contents = array_merge($target->getInventory()->getContents(), $target->getArmorInventory()->getContents());
foreach($contents as $content){
$cleared += $content->getCount();
}
$target->getInventory()->clearAll();
$target->getArmorInventory()->clearAll();
//TODO: should the cursor inv be cleared?
}else{
// Clear the item from target's inventory irrelevant of the count
//clear the item from targets inventory irrelevant of the count
if($maxCount === -1){
$clearedCount += $this->countItems($inventories, $targetItem);
foreach($inventories as $inventory){
$inventory->remove($targetItem);
if(($slot = $target->getArmorInventory()->first($item)) !== -1){
$cleared++;
$target->getArmorInventory()->clear($slot);
}
foreach($target->getInventory()->all($item) as $index => $i){
$cleared += $i->getCount();
$target->getInventory()->clear($index);
}
}else{
// Clear the item from target's inventory up to maxCount
foreach($inventories as $inventory){
foreach($inventory->all($targetItem) as $index => $item){
// The count to reduce from the item and max count
$reductionCount = min($item->getCount(), $maxCount);
$item->pop($reductionCount);
$clearedCount += $reductionCount;
$inventory->setItem($index, $item);
//clear only the given amount of that particular item from targets inventory
if(($slot = $target->getArmorInventory()->first($item)) !== -1){
$cleared++;
$maxCount--;
$target->getArmorInventory()->clear($slot);
}
$maxCount -= $reductionCount;
if($maxCount <= 0){
break 2;
if($maxCount > 0){
foreach($target->getInventory()->all($item) as $index => $i){
if($i->getCount() >= $maxCount){
$i->pop($maxCount);
$cleared += $maxCount;
$target->getInventory()->setItem($index, $i);
break;
}
if($maxCount <= 0){
break;
}
$cleared += $i->getCount();
$maxCount -= $i->getCount();
$target->getInventory()->clear($index);
}
}
}
}
if($clearedCount > 0){
Command::broadcastCommandMessage($sender, KnownTranslationFactory::commands_clear_success($target->getName(), (string) $clearedCount));
if($cleared > 0){
Command::broadcastCommandMessage($sender, KnownTranslationFactory::commands_clear_success($target->getName(), (string) $cleared));
}else{
$sender->sendMessage(KnownTranslationFactory::commands_clear_failure_no_items($target->getName())->prefix(TextFormat::RED));
}
return true;
}
/**
* @param Inventory[] $inventories
*/
protected function countItems(array $inventories, ?Item $target) : int{
$count = 0;
foreach($inventories as $inventory){
$contents = $target !== null ? $inventory->all($target) : $inventory->getContents();
foreach($contents as $item){
$count += $item->getCount();
}
}
return $count;
}
}

View File

@ -25,6 +25,7 @@ namespace pocketmine\command\defaults;
use pocketmine\command\CommandSender;
use pocketmine\command\utils\InvalidCommandSyntaxException;
use pocketmine\data\java\GameModeIdMap;
use pocketmine\lang\KnownTranslationFactory;
use pocketmine\permission\DefaultPermissionNames;
use pocketmine\player\GameMode;
@ -56,7 +57,7 @@ class DefaultGamemodeCommand extends VanillaCommand{
return true;
}
$sender->getServer()->getConfigGroup()->setConfigString("gamemode", $gameMode->name());
$sender->getServer()->getConfigGroup()->setConfigInt("gamemode", GameModeIdMap::getInstance()->toId($gameMode));
$sender->sendMessage(KnownTranslationFactory::commands_defaultgamemode_success($gameMode->getTranslatableName()));
return true;
}

View File

@ -96,7 +96,7 @@ class EffectCommand extends VanillaCommand{
$visible = true;
if(count($args) >= 5){
$v = strtolower($args[4]);
if($v === "on" || $v === "true" || $v === "t" || $v === "1"){
if($v === "on" or $v === "true" or $v === "t" or $v === "1"){
$visible = false;
}
}

View File

@ -52,7 +52,7 @@ class ListCommand extends VanillaCommand{
$playerNames = array_map(function(Player $player) : string{
return $player->getName();
}, array_filter($sender->getServer()->getOnlinePlayers(), function(Player $player) use ($sender) : bool{
return !($sender instanceof Player) || $sender->canSee($player);
return !($sender instanceof Player) or $sender->canSee($player);
}));
sort($playerNames, SORT_STRING);

View File

@ -181,12 +181,12 @@ class ParticleCommand extends VanillaCommand{
case "slime":
return new ItemBreakParticle(VanillaItems::SLIMEBALL());
case "itembreak":
if($data !== null && $data !== 0){
if($data !== null and $data !== 0){
return new ItemBreakParticle(ItemFactory::getInstance()->get($data));
}
break;
case "terrain":
if($data !== null && $data !== 0){
if($data !== null and $data !== 0){
return new TerrainParticle(BlockFactory::getInstance()->get($data, 0));
}
break;

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