mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-05-09 15:29:47 +00:00
Shift inventory management responsibility to World
this removes a bunch of problematic Position usages from Tile, as well as getting rid of a bunch of code duplication.
This commit is contained in:
parent
ce4d3aef9e
commit
40574be333
@ -276,6 +276,9 @@ class Campfire extends Transparent{
|
||||
$this->position->getWorld()->addSound($this->position, $furnaceType->getCookSound());
|
||||
}
|
||||
$this->position->getWorld()->scheduleDelayedBlockUpdate($this->position, self::UPDATE_INTERVAL_TICKS);
|
||||
}else{
|
||||
//make sure the visual state is updated when items are added
|
||||
$this->position->getWorld()->setBlock($this->position, $this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -50,13 +50,6 @@ class Barrel extends Spawnable implements ContainerTile, Nameable{
|
||||
$this->saveItems($nbt);
|
||||
}
|
||||
|
||||
public function close() : void{
|
||||
if(!$this->closed){
|
||||
$this->inventory->removeAllViewers();
|
||||
parent::close();
|
||||
}
|
||||
}
|
||||
|
||||
public function getInventory() : Inventory{
|
||||
return $this->inventory;
|
||||
}
|
||||
|
@ -27,7 +27,6 @@ use pocketmine\block\inventory\window\BrewingStandInventoryWindow;
|
||||
use pocketmine\crafting\BrewingRecipe;
|
||||
use pocketmine\event\block\BrewingFuelUseEvent;
|
||||
use pocketmine\event\block\BrewItemEvent;
|
||||
use pocketmine\inventory\CallbackInventoryListener;
|
||||
use pocketmine\inventory\Inventory;
|
||||
use pocketmine\inventory\SimpleInventory;
|
||||
use pocketmine\item\Item;
|
||||
@ -64,9 +63,6 @@ class BrewingStand extends Spawnable implements ContainerTile, Nameable{
|
||||
public function __construct(World $world, Vector3 $pos){
|
||||
parent::__construct($world, $pos);
|
||||
$this->inventory = new SimpleInventory(5);
|
||||
$this->inventory->getListeners()->add(CallbackInventoryListener::onAnyChange(static function(Inventory $unused) use ($world, $pos) : void{
|
||||
$world->scheduleDelayedBlockUpdate($pos, 1);
|
||||
}));
|
||||
}
|
||||
|
||||
public function readSaveData(CompoundTag $nbt) : void{
|
||||
@ -105,14 +101,6 @@ class BrewingStand extends Spawnable implements ContainerTile, Nameable{
|
||||
return "Brewing Stand";
|
||||
}
|
||||
|
||||
public function close() : void{
|
||||
if(!$this->closed){
|
||||
$this->inventory->removeAllViewers();
|
||||
|
||||
parent::close();
|
||||
}
|
||||
}
|
||||
|
||||
public function getInventory() : Inventory{
|
||||
return $this->inventory;
|
||||
}
|
||||
|
@ -23,10 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace pocketmine\block\tile;
|
||||
|
||||
use pocketmine\block\Campfire as BlockCampfire;
|
||||
use pocketmine\block\inventory\CampfireInventory;
|
||||
use pocketmine\inventory\CallbackInventoryListener;
|
||||
use pocketmine\inventory\Inventory;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\nbt\tag\CompoundTag;
|
||||
@ -54,14 +51,6 @@ class Campfire extends Spawnable implements ContainerTile{
|
||||
public function __construct(World $world, Vector3 $pos){
|
||||
parent::__construct($world, $pos);
|
||||
$this->inventory = new CampfireInventory();
|
||||
$this->inventory->getListeners()->add(CallbackInventoryListener::onAnyChange(
|
||||
static function(Inventory $unused) use ($world, $pos) : void{
|
||||
$block = $world->getBlock($pos);
|
||||
if($block instanceof BlockCampfire){
|
||||
$world->setBlock($pos, $block);
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
public function getInventory() : CampfireInventory{
|
||||
|
@ -94,8 +94,6 @@ class Chest extends Spawnable implements ContainerTile, Nameable{
|
||||
|
||||
public function close() : void{
|
||||
if(!$this->closed){
|
||||
$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)){
|
||||
$this->doubleInventory->removeAllViewers();
|
||||
|
@ -29,7 +29,6 @@ use pocketmine\crafting\FurnaceRecipe;
|
||||
use pocketmine\crafting\FurnaceType;
|
||||
use pocketmine\event\inventory\FurnaceBurnEvent;
|
||||
use pocketmine\event\inventory\FurnaceSmeltEvent;
|
||||
use pocketmine\inventory\CallbackInventoryListener;
|
||||
use pocketmine\inventory\Inventory;
|
||||
use pocketmine\inventory\SimpleInventory;
|
||||
use pocketmine\item\Item;
|
||||
@ -57,11 +56,6 @@ abstract class Furnace extends Spawnable implements ContainerTile, Nameable{
|
||||
public function __construct(World $world, Vector3 $pos){
|
||||
parent::__construct($world, $pos);
|
||||
$this->inventory = new SimpleInventory(3);
|
||||
$this->inventory->getListeners()->add(CallbackInventoryListener::onAnyChange(
|
||||
static function(Inventory $unused) use ($world, $pos) : void{
|
||||
$world->scheduleDelayedBlockUpdate($pos, 1);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
public function readSaveData(CompoundTag $nbt) : void{
|
||||
@ -79,10 +73,6 @@ abstract class Furnace extends Spawnable implements ContainerTile, Nameable{
|
||||
|
||||
$this->loadName($nbt);
|
||||
$this->loadItems($nbt);
|
||||
|
||||
if($this->remainingFuelTime > 0){
|
||||
$this->position->getWorld()->scheduleDelayedBlockUpdate($this->position, 1);
|
||||
}
|
||||
}
|
||||
|
||||
protected function writeSaveData(CompoundTag $nbt) : void{
|
||||
@ -97,14 +87,6 @@ abstract class Furnace extends Spawnable implements ContainerTile, Nameable{
|
||||
return "Furnace";
|
||||
}
|
||||
|
||||
public function close() : void{
|
||||
if(!$this->closed){
|
||||
$this->inventory->removeAllViewers();
|
||||
|
||||
parent::close();
|
||||
}
|
||||
}
|
||||
|
||||
public function getInventory() : Inventory{
|
||||
return $this->inventory;
|
||||
}
|
||||
|
@ -58,14 +58,6 @@ class Hopper extends Spawnable implements ContainerTile, Nameable{
|
||||
$nbt->setInt(self::TAG_TRANSFER_COOLDOWN, $this->transferCooldown);
|
||||
}
|
||||
|
||||
public function close() : void{
|
||||
if(!$this->closed){
|
||||
$this->inventory->removeAllViewers();
|
||||
|
||||
parent::close();
|
||||
}
|
||||
}
|
||||
|
||||
public function getDefaultName() : string{
|
||||
return "Hopper";
|
||||
}
|
||||
|
@ -80,13 +80,6 @@ class ShulkerBox extends Spawnable implements ContainerTile, Nameable{
|
||||
}
|
||||
}
|
||||
|
||||
public function close() : void{
|
||||
if(!$this->closed){
|
||||
$this->inventory->removeAllViewers();
|
||||
parent::close();
|
||||
}
|
||||
}
|
||||
|
||||
protected function onBlockDestroyedHook() : void{
|
||||
//NOOP override of ContainerTrait - shulker boxes retain their contents when destroyed
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ use pocketmine\block\Air;
|
||||
use pocketmine\block\Block;
|
||||
use pocketmine\block\BlockTypeIds;
|
||||
use pocketmine\block\RuntimeBlockStateRegistry;
|
||||
use pocketmine\block\tile\ContainerTile;
|
||||
use pocketmine\block\tile\Spawnable;
|
||||
use pocketmine\block\tile\Tile;
|
||||
use pocketmine\block\tile\TileFactory;
|
||||
@ -57,6 +58,8 @@ use pocketmine\event\world\WorldDisplayNameChangeEvent;
|
||||
use pocketmine\event\world\WorldParticleEvent;
|
||||
use pocketmine\event\world\WorldSaveEvent;
|
||||
use pocketmine\event\world\WorldSoundEvent;
|
||||
use pocketmine\inventory\Inventory;
|
||||
use pocketmine\inventory\InventoryListener;
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\item\ItemUseResult;
|
||||
use pocketmine\item\LegacyStringToItemParser;
|
||||
@ -144,7 +147,7 @@ use const PHP_INT_MIN;
|
||||
* @phpstan-type BlockPosHash int
|
||||
* @phpstan-type ChunkBlockPosHash int
|
||||
*/
|
||||
class World implements ChunkManager{
|
||||
class World implements ChunkManager, InventoryListener{
|
||||
|
||||
private static int $worldIdCounter = 1;
|
||||
|
||||
@ -282,6 +285,12 @@ class World implements ChunkManager{
|
||||
*/
|
||||
private array $chunks = [];
|
||||
|
||||
/**
|
||||
* @var Vector3[]|\WeakMap
|
||||
* @phpstan-var \WeakMap<Inventory, Vector3>
|
||||
*/
|
||||
private \WeakMap $containerToBlockPositionMap;
|
||||
|
||||
/**
|
||||
* @var Vector3[][] chunkHash => [relativeBlockHash => Vector3]
|
||||
* @phpstan-var array<ChunkPosHash, array<ChunkBlockPosHash, Vector3>>
|
||||
@ -506,6 +515,8 @@ class World implements ChunkManager{
|
||||
}
|
||||
});
|
||||
|
||||
$this->containerToBlockPositionMap = new \WeakMap();
|
||||
|
||||
$this->scheduledBlockUpdateQueue = new ReversePriorityQueue();
|
||||
$this->scheduledBlockUpdateQueue->setExtractFlags(\SplPriorityQueue::EXTR_BOTH);
|
||||
|
||||
@ -2787,6 +2798,10 @@ class World implements ChunkManager{
|
||||
|
||||
//delegate tile ticking to the corresponding block
|
||||
$this->scheduleDelayedBlockUpdate($pos->asVector3(), 1);
|
||||
if($tile instanceof ContainerTile){
|
||||
$tile->getInventory()->getListeners()->add($this);
|
||||
$this->containerToBlockPositionMap[$tile->getInventory()] = $pos->asVector3();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2805,11 +2820,40 @@ class World implements ChunkManager{
|
||||
if(isset($this->chunks[$hash = World::chunkHash($chunkX, $chunkZ)])){
|
||||
$this->chunks[$hash]->removeTile($tile);
|
||||
}
|
||||
if($tile instanceof ContainerTile){
|
||||
$inventory = $tile->getInventory();
|
||||
$inventory->removeAllViewers();
|
||||
$inventory->getListeners()->remove($this);
|
||||
unset($this->containerToBlockPositionMap[$inventory]);
|
||||
}
|
||||
foreach($this->getChunkListeners($chunkX, $chunkZ) as $listener){
|
||||
$listener->onBlockChanged($pos->asVector3());
|
||||
}
|
||||
}
|
||||
|
||||
private function notifyInventoryUpdate(Inventory $inventory) : void{
|
||||
$blockPosition = $this->containerToBlockPositionMap[$inventory] ?? null;
|
||||
if($blockPosition !== null){
|
||||
$this->scheduleDelayedBlockUpdate($blockPosition, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @see InventoryListener
|
||||
*/
|
||||
public function onSlotChange(Inventory $inventory, int $slot, Item $oldItem) : void{
|
||||
$this->notifyInventoryUpdate($inventory);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @see InventoryListener
|
||||
*/
|
||||
public function onContentChange(Inventory $inventory, array $oldContents) : void{
|
||||
$this->notifyInventoryUpdate($inventory);
|
||||
}
|
||||
|
||||
public function isChunkInUse(int $x, int $z) : bool{
|
||||
return isset($this->chunkLoaders[$index = World::chunkHash($x, $z)]) && count($this->chunkLoaders[$index]) > 0;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user