mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-06 01:46:04 +00:00
Hotbar/inventory bugfixes (#399)
- Fixed most issues with item equipment in creative - Added save and restore of currently-held item - Reset hotbar on death, added API method PlayerInventory->resetHotbar() - Creative players now have more leeway to get items, alleviates issues with item equipment in desktop GUI - Fixed creative players wearing armour - Found unknown field in ContainerSetSlotPacket - Removed outdated/redundant constants - Use a case statement in ContainerSetSlotPacket handler, added handling for 0x7a hotbar slot link update
This commit is contained in:
@ -152,9 +152,6 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
const SPECTATOR = 3;
|
||||
const VIEW = Player::SPECTATOR;
|
||||
|
||||
const SURVIVAL_SLOTS = 36;
|
||||
const CREATIVE_SLOTS = 112;
|
||||
|
||||
/** @var SourceInterface */
|
||||
protected $interface;
|
||||
|
||||
@ -804,6 +801,7 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
$this->sendData($this);
|
||||
$this->inventory->sendContents($this);
|
||||
$this->inventory->sendArmorContents($this);
|
||||
$this->inventory->sendHeldItem($this);
|
||||
|
||||
$pk = new SetTimePacket();
|
||||
$pk->time = $this->level->getTime();
|
||||
@ -1756,12 +1754,6 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
return;
|
||||
}
|
||||
|
||||
if($this->isCreative()){
|
||||
$this->inventory->setHeldItemSlot(0);
|
||||
}else{
|
||||
$this->inventory->setHeldItemSlot($this->inventory->getHotbarSlotIndex(0));
|
||||
}
|
||||
|
||||
$this->dataPacket(new ResourcePacksInfoPacket());
|
||||
|
||||
if(!$this->hasValidSpawnPosition() and isset($this->namedtag->SpawnLevel) and ($level = $this->server->getLevelByName($this->namedtag["SpawnLevel"])) instanceof Level){
|
||||
@ -1987,64 +1979,20 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
break;
|
||||
}
|
||||
|
||||
if($packet->slot === 0x28 or $packet->slot === 0 or $packet->slot === 255){ //0 for 0.8.0 compatibility
|
||||
$packet->slot = -1; //Air
|
||||
if($packet->inventorySlot === 255){
|
||||
$packet->inventorySlot = -1; //Cleared slot
|
||||
}else{
|
||||
$packet->slot -= 9; //Get real block slot
|
||||
}
|
||||
$packet->inventorySlot -= 9; //Get real inventory slot
|
||||
$item = $this->inventory->getItem($packet->inventorySlot);
|
||||
|
||||
/** @var Item $item */
|
||||
$item = null;
|
||||
|
||||
if($this->isCreative()){ //Creative mode match
|
||||
$item = $packet->item;
|
||||
$slot = Item::getCreativeItemIndex($item);
|
||||
}else{
|
||||
$item = $this->inventory->getItem($packet->slot);
|
||||
$slot = $packet->slot;
|
||||
}
|
||||
|
||||
if($packet->slot === -1){ //Air
|
||||
if($this->isCreative()){
|
||||
$found = false;
|
||||
for($i = 0; $i < $this->inventory->getHotbarSize(); ++$i){
|
||||
if($this->inventory->getHotbarSlotIndex($i) === -1){
|
||||
$this->inventory->setHeldItemIndex($i);
|
||||
$found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!$found){ //couldn't find a empty slot (error)
|
||||
$this->inventory->sendContents($this);
|
||||
break;
|
||||
}
|
||||
}else{
|
||||
if($packet->selectedSlot >= 0 and $packet->selectedSlot < 9){
|
||||
$this->inventory->setHeldItemIndex($packet->selectedSlot, false);
|
||||
$this->inventory->setHeldItemSlot($packet->slot);
|
||||
}else{
|
||||
$this->inventory->sendContents($this);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}elseif($item === null or $slot === -1 or !$item->deepEquals($packet->item)){ // packet error or not implemented
|
||||
$this->inventory->sendContents($this);
|
||||
break;
|
||||
}elseif($this->isCreative()){
|
||||
$this->inventory->setHeldItemIndex($packet->selectedSlot, false);
|
||||
$this->inventory->setItem($packet->selectedSlot, $item);
|
||||
$this->inventory->setHeldItemSlot($packet->selectedSlot);
|
||||
}else{
|
||||
if($packet->selectedSlot >= 0 and $packet->selectedSlot < $this->inventory->getHotbarSize()){
|
||||
$this->inventory->setHeldItemIndex($packet->selectedSlot, false);
|
||||
$this->inventory->setHeldItemSlot($slot);
|
||||
}else{
|
||||
if(!$item->equals($packet->item)){
|
||||
$this->inventory->sendContents($this);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$this->inventory->equipItem($packet->hotbarSlot, $packet->inventorySlot);
|
||||
|
||||
$this->setDataFlag(self::DATA_FLAGS, self::DATA_FLAG_ACTION, false);
|
||||
break;
|
||||
case ProtocolInfo::USE_ITEM_PACKET:
|
||||
@ -2854,33 +2802,38 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
break;
|
||||
}
|
||||
|
||||
if($packet->windowid === 0){ //Our inventory
|
||||
if($packet->slot >= $this->inventory->getSize()){
|
||||
break;
|
||||
}
|
||||
if($this->isCreative()){
|
||||
if(Item::getCreativeItemIndex($packet->item) !== -1){
|
||||
$this->inventory->setItem($packet->slot, $packet->item);
|
||||
$this->inventory->setHotbarSlotIndex($packet->slot, $packet->slot); //links $hotbar[$packet->slot] to $slots[$packet->slot]
|
||||
switch($packet->windowid){
|
||||
case ContainerSetContentPacket::SPECIAL_INVENTORY: //Normal inventory change
|
||||
if($packet->slot >= $this->inventory->getSize()){
|
||||
break 2;
|
||||
}
|
||||
}
|
||||
$transaction = new BaseTransaction($this->inventory, $packet->slot, $this->inventory->getItem($packet->slot), $packet->item);
|
||||
}elseif($packet->windowid === ContainerSetContentPacket::SPECIAL_ARMOR){ //Our armor
|
||||
if($packet->slot >= 4){
|
||||
break;
|
||||
}
|
||||
|
||||
$transaction = new BaseTransaction($this->inventory, $packet->slot + $this->inventory->getSize(), $this->inventory->getArmorItem($packet->slot), $packet->item);
|
||||
}elseif(isset($this->windowIndex[$packet->windowid])){
|
||||
$this->craftingType = 0;
|
||||
$inv = $this->windowIndex[$packet->windowid];
|
||||
$transaction = new BaseTransaction($inv, $packet->slot, $inv->getItem($packet->slot), $packet->item);
|
||||
}else{
|
||||
break;
|
||||
$transaction = new BaseTransaction($this->inventory, $packet->slot, $this->inventory->getItem($packet->slot), $packet->item);
|
||||
break;
|
||||
case ContainerSetContentPacket::SPECIAL_ARMOR: //Armour change
|
||||
if($packet->slot >= 4){
|
||||
break 2;
|
||||
}
|
||||
|
||||
$transaction = new BaseTransaction($this->inventory, $packet->slot + $this->inventory->getSize(), $this->inventory->getArmorItem($packet->slot), $packet->item);
|
||||
break;
|
||||
case ContainerSetContentPacket::SPECIAL_HOTBAR: //Hotbar link update
|
||||
//hotbarSlot 0-8, slot 9-44
|
||||
$this->inventory->setHotbarSlotIndex($packet->hotbarSlot, $packet->slot - 9);
|
||||
break 2;
|
||||
default:
|
||||
if(!isset($this->windowIndex[$packet->windowid])){
|
||||
break 2; //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()->deepEquals($transaction->getTargetItem()) and $transaction->getTargetItem()->getCount() === $transaction->getSourceItem()->getCount()){ //No changes!
|
||||
//No changes, just a local inventory update sent by the server
|
||||
//No changes, just a local inventory update sent by the client
|
||||
break;
|
||||
}
|
||||
|
||||
@ -3372,6 +3325,8 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
|
||||
|
||||
if($this->inventory !== null){
|
||||
$this->inventory->clearAll();
|
||||
$this->inventory->setHeldItemIndex(0);
|
||||
$this->inventory->resetHotbar(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user