Merge branch 'next-major' into modern-world-support

This commit is contained in:
Dylan K. Taylor 2022-06-02 20:24:25 +01:00
commit 01af70f671
No known key found for this signature in database
GPG Key ID: 8927471A91CAFD3D
26 changed files with 299 additions and 351 deletions

77
changelogs/4.4.md Normal file
View File

@ -0,0 +1,77 @@
**For Minecraft: Bedrock Edition 1.18.30**
### 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.4.0
Released 1st June 2022.
## General
- The server will now shut itself down if any of the following errors occur during startup:
- Any plugin fails to load or enable (plugins loaded by other plugins post-startup are **not** affected by this change) (**PR [#4951](https://github.com/pmmp/PocketMine-MP/pull/4951)**)
- The motivation for this change is to prevent situations where plugins failing to load could result in adverse outcomes, such as a world protection plugin leaving a lobby unprotected from griefing.
- If you encounter this problem, remove the offending plugin(s) or prevent it from loading using `plugin_list.yml`.
- See **PR [#4951](https://github.com/pmmp/PocketMine-MP/pull/4951)** for more detail on this change.
- Any world mentioned in `server.properties` or `pocketmine.yml` fails to load (worlds loaded by plugins are **not** affected by this change)
- Any world mentioned in `server.properties` or `pocketmine.yml` fails to generate (e.g. due to invalid generator settings)
- Enabling the server whitelist while the server is running (e.g. using `/whitelist on`) will now kick any non-whitelisted players currently on the server (**PR [#4774](https://github.com/pmmp/PocketMine-MP/pull/4774)**).
- Help for commands (`/help <name of command>`) now displays a list of aliases of that command.
- A CRITICAL log message is now generated if a plugin disables itself when enabling, in case the plugin doesn't emit any error of its own.
- The `/give` command now shows the alias used to find the given item in the success message, instead of the item ID/meta.
## Fixes
- Block placement has been fixed in many places where it previously didn't work correctly (**PR [#4886](https://github.com/pmmp/PocketMine-MP/pull/4886)**):
- torches on top of slabs, upside-down stairs
- torches on the back face of stairs
- flower pots on top of fences
- the list goes on and on ...
- Fixed backslash escapes not getting properly removed from commands in some cases.
- Fixed aliases defined in the `aliases` section of `pocketmine.yml` not being treated as quote-aware.
## Gameplay
- Plants in flower pots can now be removed by right-clicking on the flower pot.
- Leaves now have a 2% chance of dropping sticks when destroyed by hand (**PR [#5019](https://github.com/pmmp/PocketMine-MP/pull/5019)**).
- Food exhaustion now matches Bedrock 1.18.30 (**PR [#5034](https://github.com/pmmp/PocketMine-MP/pull/5034)**).
- Implemented Stonecutter block (**PR [#4732](https://github.com/pmmp/PocketMine-MP/pull/4732)**).
## API
### Block
- Added `Block->getSupportType(Facing) : SupportType` (**PR [#4886](https://github.com/pmmp/PocketMine-MP/pull/4886)**).
- This is used to determine the kind of support a block face can provide to a block (e.g. a torch) placed on it.
- Added `utils\SupportType` enum (**PR [#4886](https://github.com/pmmp/PocketMine-MP/pull/4886)**).
- `tile\Spawnable->isDirty()` and `tile\Spawnable->setDirty()` are now `@deprecated`.
### Command
- Added `CommandStringHelper::parseQuoteAware()`. This static method contains the code used by `SimpleCommandMap` used to parse quoted command arguments.
### Entity
- Added `Human::emote()` (**PR [#4610](https://github.com/pmmp/PocketMine-MP/pull/4610)**)
### Event
- `PlayerCommandPreprocessEvent` is now `@deprecated`, since its functionality is entirely replaced by other, general-purpose events.
- Use `CommandEvent` to intercept commands.
- Use `PlayerChatEvent` to intercept chat messages.
- To convert a chat message into a command, pass it directly to `Server->dispatchCommand()` with the player as sender.
- Added `PlayerPostChunkSendEvent` (**PR [#4937](https://github.com/pmmp/PocketMine-MP/pull/4937)**).
- Added `PlayerDeathEvent->setKeepXp()` (**PR [#4015](https://github.com/pmmp/PocketMine-MP/pull/4015)**).
- `InventoryCloseEvent` is now called **after** the target window has been removed. This fixes various feedback loops caused by trying to open new windows to a player while there was one still active.
- As a side effect, this now means that `Player->getCurrentWindow()` will return `null` during `InventoryCloseEvent`. Use `InventoryCloseEvent->getInventory()` instead.
### Item
- `StringToItemParser` now recognizes `cod`, `raw_cod` and `cooked_cod` aliases.
### Plugin
- `DisablePluginException` may now be thrown from `Plugin::onEnable()` to make the server gracefully disable the plugin (without crashing) (**PR [#4780](https://github.com/pmmp/PocketMine-MP/pull/4780)**).
- `PluginManager->registerEvent()` now returns the `RegisteredListener` created for the handler, to permit unregistering it later.
## Internals
- Private property declarations now use typed properties (PHP 7.4) and promoted constructor properties (PHP 8.0) wherever possible.
- Protected and public properties remain unchanged, since they can't be changed without breaking subclasses.
- Promoted constructor properties are only used when it's consistently possible to promote most or all properties in a class.
- Simplified and improved legibility of `FormattedCommandAlias`.
- Added unit tests for the quote-aware command parser used by `SimpleCommandMap`.
- Various hardcoded values in `block` package classes have been moved to private constants to improve readability.
- Added various constants used in the `LevelDB` world provider.

View File

@ -31,9 +31,9 @@ use function str_repeat;
final class VersionInfo{
public const NAME = "PocketMine-MP";
public const BASE_VERSION = "4.4.0-BETA2";
public const BASE_VERSION = "5.0.0";
public const IS_DEVELOPMENT_BUILD = true;
public const BUILD_CHANNEL = "beta";
public const BUILD_CHANNEL = "alpha";
private function __construct(){
//NOOP

View File

@ -90,125 +90,79 @@ abstract class Entity{
}
/** @var Player[] */
protected $hasSpawned = [];
protected array $hasSpawned = [];
/** @var int */
protected $id;
protected int $id;
private EntityMetadataCollection $networkProperties;
/** @var EntityDamageEvent|null */
protected $lastDamageCause = null;
protected ?EntityDamageEvent $lastDamageCause = null;
/** @var Block[]|null */
protected $blocksAround;
protected ?array $blocksAround = null;
/** @var Location */
protected $location;
/** @var Location */
protected $lastLocation;
/** @var Vector3 */
protected $motion;
/** @var Vector3 */
protected $lastMotion;
/** @var bool */
protected $forceMovementUpdate = false;
protected Location $location;
protected Location $lastLocation;
protected Vector3 $motion;
protected Vector3 $lastMotion;
protected bool $forceMovementUpdate = false;
/** @var AxisAlignedBB */
public $boundingBox;
/** @var bool */
public $onGround = false;
public AxisAlignedBB $boundingBox;
public bool $onGround = false;
/** @var EntitySizeInfo */
public $size;
public EntitySizeInfo $size;
private float $health = 20.0;
private int $maxHealth = 20;
/** @var float */
protected $ySize = 0.0;
/** @var float */
protected $stepHeight = 0.0;
/** @var bool */
public $keepMovement = false;
protected float $ySize = 0.0;
protected float $stepHeight = 0.0;
public bool $keepMovement = false;
/** @var float */
public $fallDistance = 0.0;
/** @var int */
public $ticksLived = 0;
/** @var int */
public $lastUpdate;
/** @var int */
protected $fireTicks = 0;
/** @var bool */
public $canCollide = true;
/** @var bool */
protected $isStatic = false;
public float $fallDistance = 0.0;
public int $ticksLived = 0;
public int $lastUpdate;
protected int $fireTicks = 0;
private bool $savedWithChunk = true;
/** @var bool */
public $isCollided = false;
/** @var bool */
public $isCollidedHorizontally = false;
/** @var bool */
public $isCollidedVertically = false;
public bool $isCollided = false;
public bool $isCollidedHorizontally = false;
public bool $isCollidedVertically = false;
/** @var int */
public $noDamageTicks = 0;
/** @var bool */
protected $justCreated = true;
public int $noDamageTicks = 0;
protected bool $justCreated = true;
/** @var AttributeMap */
protected $attributeMap;
protected AttributeMap $attributeMap;
/** @var float */
protected $gravity;
/** @var float */
protected $drag;
/** @var bool */
protected $gravityEnabled = true;
protected float $gravity;
protected float $drag;
protected bool $gravityEnabled = true;
/** @var Server */
protected $server;
protected Server $server;
/** @var bool */
protected $closed = false;
protected bool $closed = false;
private bool $closeInFlight = false;
private bool $needsDespawn = false;
/** @var TimingsHandler */
protected $timings;
protected TimingsHandler $timings;
protected bool $networkPropertiesDirty = false;
/** @var string */
protected $nameTag = "";
/** @var bool */
protected $nameTagVisible = true;
/** @var bool */
protected $alwaysShowNameTag = false;
/** @var string */
protected $scoreTag = "";
/** @var float */
protected $scale = 1.0;
protected string $nameTag = "";
protected bool $nameTagVisible = true;
protected bool $alwaysShowNameTag = false;
protected string $scoreTag = "";
protected float $scale = 1.0;
/** @var bool */
protected $canClimb = false;
/** @var bool */
protected $canClimbWalls = false;
/** @var bool */
protected $immobile = false;
/** @var bool */
protected $invisible = false;
/** @var bool */
protected $silent = false;
protected bool $canClimb = false;
protected bool $canClimbWalls = false;
protected bool $immobile = false;
protected bool $invisible = false;
protected bool $silent = false;
/** @var int|null */
protected $ownerId = null;
/** @var int|null */
protected $targetId = null;
protected ?int $ownerId = null;
protected ?int $targetId = null;
private bool $constructorCalled = false;
@ -222,6 +176,8 @@ abstract class Entity{
$this->timings = Timings::getEntityTimings($this);
$this->size = $this->getInitialSizeInfo();
$this->drag = $this->getInitialDragMultiplier();
$this->gravity = $this->getInitialGravity();
$this->id = self::nextRuntimeId();
$this->server = $location->getWorld()->getServer();
@ -257,6 +213,21 @@ abstract class Entity{
abstract protected function getInitialSizeInfo() : EntitySizeInfo;
/**
* Returns the percentage by which the entity's velocity is reduced per tick when moving through air.
* The entity's velocity is multiplied by 1 minus this value.
*
* @return float 0-1
*/
abstract protected function getInitialDragMultiplier() : float;
/**
* Returns the downwards acceleration of the entity when falling, in blocks/tick².
*
* @return float minimum 0
*/
abstract protected function getInitialGravity() : float;
public function getNameTag() : string{
return $this->nameTag;
}
@ -984,9 +955,7 @@ abstract class Entity{
$this->timings->stopTiming();
//if($this->isStatic())
return ($hasUpdate || $this->hasMovementUpdate());
//return !($this instanceof Player);
}
final public function scheduleUpdate() : void{

View File

@ -74,28 +74,18 @@ class Human extends Living implements ProjectileSource, InventoryHolder{
public static function getNetworkTypeId() : string{ return EntityIds::PLAYER; }
/** @var PlayerInventory */
protected $inventory;
protected PlayerInventory $inventory;
protected PlayerOffHandInventory $offHandInventory;
protected PlayerEnderInventory $enderInventory;
/** @var PlayerOffHandInventory */
protected $offHandInventory;
protected UuidInterface $uuid;
/** @var PlayerEnderInventory */
protected $enderInventory;
protected Skin $skin;
/** @var UuidInterface */
protected $uuid;
protected HungerManager $hungerManager;
protected ExperienceManager $xpManager;
/** @var Skin */
protected $skin;
/** @var HungerManager */
protected $hungerManager;
/** @var ExperienceManager */
protected $xpManager;
/** @var int */
protected $xpSeed;
protected int $xpSeed;
public function __construct(Location $location, Skin $skin, ?CompoundTag $nbt = null){
$this->skin = $skin;
@ -383,9 +373,9 @@ class Human extends Living implements ProjectileSource, InventoryHolder{
public function getDrops() : array{
return array_filter(array_merge(
$this->inventory !== null ? array_values($this->inventory->getContents()) : [],
$this->armorInventory !== null ? array_values($this->armorInventory->getContents()) : [],
$this->offHandInventory !== null ? array_values($this->offHandInventory->getContents()) : [],
array_values($this->inventory->getContents()),
array_values($this->armorInventory->getContents()),
array_values($this->offHandInventory->getContents()),
), function(Item $item) : bool{ return !$item->hasEnchantment(VanillaEnchantments::VANISHING()); });
}
@ -404,55 +394,51 @@ class Human extends Living implements ProjectileSource, InventoryHolder{
$inventoryTag = new ListTag([], NBT::TAG_Compound);
$nbt->setTag("Inventory", $inventoryTag);
if($this->inventory !== null){
//Normal inventory
$slotCount = $this->inventory->getSize() + $this->inventory->getHotbarSize();
for($slot = $this->inventory->getHotbarSize(); $slot < $slotCount; ++$slot){
$item = $this->inventory->getItem($slot - 9);
if(!$item->isNull()){
$inventoryTag->push($item->nbtSerialize($slot));
}
}
//Armor
for($slot = 100; $slot < 104; ++$slot){
$item = $this->armorInventory->getItem($slot - 100);
if(!$item->isNull()){
$inventoryTag->push($item->nbtSerialize($slot));
}
//Normal inventory
$slotCount = $this->inventory->getSize() + $this->inventory->getHotbarSize();
for($slot = $this->inventory->getHotbarSize(); $slot < $slotCount; ++$slot){
$item = $this->inventory->getItem($slot - 9);
if(!$item->isNull()){
$inventoryTag->push($item->nbtSerialize($slot));
}
$nbt->setInt("SelectedInventorySlot", $this->inventory->getHeldItemIndex());
}
//Armor
for($slot = 100; $slot < 104; ++$slot){
$item = $this->armorInventory->getItem($slot - 100);
if(!$item->isNull()){
$inventoryTag->push($item->nbtSerialize($slot));
}
}
$nbt->setInt("SelectedInventorySlot", $this->inventory->getHeldItemIndex());
$offHandItem = $this->offHandInventory->getItem(0);
if(!$offHandItem->isNull()){
$nbt->setTag("OffHandItem", $offHandItem->nbtSerialize());
}
if($this->enderInventory !== null){
/** @var CompoundTag[] $items */
$items = [];
/** @var CompoundTag[] $items */
$items = [];
$slotCount = $this->enderInventory->getSize();
for($slot = 0; $slot < $slotCount; ++$slot){
$item = $this->enderInventory->getItem($slot);
if(!$item->isNull()){
$items[] = $item->nbtSerialize($slot);
}
$slotCount = $this->enderInventory->getSize();
for($slot = 0; $slot < $slotCount; ++$slot){
$item = $this->enderInventory->getItem($slot);
if(!$item->isNull()){
$items[] = $item->nbtSerialize($slot);
}
$nbt->setTag("EnderChestInventory", new ListTag($items, NBT::TAG_Compound));
}
if($this->skin !== null){
$nbt->setTag("Skin", CompoundTag::create()
->setString("Name", $this->skin->getSkinId())
->setByteArray("Data", $this->skin->getSkinData())
->setByteArray("CapeData", $this->skin->getCapeData())
->setString("GeometryName", $this->skin->getGeometryName())
->setByteArray("GeometryData", $this->skin->getGeometryData())
);
}
$nbt->setTag("EnderChestInventory", new ListTag($items, NBT::TAG_Compound));
$nbt->setTag("Skin", CompoundTag::create()
->setString("Name", $this->skin->getSkinId())
->setByteArray("Data", $this->skin->getSkinData())
->setByteArray("CapeData", $this->skin->getCapeData())
->setString("GeometryName", $this->skin->getGeometryName())
->setByteArray("GeometryData", $this->skin->getGeometryData())
);
return $nbt;
}
@ -512,11 +498,13 @@ class Human extends Living implements ProjectileSource, InventoryHolder{
}
protected function destroyCycles() : void{
$this->inventory = null;
$this->offHandInventory = null;
$this->enderInventory = null;
$this->hungerManager = null;
$this->xpManager = null;
unset(
$this->inventory,
$this->offHandInventory,
$this->enderInventory,
$this->hungerManager,
$this->xpManager
);
parent::destroyCycles();
}
}

View File

@ -76,50 +76,34 @@ use const M_PI;
abstract class Living extends Entity{
protected const DEFAULT_BREATH_TICKS = 300;
protected $gravity = 0.08;
protected $drag = 0.02;
protected int $attackTime = 0;
/** @var int */
protected $attackTime = 0;
public int $deadTicks = 0;
protected int $maxDeadTicks = 25;
/** @var int */
public $deadTicks = 0;
/** @var int */
protected $maxDeadTicks = 25;
protected float $jumpVelocity = 0.42;
/** @var float */
protected $jumpVelocity = 0.42;
protected EffectManager $effectManager;
/** @var EffectManager */
protected $effectManager;
protected ArmorInventory $armorInventory;
/** @var ArmorInventory */
protected $armorInventory;
protected bool $breathing = true;
protected int $breathTicks = self::DEFAULT_BREATH_TICKS;
protected int $maxBreathTicks = self::DEFAULT_BREATH_TICKS;
/** @var bool */
protected $breathing = true;
/** @var int */
protected $breathTicks = self::DEFAULT_BREATH_TICKS;
/** @var int */
protected $maxBreathTicks = self::DEFAULT_BREATH_TICKS;
protected Attribute $healthAttr;
protected Attribute $absorptionAttr;
protected Attribute $knockbackResistanceAttr;
protected Attribute $moveSpeedAttr;
/** @var Attribute */
protected $healthAttr;
/** @var Attribute */
protected $absorptionAttr;
/** @var Attribute */
protected $knockbackResistanceAttr;
/** @var Attribute */
protected $moveSpeedAttr;
protected bool $sprinting = false;
protected bool $sneaking = false;
protected bool $gliding = false;
protected bool $swimming = false;
/** @var bool */
protected $sprinting = false;
/** @var bool */
protected $sneaking = false;
/** @var bool */
protected $gliding = false;
/** @var bool */
protected $swimming = false;
protected function getInitialDragMultiplier() : float{ return 0.02; }
protected function getInitialGravity() : float{ return 0.08; }
abstract public function getName() : string;
@ -850,8 +834,10 @@ abstract class Living extends Entity{
}
protected function destroyCycles() : void{
$this->armorInventory = null;
$this->effectManager = null;
unset(
$this->armorInventory,
$this->effectManager
);
parent::destroyCycles();
}
}

View File

@ -29,10 +29,8 @@ use pocketmine\world\World;
class Location extends Position{
/** @var float */
public $yaw;
/** @var float */
public $pitch;
public float $yaw;
public float $pitch;
public function __construct(float $x, float $y, float $z, ?World $world, float $yaw, float $pitch){
$this->yaw = $yaw;

View File

@ -39,10 +39,8 @@ class Squid extends WaterAnimal{
public static function getNetworkTypeId() : string{ return EntityIds::SQUID; }
/** @var Vector3|null */
public $swimDirection = null;
/** @var float */
public $swimSpeed = 0.1;
public ?Vector3 $swimDirection = null;
public float $swimSpeed = 0.1;
private int $switchDirectionTicker = 0;

View File

@ -28,8 +28,7 @@ use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataCollection;
use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataFlags;
abstract class WaterAnimal extends Living implements Ageable{
/** @var bool */
protected $baby = false;
protected bool $baby = false;
public function isBaby() : bool{
return $this->baby;

View File

@ -33,25 +33,22 @@ use function count;
use function spl_object_id;
class EffectManager{
/** @var EffectInstance[] */
protected $effects = [];
protected array $effects = [];
/** @var Color */
protected $bubbleColor;
/** @var bool */
protected $onlyAmbientEffects = false;
protected Color $bubbleColor;
protected bool $onlyAmbientEffects = false;
/**
* @var \Closure[]|ObjectSet
* @phpstan-var ObjectSet<\Closure(EffectInstance, bool $replacesOldEffect) : void>
*/
protected $effectAddHooks;
protected ObjectSet $effectAddHooks;
/**
* @var \Closure[]|ObjectSet
* @phpstan-var ObjectSet<\Closure(EffectInstance) : void>
*/
protected $effectRemoveHooks;
protected ObjectSet $effectRemoveHooks;
public function __construct(
private Living $entity

View File

@ -78,26 +78,15 @@ class ExperienceOrb extends Entity{
return $result;
}
public $gravity = 0.04;
public $drag = 0.02;
protected int $age = 0;
/** @var int */
protected $age = 0;
/** Ticker used for determining interval in which to look for new target players. */
protected int $lookForTargetTime = 0;
/**
* @var int
* Ticker used for determining interval in which to look for new target players.
*/
protected $lookForTargetTime = 0;
/** Runtime entity ID of the player this XP orb is targeting. */
protected ?int $targetPlayerRuntimeId = null;
/**
* @var int|null
* Runtime entity ID of the player this XP orb is targeting.
*/
protected $targetPlayerRuntimeId = null;
/** @var int */
protected $xpValue;
protected int $xpValue;
public function __construct(Location $location, int $xpValue, ?CompoundTag $nbt = null){
$this->xpValue = $xpValue;
@ -106,6 +95,10 @@ class ExperienceOrb extends Entity{
protected function getInitialSizeInfo() : EntitySizeInfo{ return new EntitySizeInfo(0.25, 0.25); }
protected function getInitialDragMultiplier() : float{ return 0.02; }
protected function getInitialGravity() : float{ return 0.04; }
protected function initEntity(CompoundTag $nbt) : void{
parent::initEntity($nbt);

View File

@ -46,13 +46,7 @@ class FallingBlock extends Entity{
public static function getNetworkTypeId() : string{ return EntityIds::FALLING_BLOCK; }
protected $gravity = 0.04;
protected $drag = 0.02;
/** @var Block */
protected $block;
public $canCollide = false;
protected Block $block;
public function __construct(Location $location, Block $block, ?CompoundTag $nbt = null){
$this->block = $block;
@ -61,6 +55,10 @@ class FallingBlock extends Entity{
protected function getInitialSizeInfo() : EntitySizeInfo{ return new EntitySizeInfo(0.98, 0.98); }
protected function getInitialDragMultiplier() : float{ return 0.02; }
protected function getInitialGravity() : float{ return 0.04; }
public static function parseBlockNBT(BlockFactory $factory, CompoundTag $nbt) : Block{
$blockId = 0;

View File

@ -50,22 +50,11 @@ class ItemEntity extends Entity{
public const NEVER_DESPAWN = -1;
public const MAX_DESPAWN_DELAY = 32767 + self::DEFAULT_DESPAWN_DELAY; //max value storable by mojang NBT :(
/** @var string */
protected $owner = "";
/** @var string */
protected $thrower = "";
/** @var int */
protected $pickupDelay = 0;
/** @var Item */
protected $item;
protected $gravity = 0.04;
protected $drag = 0.02;
public $canCollide = false;
/** @var int */
protected $despawnDelay = self::DEFAULT_DESPAWN_DELAY;
protected string $owner = "";
protected string $thrower = "";
protected int $pickupDelay = 0;
protected int $despawnDelay = self::DEFAULT_DESPAWN_DELAY;
protected Item $item;
public function __construct(Location $location, Item $item, ?CompoundTag $nbt = null){
if($item->isNull()){
@ -77,6 +66,10 @@ class ItemEntity extends Entity{
protected function getInitialSizeInfo() : EntitySizeInfo{ return new EntitySizeInfo(0.25, 0.25); }
protected function getInitialDragMultiplier() : float{ return 0.02; }
protected function getInitialGravity() : float{ return 0.04; }
protected function initEntity(CompoundTag $nbt) : void{
parent::initEntity($nbt);
@ -197,12 +190,8 @@ class ItemEntity extends Entity{
}
$nbt->setShort("Age", $age);
$nbt->setShort("PickupDelay", $this->pickupDelay);
if($this->owner !== null){
$nbt->setString("Owner", $this->owner);
}
if($this->thrower !== null){
$nbt->setString("Thrower", $this->thrower);
}
$nbt->setString("Owner", $this->owner);
$nbt->setString("Thrower", $this->thrower);
return $nbt;
}

View File

@ -56,17 +56,9 @@ class Painting extends Entity{
Facing::EAST => 3
];
/** @var float */
protected $gravity = 0.0;
/** @var float */
protected $drag = 1.0;
/** @var Vector3 */
protected $blockIn;
/** @var int */
protected $facing = Facing::NORTH;
/** @var PaintingMotive */
protected $motive;
protected Vector3 $blockIn;
protected int $facing;
protected PaintingMotive $motive;
public function __construct(Location $location, Vector3 $blockIn, int $facing, PaintingMotive $motive, ?CompoundTag $nbt = null){
$this->motive = $motive;
@ -80,6 +72,10 @@ class Painting extends Entity{
return new EntitySizeInfo(0.5, 0.5);
}
protected function getInitialDragMultiplier() : float{ return 1.0; }
protected function getInitialGravity() : float{ return 0.0; }
protected function initEntity(CompoundTag $nbt) : void{
$this->setMaxHealth(1);
$this->setHealth(1);

View File

@ -84,18 +84,11 @@ class PaintingMotive{
return self::$motives;
}
/** @var string */
protected $name;
/** @var int */
protected $width;
/** @var int */
protected $height;
public function __construct(int $width, int $height, string $name){
$this->name = $name;
$this->width = $width;
$this->height = $height;
}
public function __construct(
protected int $width,
protected int $height,
protected string $name
){}
public function getName() : string{
return $this->name;

View File

@ -41,18 +41,15 @@ class PrimedTNT extends Entity implements Explosive{
public static function getNetworkTypeId() : string{ return EntityIds::TNT; }
protected $gravity = 0.04;
protected $drag = 0.02;
/** @var int */
protected $fuse;
protected int $fuse;
protected bool $worksUnderwater = false;
public $canCollide = false;
protected function getInitialSizeInfo() : EntitySizeInfo{ return new EntitySizeInfo(0.98, 0.98); }
protected function getInitialDragMultiplier() : float{ return 0.02; }
protected function getInitialGravity() : float{ return 0.04; }
public function getFuse() : int{
return $this->fuse;
}

View File

@ -52,23 +52,11 @@ class Arrow extends Projectile{
private const TAG_PICKUP = "pickup"; //TAG_Byte
public const TAG_CRIT = "crit"; //TAG_Byte
protected $gravity = 0.05;
protected $drag = 0.01;
/** @var float */
protected $damage = 2.0;
/** @var int */
protected $pickupMode = self::PICKUP_ANY;
/** @var float */
protected $punchKnockback = 0.0;
/** @var int */
protected $collideTicks = 0;
/** @var bool */
protected $critical = false;
protected float $damage = 2.0;
protected int $pickupMode = self::PICKUP_ANY;
protected float $punchKnockback = 0.0;
protected int $collideTicks = 0;
protected bool $critical = false;
public function __construct(Location $location, ?Entity $shootingEntity, bool $critical, ?CompoundTag $nbt = null){
parent::__construct($location, $shootingEntity, $nbt);
@ -77,6 +65,10 @@ class Arrow extends Projectile{
protected function getInitialSizeInfo() : EntitySizeInfo{ return new EntitySizeInfo(0.25, 0.25); }
protected function getInitialDragMultiplier() : float{ return 0.01; }
protected function getInitialGravity() : float{ return 0.05; }
protected function initEntity(CompoundTag $nbt) : void{
parent::initEntity($nbt);

View File

@ -32,7 +32,7 @@ use function mt_rand;
class ExperienceBottle extends Throwable{
public static function getNetworkTypeId() : string{ return EntityIds::XP_BOTTLE; }
protected $gravity = 0.07;
protected function getInitialGravity() : float{ return 0.07; }
public function getResultDamage() : int{
return -1;

View File

@ -51,11 +51,8 @@ use const PHP_INT_MAX;
abstract class Projectile extends Entity{
/** @var float */
protected $damage = 0.0;
/** @var Block|null */
protected $blockHit;
protected float $damage = 0.0;
protected ?Block $blockHit = null;
public function __construct(Location $location, ?Entity $shootingEntity, ?CompoundTag $nbt = null){
parent::__construct($location, $nbt);

View File

@ -52,11 +52,7 @@ class SplashPotion extends Throwable{
public static function getNetworkTypeId() : string{ return EntityIds::SPLASH_POTION; }
protected $gravity = 0.05;
protected $drag = 0.01;
/** @var bool */
protected $linger = false;
protected bool $linger = false;
protected PotionType $potionType;
public function __construct(Location $location, ?Entity $shootingEntity, PotionType $potionType, ?CompoundTag $nbt = null){
@ -64,6 +60,8 @@ class SplashPotion extends Throwable{
parent::__construct($location, $shootingEntity, $nbt);
}
protected function getInitialGravity() : float{ return 0.05; }
public function saveNBT() : CompoundTag{
$nbt = parent::saveNBT();
$nbt->setShort("PotionId", PotionTypeIdMap::getInstance()->toId($this->getPotionType()));

View File

@ -29,11 +29,12 @@ use pocketmine\math\RayTraceResult;
abstract class Throwable extends Projectile{
protected $gravity = 0.03;
protected $drag = 0.01;
protected function getInitialSizeInfo() : EntitySizeInfo{ return new EntitySizeInfo(0.25, 0.25); }
protected function getInitialDragMultiplier() : float{ return 0.01; }
protected function getInitialGravity() : float{ return 0.03; }
protected function onHitBlock(Block $blockHit, RayTraceResult $hitResult) : void{
parent::onHitBlock($blockHit, $hitResult);
$this->flagForDespawn();

View File

@ -241,8 +241,8 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
protected ?float $lastMovementProcess = null;
protected int $inAirTicks = 0;
/** @var float */
protected $stepHeight = 0.6;
protected float $stepHeight = 0.6;
protected ?Vector3 $sleeping = null;
private ?Position $spawnPosition = null;
@ -2217,16 +2217,10 @@ class Player extends Human implements CommandSender, ChunkListener, IPlayer{
$this->getWorld()->dropItem($this->location, $item);
}
if($this->inventory !== null){
$this->inventory->setHeldItemIndex(0);
$this->inventory->clearAll();
}
if($this->armorInventory !== null){
$this->armorInventory->clearAll();
}
if($this->offHandInventory !== null){
$this->offHandInventory->clearAll();
}
$this->inventory->setHeldItemIndex(0);
$this->inventory->clearAll();
$this->armorInventory->clearAll();
$this->offHandInventory->clearAll();
}
if(!$ev->getKeepXp()){

View File

@ -28,16 +28,9 @@ use pocketmine\utils\AssumptionFailedError;
use function assert;
class Position extends Vector3{
public ?World $world = null;
/** @var World|null */
public $world = null;
/**
* @param float|int $x
* @param float|int $y
* @param float|int $z
*/
public function __construct($x, $y, $z, ?World $world){
public function __construct(float|int $x, float|int $y, float|int $z, ?World $world){
parent::__construct($x, $y, $z);
if($world !== null && !$world->isLoaded()){
throw new \InvalidArgumentException("Specified world has been unloaded and cannot be used");

View File

@ -1904,11 +1904,9 @@ class World implements ChunkManager{
public function getCollidingEntities(AxisAlignedBB $bb, ?Entity $entity = null) : array{
$nearby = [];
if($entity === null || $entity->canCollide){
foreach($this->getNearbyEntities($bb, $entity) as $ent){
if($ent->canBeCollidedWith() && ($entity === null || $entity->canCollideWith($ent))){
$nearby[] = $ent;
}
foreach($this->getNearbyEntities($bb, $entity) as $ent){
if($ent->canBeCollidedWith() && ($entity === null || $entity->canCollideWith($ent))){
$nearby[] = $ent;
}
}

View File

@ -64,9 +64,6 @@ class RegionLoader{
public const FIRST_SECTOR = 2; //location table occupies 0 and 1
/** @var int */
public static $COMPRESSION_LEVEL = 7;
/** @var string */
protected $filePath;
/** @var resource */

@ -1 +1 @@
Subproject commit e884a4c234629126203e769df7c4dbbbc0dc2d49
Subproject commit 1b264da3d244cd9b0030cbc3d584d2f685648bfe

View File

@ -2,7 +2,7 @@ name: TesterPlugin
main: pmmp\TesterPlugin\Main
src-namespace-prefix: pmmp\TesterPlugin
version: 0.1.0
api: [3.2.0, 4.0.0]
api: [5.0.0]
load: POSTWORLD
author: pmmp
description: Plugin used to run tests on PocketMine-MP