previously we had to make sure that the two chests shared the same instance, so that the viewer
lists would be properly updated. Now, instead, we can just combine the viewer lists of the individual
chests, which is a lot cleaner.
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
TypeConverter: Strip unnecessary NBT from clientbound items
Item containers like shulker boxes, or chests with block entity data obtained with ctrl+middle click, will often have extremely large NBT payloads.
This problem gets exponentially worse in cases where it's possible to nest inventories, as in #4665.
We can't easily address this at the core level, because tiles are not able to exist within items (due to position requirement)
so we don't have a good way to avoid this useless NBT in the first place. However, we can strip it before the item is sent to
the client, which dramatically reduces the network costs of such items, as well as removing any reason the client could have
to send such enormous items to the server.
A fully loaded shulker box with written books now takes only 5-6 KB on the wire instead of ~1 MB, which is a substantial improvement.
Dealing with this in a less hacky way is currently blocked on #6147.
* Deprecate BaseSign get/set/updateText(), add get/set/updateFaceText() which accepts true/false for front/back
* add isFrontFace() to SignChangeEvent
* add optional frontFace to Player::openSignEditor()
* add BaseSign::getFacingDegrees() and getHitboxCenter() which need to be implemented by subclasses
we used to have this to prevent dependence on client ordering, and make ordering consistently not work.
However, since the introduction of the ItemStackRequest protocol, we don't expect to see client actions
in the wrong order anymore, so this shouldn't be needed anymore.
closes#6701
if we have only a name (the majority case), we can just return the name directly instead of an object.
this massively reduces the amount of noise in the files as seen in pmmp/BedrockData@f814036229