mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-12 04:20:17 +00:00
Compare commits
5 Commits
4.1.0-BETA
...
4.0.8
Author | SHA1 | Date | |
---|---|---|---|
8a4bc72b34 | |||
32b07e0940 | |||
99f087e5e1 | |||
aaf7a88de7 | |||
67a0ae0246 |
@ -43,7 +43,6 @@ return (new PhpCsFixer\Config)
|
||||
'import_classes' => null,
|
||||
],
|
||||
'indentation_type' => true,
|
||||
'logical_operators' => true,
|
||||
'native_function_invocation' => [
|
||||
'scope' => 'namespaced',
|
||||
'include' => ['@all'],
|
||||
|
@ -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";
|
||||
|
@ -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){
|
||||
|
@ -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 . '";',
|
||||
|
@ -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.
|
||||
|
@ -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.
|
@ -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
47
composer.lock
generated
@ -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",
|
||||
|
@ -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
|
||||
|
@ -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!");
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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{
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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 [];
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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{
|
||||
|
@ -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{
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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()){
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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])){
|
||||
|
@ -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{
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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));
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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());
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
|
@ -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()){
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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()));
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
Reference in New Issue
Block a user