Skip to content

Commit

Permalink
Fixed possible inconsistency issues with entities and tile blocks tha…
Browse files Browse the repository at this point in the history
…t get some null values due to asynchronous methods.
  • Loading branch information
matcracker committed May 4, 2020
1 parent b643bf9 commit c4a0b50
Show file tree
Hide file tree
Showing 13 changed files with 326 additions and 139 deletions.
5 changes: 2 additions & 3 deletions src/matcracker/BedcoreProtect/listeners/PlayerListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -140,13 +140,12 @@ public function trackPlayerInteraction(PlayerInteractEvent $event): void
if ($clickedBlock instanceof ItemFrame) {
$tile = BlockUtils::asTile($clickedBlock);
if ($tile instanceof TileItemFrame) {
$oldNbt = BlockUtils::getCompoundTag($clickedBlock);
//I consider the ItemFrame as a fake inventory holder to only log "adding/removing" item.
if (!$tile->hasItem() && !$itemInHand->isNull()) {
$this->blocksQueries->addItemFrameLogByPlayer($player, $clickedBlock, $oldNbt, Action::ADD());
$this->blocksQueries->addItemFrameLogByPlayer($player, $clickedBlock, Action::ADD());
return;
} elseif ($tile->hasItem() && $leftClickBlock) {
$this->blocksQueries->addItemFrameLogByPlayer($player, $clickedBlock, $oldNbt, Action::REMOVE());
$this->blocksQueries->addItemFrameLogByPlayer($player, $clickedBlock, Action::REMOVE());
return;
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/matcracker/BedcoreProtect/math/Area.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

namespace matcracker\BedcoreProtect\math;

use matcracker\BedcoreProtect\serializable\SerializableWorld;
use matcracker\BedcoreProtect\serializable\SerializablePosition;
use pocketmine\level\format\Chunk;
use pocketmine\level\Level;
use pocketmine\math\AxisAlignedBB;
Expand Down Expand Up @@ -81,7 +81,7 @@ public function getWorld(): ?Level
}

/**
* @param SerializableWorld[]|Vector3[] $positions
* @param SerializablePosition[]|Vector3[] $positions
* @return Chunk[]
*/
public function getTouchedChunks(array $positions): array
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

/*
* ___ __ ___ __ __
* / _ )___ ___/ /______ _______ / _ \_______ / /____ ____/ /_
* / _ / -_) _ / __/ _ \/ __/ -_) ___/ __/ _ \/ __/ -_) __/ __/
* /____/\__/\_,_/\__/\___/_/ \__/_/ /_/ \___/\__/\__/\__/\__/
*
* Copyright (C) 2019
* 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 matcracker
* @link https://www.github.com/matcracker/BedcoreProtect
*
*/

declare(strict_types=1);

namespace matcracker\BedcoreProtect\serializable;

abstract class AbstractSerializable
{
/**
* Returns an instance of AbstractSerializable from $object.
* @param $object
* @return static
*/
abstract public static function fromPrimitive($object): self;

/**
* Returns an instance of primitive object from AbstractSerializable.
* @return mixed
*/
abstract public function toPrimitive();
}
54 changes: 32 additions & 22 deletions src/matcracker/BedcoreProtect/serializable/SerializableBlock.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,24 +21,27 @@

namespace matcracker\BedcoreProtect\serializable;

use http\Exception\InvalidArgumentException;
use matcracker\BedcoreProtect\utils\BlockUtils;
use pocketmine\block\Block;
use pocketmine\block\BlockFactory;
use pocketmine\level\Position;
use pocketmine\Server;
use function get_class;

final class SerializableBlock extends SerializableWorld
final class SerializableBlock extends SerializablePosition
{
/** @var string */
private $name;
/** @var int */
private $id;
/** @var int */
private $meta;
/** @var string|null */
private $serializedNbt;

public function __construct(int $id, int $meta, ?int $x, ?int $y, ?int $z, ?string $worldName, ?string $serializedNbt = null)
public function __construct(string $name, int $id, int $meta, ?int $x, ?int $y, ?int $z, ?string $worldName, ?string $serializedNbt = null)
{
parent::__construct($x, $y, $z, $worldName);
parent::__construct((float)$x, (float)$y, (float)$z, $worldName);
$this->name = $name;
$this->id = $id;
$this->meta = $meta;
$this->serializedNbt = $serializedNbt;
Expand All @@ -48,40 +51,47 @@ public function __construct(int $id, int $meta, ?int $x, ?int $y, ?int $z, ?stri
* @param Block $block
* @return SerializableBlock
*/
public static function toSerializableBlock(Block $block): self
public static function fromPrimitive($block): AbstractSerializable
{
$worldName = null;
if (($world = $block->getLevel()) !== null) {
$worldName = $world->getFolderName();
if (!$block instanceof Block) {
throw new InvalidArgumentException("Expected Block instance, got " . get_class($block));
}
return new self($block->getId(), $block->getDamage(), (int)$block->getX(), (int)$block->getY(), (int)$block->getZ(), $worldName, BlockUtils::serializeBlockTileNBT($block));
}

public function toBlock(): Block
{
$world = Server::getInstance()->getLevelByName($this->worldName);
return BlockFactory::get($this->id, $this->meta, new Position($this->x, $this->y, $this->z, $world));
return new self(
$block->getName(),
$block->getId(),
$block->getDamage(),
(int)$block->getX(),
(int)$block->getY(),
(int)$block->getZ(),
parent::fromPrimitive($block)->worldName,
BlockUtils::serializeBlockTileNBT($block)
);
}

/**
* @return int
* @return Block
*/
public function toPrimitive()
{
return BlockFactory::get($this->id, $this->meta, parent::toPrimitive());
}

public function getName(): string
{
return $this->name;
}

public function getId(): int
{
return $this->id;
}

/**
* @return int
*/
public function getMeta(): int
{
return $this->meta;
}

/**
* @return string|null
*/
public function getSerializedNbt(): ?string
{
return $this->serializedNbt;
Expand Down
137 changes: 137 additions & 0 deletions src/matcracker/BedcoreProtect/serializable/SerializableEntity.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
<?php

/*
* ___ __ ___ __ __
* / _ )___ ___/ /______ _______ / _ \_______ / /____ ____/ /_
* / _ / -_) _ / __/ _ \/ __/ -_) ___/ __/ _ \/ __/ -_) __/ __/
* /____/\__/\_,_/\__/\___/_/ \__/_/ /_/ \___/\__/\__/\__/\__/
*
* Copyright (C) 2019
* 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 matcracker
* @link https://www.github.com/matcracker/BedcoreProtect
*
*/

declare(strict_types=1);

namespace matcracker\BedcoreProtect\serializable;

use http\Exception\InvalidArgumentException;
use matcracker\BedcoreProtect\utils\Utils;
use pocketmine\entity\Entity;
use pocketmine\entity\Living;
use pocketmine\Player;
use RuntimeException;
use function get_class;

final class SerializableEntity extends SerializablePosition
{
/** @var string */
private $uuid;
/** @var int */
private $id;
/** @var string */
private $name;
/** @var string */
private $classPath;
/** @var string */
private $address;
/** @var string */
private $serializedNbt;

public function __construct(string $uuid, int $id, string $name, string $classPath, string $address, ?float $x, ?float $y, ?float $z, ?string $worldName, string $serializedNbt)
{
parent::__construct($x, $y, $z, $worldName);
$this->uuid = $uuid;
$this->id = $id;
$this->name = $name;
$this->classPath = $classPath;
$this->address = $address;
$this->serializedNbt = $serializedNbt;
}

/**
* @param Entity $entity
* @return SerializableEntity
*/
public static function fromPrimitive($entity): AbstractSerializable
{
$classPath = get_class($entity);
if (!$entity instanceof Entity) {
throw new InvalidArgumentException("Expected Entity instance, got " . $classPath);
}

$entity->saveNBT();

if ($entity instanceof Living) {
$entity->namedtag->setFloat("Health", $entity->getMaxHealth());
}

return new self(
Utils::getEntityUniqueId($entity),
$entity->getId(),
Utils::getEntityName($entity),
$classPath,
($entity instanceof Player) ? $entity->getAddress() : "127.0.0.1",
(float)$entity->getX(),
(float)$entity->getY(),
(float)$entity->getZ(),
parent::fromPrimitive($entity->asPosition())->worldName,
Utils::serializeNBT($entity->namedtag)
);
}

/**
* @return Entity
*/
public function toPrimitive()
{
if (($level = parent::toPrimitive()->getLevel()) === null) {
throw new RuntimeException("Could not create an entity with \"null\" world.");
}

/** @var Entity $classPath */
$classPath = $this->classPath;
return Entity::createEntity($classPath::NETWORK_ID, $level, Utils::deserializeNBT($this->serializedNbt));
}

public function getUuid(): string
{
return $this->uuid;
}

public function getId(): int
{
return $this->id;
}

public function getAddress(): string
{
return $this->address;
}

public function getClassPath(): string
{
return $this->classPath;
}

public function getName(): string
{
return $this->name;
}

public function getSerializedNbt(): string
{
return $this->serializedNbt;
}

public function __toString(): string
{
return "SerializableEntity({$this->uuid}:{$this->name})({$this->classPath})[{$this->worldName}]";
}
}
37 changes: 17 additions & 20 deletions src/matcracker/BedcoreProtect/serializable/SerializableItem.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,13 @@

namespace matcracker\BedcoreProtect\serializable;

use http\Exception\InvalidArgumentException;
use matcracker\BedcoreProtect\utils\Utils;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
use function get_class;

final class SerializableItem
final class SerializableItem extends AbstractSerializable
{
/** @var int */
private $id;
Expand All @@ -48,44 +50,31 @@ public function __construct(int $id, int $meta, int $count, string $serializedNb
* @param Item $item
* @return SerializableItem
*/
public static function toSerializableItem(Item $item): self
public static function fromPrimitive($item): AbstractSerializable
{
return new self($item->getId(), $item->getDamage(), $item->getCount(), Utils::serializeNBT($item->getNamedTag()));
}
if (!$item instanceof Item) {
throw new InvalidArgumentException("Expected Item instance, got " . get_class($item));
}

public function toItem(): Item
{
return ItemFactory::get($this->id, $this->meta, $this->count, Utils::deserializeNBT($this->serializedNbt));
return new self($item->getId(), $item->getDamage(), $item->getCount(), Utils::serializeNBT($item->getNamedTag()));
}

/**
* @return int
*/
public function getId(): int
{
return $this->id;
}

/**
* @return int
*/
public function getMeta(): int
{
return $this->meta;
}

/**
* @return int
*/
public function getCount(): int
{
return $this->count;
}

/**
* @return string|null
*/
public function getSerializedNbt(): ?string
public function getSerializedNbt(): string
{
return $this->serializedNbt;
}
Expand All @@ -94,4 +83,12 @@ public function __toString(): string
{
return "SerializableItem({$this->id}:{$this->meta})[{$this->count}]";
}

/**
* @return Item
*/
public function toPrimitive()
{
return ItemFactory::get($this->id, $this->meta, $this->count, Utils::deserializeNBT($this->serializedNbt));
}
}
Loading

0 comments on commit c4a0b50

Please sign in to comment.