Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Separate inventory holder info from container & player inventories #6533

Open
wants to merge 32 commits into
base: major-next
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
f98cebb
Separate hotbar from player inventory
dktapps Nov 24, 2024
473bbe6
BaseInventory no longer uses viewers to send updates to players
dktapps Nov 24, 2024
45a4282
First look: Split up Inventory & InventoryWindow
dktapps Nov 24, 2024
dcbf1c7
this bites me every single time
dktapps Nov 24, 2024
9c5df90
Burn more junk
dktapps Nov 24, 2024
1d2b527
Chest block now has responsibility for configuring double chest inven…
dktapps Nov 24, 2024
fe1a8d9
namespace tidy
dktapps Nov 24, 2024
1738355
Remove potentially problematic ephemeral window creation
dktapps Nov 24, 2024
7f58122
Avoid unnecessary repeated calls
dktapps Nov 24, 2024
5c22124
Merge branch 'major-next' into inventory-rework
dktapps Nov 24, 2024
6aa4e4c
CS
dktapps Nov 24, 2024
f4d50a1
Merge branch 'major-next' into inventory-rework
dktapps Nov 24, 2024
4dcc14e
Integrate block container animations and SFX into Block classes by wa…
dktapps Nov 25, 2024
edf4e9d
...
dktapps Nov 25, 2024
d69d8d6
EnchantingTableInventoryWindow: cleanup weakref mess
dktapps Nov 25, 2024
3099129
Merge branch 'major-next' into inventory-rework
dktapps Nov 25, 2024
5a35c25
Merge branch 'major-next' into inventory-rework
dktapps Nov 26, 2024
6578d65
Merge branch 'major-next' into inventory-rework
dktapps Dec 6, 2024
ce4d3ae
Rename Container(Trait) -> ContainerTile(Trait)
dktapps Dec 6, 2024
40574be
Shift inventory management responsibility to World
dktapps Dec 6, 2024
4850bd5
Allow blocks to respond to the contents of their containers being upd…
dktapps Dec 6, 2024
76528b2
Remove dodgy code
dktapps Dec 7, 2024
15bb0c7
Remove CampfireInventory
dktapps Dec 7, 2024
b76db73
Campfire block's inventory is now null if it hasn't been set in the w…
dktapps Dec 7, 2024
b5a69c8
smh
dktapps Dec 7, 2024
ef3d165
Revert "Chest block now has responsibility for configuring double che…
dktapps Dec 7, 2024
4906f5b
...
dktapps Dec 7, 2024
699a85a
Replace DoubleChestInventory with a more generic CombinedInventory
dktapps Dec 7, 2024
9e6e508
stfu
dktapps Dec 7, 2024
3ee78e2
BlockInventoryTrait: include a Block ref instead of Position
dktapps Dec 7, 2024
9949e38
CombinedInventory now propagates updates if its backing inventories w…
dktapps Dec 8, 2024
0fe786a
Rename CombinedInventory -> CombinedInventoryProxy
dktapps Dec 8, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/block/Anvil.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

namespace pocketmine\block;

use pocketmine\block\inventory\AnvilInventory;
use pocketmine\block\inventory\window\AnvilInventoryWindow;
use pocketmine\block\utils\Fallable;
use pocketmine\block\utils\FallableTrait;
use pocketmine\block\utils\HorizontalFacingTrait;
Expand Down Expand Up @@ -83,7 +83,7 @@ public function getSupportType(int $facing) : SupportType{

public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($player instanceof Player){
$player->setCurrentWindow(new AnvilInventory($this->position));
$player->setCurrentWindow(new AnvilInventoryWindow($player, $this));
}

return true;
Expand Down
28 changes: 26 additions & 2 deletions src/block/Barrel.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,25 @@

namespace pocketmine\block;

use pocketmine\block\inventory\window\BlockInventoryWindow;
use pocketmine\block\tile\Barrel as TileBarrel;
use pocketmine\block\utils\AnimatedContainer;
use pocketmine\block\utils\AnimatedContainerTrait;
use pocketmine\block\utils\AnyFacingTrait;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\item\Item;
use pocketmine\math\Facing;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
use pocketmine\world\BlockTransaction;
use pocketmine\world\Position;
use pocketmine\world\sound\BarrelCloseSound;
use pocketmine\world\sound\BarrelOpenSound;
use pocketmine\world\sound\Sound;
use function abs;

class Barrel extends Opaque{
class Barrel extends Opaque implements AnimatedContainer{
use AnimatedContainerTrait;
use AnyFacingTrait;

protected bool $open = false;
Expand Down Expand Up @@ -81,7 +89,7 @@ public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player
return true;
}

$player->setCurrentWindow($barrel->getInventory());
$player->setCurrentWindow(new BlockInventoryWindow($player, $barrel->getInventory(), $this));
}
}

Expand All @@ -91,4 +99,20 @@ public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player
public function getFuelTime() : int{
return 300;
}

protected function getContainerOpenSound() : Sound{
return new BarrelOpenSound();
}

protected function getContainerCloseSound() : Sound{
return new BarrelCloseSound();
}

protected function doContainerAnimation(Position $position, bool $isOpen) : void{
$world = $position->getWorld();
$block = $world->getBlock($position);
if($block instanceof Barrel){
$world->setBlock($position, $block->setOpen($isOpen));
}
}
}
10 changes: 10 additions & 0 deletions src/block/Block.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
use pocketmine\data\runtime\RuntimeDataWriter;
use pocketmine\entity\Entity;
use pocketmine\entity\projectile\Projectile;
use pocketmine\inventory\Inventory;
use pocketmine\item\enchantment\AvailableEnchantmentRegistry;
use pocketmine\item\enchantment\ItemEnchantmentTagRegistry;
use pocketmine\item\enchantment\ItemEnchantmentTags;
Expand Down Expand Up @@ -515,6 +516,15 @@ public function onScheduledUpdate() : void{

}

/**
* Called by the World when a change is detected in a container's inventory at the block's position.
* Use this to do visual updates on the block if needed.
* Don't do any expensive logic in here. It will be called every time a slot of the inventory changes.
*/
public function onContainerUpdate(Inventory $inventory) : void{

}

/**
* Do actions when interacted by Item. Returns if it has done anything
*
Expand Down
27 changes: 16 additions & 11 deletions src/block/BrewingStand.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,12 @@

namespace pocketmine\block;

use pocketmine\block\inventory\window\BrewingStandInventoryWindow;
use pocketmine\block\tile\BrewingStand as TileBrewingStand;
use pocketmine\block\utils\BrewingStandSlot;
use pocketmine\block\utils\SupportType;
use pocketmine\data\runtime\RuntimeDataDescriber;
use pocketmine\inventory\Inventory;
use pocketmine\item\Item;
use pocketmine\math\Axis;
use pocketmine\math\AxisAlignedBB;
Expand Down Expand Up @@ -99,7 +101,7 @@ public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player
if($player instanceof Player){
$stand = $this->position->getWorld()->getTile($this->position);
if($stand instanceof TileBrewingStand && $stand->canOpenWith($item->getCustomName())){
$player->setCurrentWindow($stand->getInventory());
$player->setCurrentWindow(new BrewingStandInventoryWindow($player, $stand->getInventory(), $this));
}
}

Expand All @@ -113,19 +115,22 @@ public function onScheduledUpdate() : void{
if($brewing->onUpdate()){
$world->scheduleDelayedBlockUpdate($this->position, 1);
}
}
}

$changed = false;
foreach(BrewingStandSlot::cases() as $slot){
$occupied = !$brewing->getInventory()->isSlotEmpty($slot->getSlotNumber());
if($occupied !== $this->hasSlot($slot)){
$this->setSlot($slot, $occupied);
$changed = true;
}
public function onContainerUpdate(Inventory $inventory) : void{
$world = $this->position->getWorld();
$changed = false;
foreach(BrewingStandSlot::cases() as $slot){
$occupied = !$inventory->isSlotEmpty($slot->getSlotNumber());
if($occupied !== $this->hasSlot($slot)){
$this->setSlot($slot, $occupied);
$changed = true;
}
}

if($changed){
$world->setBlock($this->position, $this);
}
if($changed){
$world->setBlock($this->position, $this);
}
}
}
38 changes: 22 additions & 16 deletions src/block/Campfire.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@

namespace pocketmine\block;

use pocketmine\block\inventory\CampfireInventory;
use pocketmine\block\tile\Campfire as TileCampfire;
use pocketmine\block\utils\HorizontalFacingTrait;
use pocketmine\block\utils\LightableTrait;
Expand All @@ -38,6 +37,7 @@
use pocketmine\event\block\CampfireCookEvent;
use pocketmine\event\entity\EntityDamageByBlockEvent;
use pocketmine\event\entity\EntityDamageEvent;
use pocketmine\inventory\Inventory;
use pocketmine\item\Durable;
use pocketmine\item\enchantment\VanillaEnchantments;
use pocketmine\item\Item;
Expand Down Expand Up @@ -67,13 +67,11 @@ class Campfire extends Transparent{
LightableTrait::describeBlockOnlyState as encodeLitState;
}

private const UPDATE_INTERVAL_TICKS = 10;

/**
* @deprecated This was added by mistake. It can't be relied on as the inventory won't be initialized if this block
* has never been set in the world.
*/
protected CampfireInventory $inventory;
protected ?Inventory $inventory = null;

/**
* @var int[] slot => ticks
Expand All @@ -93,7 +91,8 @@ public function readStateFromWorld() : Block{
$this->inventory = $tile->getInventory();
$this->cookingTimes = $tile->getCookingTimes();
}else{
$this->inventory = new CampfireInventory($this->position);
$this->inventory = null;
$this->cookingTimes = [];
}

return $this;
Expand Down Expand Up @@ -137,7 +136,7 @@ protected function recalculateCollisionBoxes() : array{
* @deprecated This was added by mistake. It can't be relied on as the inventory won't be initialized if this block
* has never been set in the world.
*/
public function getInventory() : CampfireInventory{
public function getInventory() : ?Inventory{
return $this->inventory;
}

Expand Down Expand Up @@ -200,10 +199,11 @@ public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player
return true;
}

if($this->position->getWorld()->getServer()->getCraftingManager()->getFurnaceRecipeManager($this->getFurnaceType())->match($item) !== null){
$inventory = $this->inventory;
if($inventory !== null && $this->position->getWorld()->getServer()->getCraftingManager()->getFurnaceRecipeManager($this->getFurnaceType())->match($item) !== null){
$ingredient = clone $item;
$ingredient->setCount(1);
if(count($this->inventory->addItem($ingredient)) === 0){
if(count($inventory->addItem($ingredient)) === 0){
$item->pop();
$this->position->getWorld()->addSound($this->position, new ItemFrameAddItemSound());
return true;
Expand Down Expand Up @@ -238,12 +238,12 @@ public function onProjectileHit(Projectile $projectile, RayTraceResult $hitResul
}

public function onScheduledUpdate() : void{
if($this->lit){
$items = $this->inventory->getContents();
if($this->lit && ($inventory = $this->inventory) !== null){
$items = $inventory->getContents();
$furnaceType = $this->getFurnaceType();
$maxCookDuration = $furnaceType->getCookDurationTicks();
foreach($items as $slot => $item){
$this->setCookingTime($slot, min($maxCookDuration, $this->getCookingTime($slot) + self::UPDATE_INTERVAL_TICKS));
$this->setCookingTime($slot, min($maxCookDuration, $this->getCookingTime($slot) + 1));
if($this->getCookingTime($slot) >= $maxCookDuration){
$result =
($recipe = $this->position->getWorld()->getServer()->getCraftingManager()->getFurnaceRecipeManager($furnaceType)->match($item)) instanceof FurnaceRecipe ?
Expand All @@ -257,21 +257,27 @@ public function onScheduledUpdate() : void{
continue;
}

$this->inventory->setItem($slot, VanillaItems::AIR());
$inventory->setItem($slot, VanillaItems::AIR());
$this->setCookingTime($slot, 0);
$this->position->getWorld()->dropItem($this->position->add(0.5, 1, 0.5), $ev->getResult());
}
}
if(count($items) > 0){
$this->position->getWorld()->setBlock($this->position, $this);
$tile = $this->position->getWorld()->getTile($this->position);
if($tile instanceof TileCampfire){
//TODO: we probably need to rethink how these are tracked
$tile->setCookingTimes($this->cookingTimes);
}
if(mt_rand(1, 6) === 1){
$this->position->getWorld()->addSound($this->position, $furnaceType->getCookSound());
}
$this->position->getWorld()->scheduleDelayedBlockUpdate($this->position, self::UPDATE_INTERVAL_TICKS);
$this->position->getWorld()->scheduleDelayedBlockUpdate($this->position, 1);
}
}

public function onContainerUpdate(Inventory $inventory) : void{
$this->position->getWorld()->setBlock($this->position, $this); //update visual state
}

private function extinguish() : void{
$this->position->getWorld()->addSound($this->position, new FireExtinguishSound());
$this->position->getWorld()->setBlock($this->position, $this->setLit(false));
Expand All @@ -280,6 +286,6 @@ private function extinguish() : void{
private function ignite() : void{
$this->position->getWorld()->addSound($this->position, new FlintSteelSound());
$this->position->getWorld()->setBlock($this->position, $this->setLit(true));
$this->position->getWorld()->scheduleDelayedBlockUpdate($this->position, self::UPDATE_INTERVAL_TICKS);
$this->position->getWorld()->scheduleDelayedBlockUpdate($this->position, 1);
}
}
4 changes: 2 additions & 2 deletions src/block/CartographyTable.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

namespace pocketmine\block;

use pocketmine\block\inventory\CartographyTableInventory;
use pocketmine\block\inventory\window\CartographyTableInventoryWindow;
use pocketmine\item\Item;
use pocketmine\math\Vector3;
use pocketmine\player\Player;
Expand All @@ -32,7 +32,7 @@ final class CartographyTable extends Opaque{

public function onInteract(Item $item, int $face, Vector3 $clickVector, ?Player $player = null, array &$returnedItems = []) : bool{
if($player !== null){
$player->setCurrentWindow(new CartographyTableInventory($this->position));
$player->setCurrentWindow(new CartographyTableInventoryWindow($player, $this));
}

return true;
Expand Down
Loading
Loading