Commit Graph

14 Commits

Author SHA1 Message Date
644f73aa84 Separate inventory holder info from container & player inventories (#6533)
This PR breaks the cyclic dependency between `Inventory` and its holder, which unblocks a lot of new developments.

### Related issues & PRs
- Fixes #5033
- Removes a blocker for #6147 (which in turn means that async tasks will eventually be able to work with tiles)
- Removes a blocker for #2684

## Changes
### API changes
- `Player->getCurrentWindow()` now returns `?InventoryWindow` instead of `?Inventory`
- `Player->setCurrentWindow()` now accepts `?InventoryWindow` instead of `?Inventory`
- `InventoryWindow` introduced, which is created for each player viewing the inventory, provides decorative information like holder info for `InventoryTransactionEvent`, and is destroyed when the window is closed, eliminating cyclic references
- Added:
  - `player\InventoryWindow`
  - `player\PlayerInventoryWindow` - wraps all permanent inventories of Player with type info for transactions
  - `inventory\Hotbar` - replaces all hotbar usages in `PlayerInventory`
  - `Human->getHotbar()`
  - `Human->getMainHandItem()`, `Human->setMainHandItem()`, `Human->getOffHandItem()`, `Human->setOffHandItem()`
  - `block\utils\AnimatedContainerLike` & `block\utils\AnimatedContainerLikeTrait` (for chests, shulkerboxes, etc)
  - `block\utils\Container` & `block\utils\ContainerTrait` for blocks containing items (chests, etc)
  - `block\utils\MenuAccessor` implemented by all blocks that can open inventory menus
  - `block\utils\MenuAccessorTrait` used by blocks with menus but without inventories (anvils, crafting tables etc)
- Removed:
  - `inventory\DelegateInventory` (only used for ender chests)
  - `inventory\PlayerInventory`,
  - `inventory\PlayerOffHandInventory`,
  - `inventory\PlayerCraftingInventory`,
  - `inventory\PlayerCursorInventory` - these have all been internally replaced by `SimpleInventory` & they will appear as `PlayerInventoryWindow` in transactions (check `getType()` against the `PlayerInventoryWindow::TYPE_*` constants to identify them)
  - `block\inventory\AnimatedBlockInventoryTrait`, (blocks now handle this logic directly using `AnimatedContainer` and `AnimatedContainerTrait`)
  - `block\inventory\BlockInventoryTrait`,
  - `block\inventory\BlockInventory`
- Most `BlockInventory` classes have been transitioned to `InventoryWindow` wrappers
- Tiles now all use `SimpleInventory` internally (no cyclic references) except for `Chest` (which uses `CombinedInventory`, without holder info)
- `InventoryOpenEvent` and `InventoryCloseEvent` now provide `InventoryWindow` instead of `Inventory` (to provide type information)
- `InventoryTransaction` and `SlotChangeAction` now provide `InventoryWindow` instead of `Inventory`
- Renamed `TransactionBuilderInventory` to `SlotChangeActionBuilder`
- `TransactionBuilderInventory->getBuilder()` now accepts `InventoryWindow` instead of `Inventory`
- `DoubleChestInventory` superseded by `CombinedInventory` - this new class allows combining any number of inventories behind a single object; mainly used for double chests but plugins could use it to do lots of fun things

### Impacts to plugins
Plugins can now do the following:
```php
$block = $world->getBlockAt($x, $y, $z);
if($block instanceof MenuAccessor){
    $block->openToUnchecked($player);
}
```
As compared to the old way:
```php
$tile = $world->getTileAt($x, $y, $z);
if($tile instanceof Container){
    $player->setCurrentWindow($tile->getInventory());
}
```

#### Advantages
- No tile access needed
- Works for menu blocks without inventories as well as container blocks
- Less code

### Behavioural changes
Inventories no longer keep permanent cyclic references to their holders.

## Backwards compatibility
This makes significant BC breaks. However, all changes are able to be adapted to and the same amount of information is present on all APIs and events.

## Follow-up
- Implement #6147 
- Support inventory inheritance when copying blocks from one position to another
2025-09-02 19:23:16 +01:00
38d6284671 Use PHP-CS-Fixer to enforce file header presence 2022-06-04 17:34:49 +01:00
0c012ca5d9 Replace usages of ItemFactory in tests with VanillaItems 2021-12-06 23:45:36 +00:00
62f11360ee Added unit tests for getAddableItemQuantity() 2021-10-11 21:52:27 +01:00
61b7faae08 Simplify BaseInventoryTest 2021-08-04 21:01:01 +01:00
a6039ad733 Fixed InventoryHelpersTrait::addItem() cannot add items with a count greater than maxstack (#4283) 2021-06-26 16:48:53 +01:00
15e5bdb210 BaseInventory::addItem(item1,item2,item3) now has the same behaviour as multiple separate addItem() calls (#4237)
fixes #1412
2021-06-17 21:05:24 +01:00
f909557529 Cleaned up implementations for EnderChestInventory/DoubleChestInventory
previously, these were forced to extend BaseInventory because of the amount of crap in Inventory's interface.
This meant that these inventories had their own slots storage, which would be _mostly_ unused because these inventories aren't real inventories, but rather just delegates.
This lead to a variety of bugs in the past, such as certain API methods on BaseInventory not working correctly for DoubleChestInventory in particular.

Now, BaseInventory just implements the functional part of the inventory implementation, leaving the storage system up to the implementation.
A SimpleInventory class is provided with a simple SplFixedArray storage backing, which is used by most inventories.
EnderChestInventory and DoubleChestInventory now extend BaseInventory directly, and implement custom methods for dealing with their delegates.
2021-05-09 20:51:16 +01:00
5a94af40e2 Convert ItemFactory to singleton 2020-04-24 00:18:31 +01:00
fb1126797a Merge branch 'stable' 2020-02-07 18:13:55 +00:00
e12618c705 tests/phpunit: added missing native typehints 2020-02-06 12:13:42 +00:00
1fee70abfb Item no longer implements ItemIds 2019-07-19 17:43:06 +01:00
9904810f24 BaseInventory: Remove getDefaultSize()
it's possible to want to initialize dynamically-sized inventories which don't have a default size.
2019-03-22 19:21:41 +00:00
a30b1fb6d5 Inventory: Add failing test case for itemstack NBT duplication 2019-03-03 11:11:33 +00:00