mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-06-23 20:04:02 +00:00
Duct tape for inventory transactions, removed ContainerSetSlotPacket
This commit is contained in:
parent
5208ad885c
commit
74ee94b385
@ -78,6 +78,7 @@ use pocketmine\inventory\BigShapedRecipe;
|
|||||||
use pocketmine\inventory\BigShapelessRecipe;
|
use pocketmine\inventory\BigShapelessRecipe;
|
||||||
use pocketmine\inventory\FurnaceInventory;
|
use pocketmine\inventory\FurnaceInventory;
|
||||||
use pocketmine\inventory\Inventory;
|
use pocketmine\inventory\Inventory;
|
||||||
|
use pocketmine\inventory\PlayerCursorInventory;
|
||||||
use pocketmine\inventory\PlayerInventory;
|
use pocketmine\inventory\PlayerInventory;
|
||||||
use pocketmine\inventory\ShapedRecipe;
|
use pocketmine\inventory\ShapedRecipe;
|
||||||
use pocketmine\inventory\ShapelessRecipe;
|
use pocketmine\inventory\ShapelessRecipe;
|
||||||
@ -116,7 +117,6 @@ use pocketmine\network\mcpe\protocol\ChunkRadiusUpdatedPacket;
|
|||||||
use pocketmine\network\mcpe\protocol\ClientToServerHandshakePacket;
|
use pocketmine\network\mcpe\protocol\ClientToServerHandshakePacket;
|
||||||
use pocketmine\network\mcpe\protocol\CommandBlockUpdatePacket;
|
use pocketmine\network\mcpe\protocol\CommandBlockUpdatePacket;
|
||||||
use pocketmine\network\mcpe\protocol\ContainerClosePacket;
|
use pocketmine\network\mcpe\protocol\ContainerClosePacket;
|
||||||
use pocketmine\network\mcpe\protocol\ContainerSetSlotPacket;
|
|
||||||
use pocketmine\network\mcpe\protocol\CraftingEventPacket;
|
use pocketmine\network\mcpe\protocol\CraftingEventPacket;
|
||||||
use pocketmine\network\mcpe\protocol\DataPacket;
|
use pocketmine\network\mcpe\protocol\DataPacket;
|
||||||
use pocketmine\network\mcpe\protocol\DisconnectPacket;
|
use pocketmine\network\mcpe\protocol\DisconnectPacket;
|
||||||
@ -239,6 +239,9 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
protected $currentTransaction = null;
|
protected $currentTransaction = null;
|
||||||
public $craftingType = 0; //0 = 2x2 crafting, 1 = 3x3 crafting, 2 = stonecutter
|
public $craftingType = 0; //0 = 2x2 crafting, 1 = 3x3 crafting, 2 = stonecutter
|
||||||
|
|
||||||
|
/** @var PlayerCursorInventory */
|
||||||
|
protected $cursorInventory;
|
||||||
|
|
||||||
public $creationTime = 0;
|
public $creationTime = 0;
|
||||||
|
|
||||||
protected $randomClientId;
|
protected $randomClientId;
|
||||||
@ -2149,13 +2152,39 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Don't expect much from this handler. Most of it is roughly hacked and duct-taped together.
|
||||||
|
*
|
||||||
|
* @param InventoryTransactionPacket $packet
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
public function handleInventoryTransaction(InventoryTransactionPacket $packet) : bool{
|
public function handleInventoryTransaction(InventoryTransactionPacket $packet) : bool{
|
||||||
switch($packet->transactionData->transactionType){
|
switch($packet->transactionData->transactionType){
|
||||||
case 0:
|
case InventoryTransactionPacket::TYPE_NORMAL:
|
||||||
//normal inventory transfer (TODO handle)
|
$transaction = new SimpleTransactionGroup($this);
|
||||||
break;
|
|
||||||
case InventoryTransactionPacket::TYPE_USE_ITEM:
|
|
||||||
|
|
||||||
|
foreach($packet->actions as $action){
|
||||||
|
if($action->inventorySource->sourceType !== InventoryTransactionPacket::SOURCE_CONTAINER){
|
||||||
|
return false; //TODO: handle other source types
|
||||||
|
}
|
||||||
|
|
||||||
|
if($action->inventorySource->containerId === ContainerIds::ARMOR){
|
||||||
|
$transaction->addTransaction(new BaseTransaction($this->inventory, $action->inventorySlot + $this->inventory->getSize(), $action->oldItem, $action->newItem));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$transaction->addTransaction(new BaseTransaction($this->windowIndex[$action->inventorySource->containerId], $action->inventorySlot, $action->oldItem, $action->newItem));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!$transaction->execute()){
|
||||||
|
//need to resend/revert/whatever (TODO)
|
||||||
|
return false; //oops!
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: fix achievement for getting iron from furnace
|
||||||
|
|
||||||
|
return true;
|
||||||
|
case InventoryTransactionPacket::TYPE_USE_ITEM:
|
||||||
$blockVector = new Vector3($packet->transactionData->x, $packet->transactionData->y, $packet->transactionData->z);
|
$blockVector = new Vector3($packet->transactionData->x, $packet->transactionData->y, $packet->transactionData->z);
|
||||||
$face = $packet->transactionData->face;
|
$face = $packet->transactionData->face;
|
||||||
|
|
||||||
@ -2834,91 +2863,6 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function handleContainerSetSlot(ContainerSetSlotPacket $packet) : bool{
|
|
||||||
if($this->spawned === false or !$this->isAlive()){
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if($packet->slot < 0){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch($packet->windowid){
|
|
||||||
case ContainerIds::INVENTORY: //Normal inventory change
|
|
||||||
if($packet->slot >= $this->inventory->getSize()){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$transaction = new BaseTransaction($this->inventory, $packet->slot, $this->inventory->getItem($packet->slot), $packet->item);
|
|
||||||
break;
|
|
||||||
case ContainerIds::ARMOR: //Armour change
|
|
||||||
if($packet->slot >= 4){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$transaction = new BaseTransaction($this->inventory, $packet->slot + $this->inventory->getSize(), $this->inventory->getArmorItem($packet->slot), $packet->item);
|
|
||||||
break;
|
|
||||||
case ContainerIds::HOTBAR: //Hotbar link update
|
|
||||||
//hotbarSlot 0-8, slot 9-44
|
|
||||||
$this->inventory->setHotbarSlotIndex($packet->hotbarSlot, $packet->slot - 9);
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
if(!isset($this->windowIndex[$packet->windowid])){
|
|
||||||
return false; //unknown windowID and/or not matching any open windows
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->craftingType = 0;
|
|
||||||
$inv = $this->windowIndex[$packet->windowid];
|
|
||||||
$transaction = new BaseTransaction($inv, $packet->slot, $inv->getItem($packet->slot), $packet->item);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if($transaction->getSourceItem()->equals($transaction->getTargetItem()) and $transaction->getTargetItem()->getCount() === $transaction->getSourceItem()->getCount()){ //No changes!
|
|
||||||
//No changes, just a local inventory update sent by the client
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if($this->currentTransaction === null or $this->currentTransaction->getCreationTime() < (microtime(true) - 8)){
|
|
||||||
if($this->currentTransaction !== null){
|
|
||||||
foreach($this->currentTransaction->getInventories() as $inventory){
|
|
||||||
if($inventory instanceof PlayerInventory){
|
|
||||||
$inventory->sendArmorContents($this);
|
|
||||||
}
|
|
||||||
$inventory->sendContents($this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$this->currentTransaction = new SimpleTransactionGroup($this);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->currentTransaction->addTransaction($transaction);
|
|
||||||
|
|
||||||
if($this->currentTransaction->canExecute()){
|
|
||||||
$achievements = [];
|
|
||||||
foreach($this->currentTransaction->getTransactions() as $ts){
|
|
||||||
$inv = $ts->getInventory();
|
|
||||||
if($inv instanceof FurnaceInventory){
|
|
||||||
if($ts->getSlot() === 2){
|
|
||||||
switch($inv->getResult()->getId()){
|
|
||||||
case Item::IRON_INGOT:
|
|
||||||
$achievements[] = "acquireIron";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if($this->currentTransaction->execute()){
|
|
||||||
foreach($achievements as $a){
|
|
||||||
$this->awardAchievement($a);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->currentTransaction = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function handleCraftingEvent(CraftingEventPacket $packet) : bool{
|
public function handleCraftingEvent(CraftingEventPacket $packet) : bool{
|
||||||
if($this->spawned === false or !$this->isAlive()){
|
if($this->spawned === false or !$this->isAlive()){
|
||||||
return true;
|
return true;
|
||||||
@ -3846,6 +3790,9 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
|
|||||||
protected function addDefaultWindows(){
|
protected function addDefaultWindows(){
|
||||||
$this->addWindow($this->getInventory(), ContainerIds::INVENTORY);
|
$this->addWindow($this->getInventory(), ContainerIds::INVENTORY);
|
||||||
|
|
||||||
|
$this->cursorInventory = new PlayerCursorInventory($this);
|
||||||
|
$this->addWindow($this->cursorInventory, ContainerIds::CURSOR);
|
||||||
|
|
||||||
//TODO: more windows
|
//TODO: more windows
|
||||||
}
|
}
|
||||||
|
|
||||||
|
91
src/pocketmine/inventory/PlayerCursorInventory.php
Normal file
91
src/pocketmine/inventory/PlayerCursorInventory.php
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* ____ _ _ __ __ _ __ __ ____
|
||||||
|
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
||||||
|
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
||||||
|
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
||||||
|
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
||||||
|
*
|
||||||
|
* 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 PocketMine Team
|
||||||
|
* @link http://www.pocketmine.net/
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace pocketmine\inventory;
|
||||||
|
|
||||||
|
use pocketmine\network\mcpe\protocol\InventorySlotPacket;
|
||||||
|
use pocketmine\network\mcpe\protocol\types\ContainerIds;
|
||||||
|
use pocketmine\network\mcpe\protocol\types\WindowTypes;
|
||||||
|
use pocketmine\Player;
|
||||||
|
|
||||||
|
class PlayerCursorInventory extends BaseInventory{
|
||||||
|
/** @var Player */
|
||||||
|
protected $holder;
|
||||||
|
|
||||||
|
public function __construct(Player $holder){
|
||||||
|
parent::__construct($holder);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getName() : string{
|
||||||
|
return "Cursor";
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDefaultSize() : int{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setSize(int $size){
|
||||||
|
throw new \BadMethodCallException("Cursor can only carry one item at a time");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getNetworkType() : int{
|
||||||
|
return WindowTypes::INVENTORY; //This should never be spawned to clients
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $index
|
||||||
|
* @param Player|Player[] $target
|
||||||
|
*/
|
||||||
|
public function sendSlot(int $index, $target){
|
||||||
|
if($target instanceof Player){
|
||||||
|
$target = [$target];
|
||||||
|
}
|
||||||
|
|
||||||
|
$pk = new InventorySlotPacket();
|
||||||
|
$pk->inventorySlot = $index;
|
||||||
|
$pk->item = clone $this->getItem($index);
|
||||||
|
|
||||||
|
foreach($target as $player){
|
||||||
|
if($player === $this->getHolder()){
|
||||||
|
/** @var Player $player */
|
||||||
|
$pk->windowId = ContainerIds::CURSOR;
|
||||||
|
$player->dataPacket(clone $pk);
|
||||||
|
}else{
|
||||||
|
if(($id = $player->getWindowId($this)) === ContainerIds::NONE){
|
||||||
|
$this->close($player);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$pk->windowId = $id;
|
||||||
|
$player->dataPacket(clone $pk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This override is here for documentation and code completion purposes only.
|
||||||
|
* @return Player
|
||||||
|
*/
|
||||||
|
public function getHolder(){
|
||||||
|
return $this->holder;
|
||||||
|
}
|
||||||
|
}
|
@ -35,7 +35,6 @@ use pocketmine\network\mcpe\protocol\ClientToServerHandshakePacket;
|
|||||||
use pocketmine\network\mcpe\protocol\CommandBlockUpdatePacket;
|
use pocketmine\network\mcpe\protocol\CommandBlockUpdatePacket;
|
||||||
use pocketmine\network\mcpe\protocol\CommandRequestPacket;
|
use pocketmine\network\mcpe\protocol\CommandRequestPacket;
|
||||||
use pocketmine\network\mcpe\protocol\ContainerClosePacket;
|
use pocketmine\network\mcpe\protocol\ContainerClosePacket;
|
||||||
use pocketmine\network\mcpe\protocol\ContainerSetSlotPacket;
|
|
||||||
use pocketmine\network\mcpe\protocol\CraftingEventPacket;
|
use pocketmine\network\mcpe\protocol\CraftingEventPacket;
|
||||||
use pocketmine\network\mcpe\protocol\DataPacket;
|
use pocketmine\network\mcpe\protocol\DataPacket;
|
||||||
use pocketmine\network\mcpe\protocol\DropItemPacket;
|
use pocketmine\network\mcpe\protocol\DropItemPacket;
|
||||||
@ -183,16 +182,6 @@ class PlayerNetworkSessionAdapter extends NetworkSession{
|
|||||||
return $this->player->handlePlayerHotbar($packet);
|
return $this->player->handlePlayerHotbar($packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO: REMOVE
|
|
||||||
* @param ContainerSetSlotPacket $packet
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function handleContainerSetSlot(ContainerSetSlotPacket $packet) : bool{
|
|
||||||
return $this->player->handleContainerSetSlot($packet);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function handleCraftingEvent(CraftingEventPacket $packet) : bool{
|
public function handleCraftingEvent(CraftingEventPacket $packet) : bool{
|
||||||
return $this->player->handleCraftingEvent($packet);
|
return $this->player->handleCraftingEvent($packet);
|
||||||
}
|
}
|
||||||
|
@ -1,64 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
*
|
|
||||||
* ____ _ _ __ __ _ __ __ ____
|
|
||||||
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
|
|
||||||
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
|
|
||||||
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
|
|
||||||
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
|
|
||||||
*
|
|
||||||
* 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 PocketMine Team
|
|
||||||
* @link http://www.pocketmine.net/
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace pocketmine\network\mcpe\protocol;
|
|
||||||
|
|
||||||
#include <rules/DataPacket.h>
|
|
||||||
|
|
||||||
use pocketmine\item\Item;
|
|
||||||
use pocketmine\network\mcpe\NetworkSession;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @removed
|
|
||||||
*/
|
|
||||||
class ContainerSetSlotPacket extends DataPacket{
|
|
||||||
const NETWORK_ID = ProtocolInfo::CONTAINER_SET_SLOT_PACKET;
|
|
||||||
|
|
||||||
public $windowid;
|
|
||||||
public $slot;
|
|
||||||
public $hotbarSlot = 0;
|
|
||||||
/** @var Item */
|
|
||||||
public $item;
|
|
||||||
public $selectSlot = 0;
|
|
||||||
|
|
||||||
protected function decodePayload(){
|
|
||||||
$this->windowid = $this->getByte();
|
|
||||||
$this->slot = $this->getVarInt();
|
|
||||||
$this->hotbarSlot = $this->getVarInt();
|
|
||||||
$this->item = $this->getSlot();
|
|
||||||
$this->selectSlot = $this->getByte();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function encodePayload(){
|
|
||||||
$this->putByte($this->windowid);
|
|
||||||
$this->putVarInt($this->slot);
|
|
||||||
$this->putVarInt($this->hotbarSlot);
|
|
||||||
$this->putSlot($this->item);
|
|
||||||
$this->putByte($this->selectSlot);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function handle(NetworkSession $session) : bool{
|
|
||||||
return $session->handleContainerSetSlot($this);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user