Added API for assigning permanent windows, fixed teleportation breaking inventory

This commit is contained in:
Dylan K. Taylor 2017-08-17 19:43:59 +01:00
parent f35ca147bb
commit 1f6d325328

View File

@ -224,6 +224,8 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
protected $windows; protected $windows;
/** @var Inventory[] */ /** @var Inventory[] */
protected $windowIndex = []; protected $windowIndex = [];
/** @var bool[] */
protected $permanentWindows = [];
protected $messageCounter = 2; protected $messageCounter = 2;
@ -3495,9 +3497,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
$this->hiddenPlayers = []; $this->hiddenPlayers = [];
} }
foreach($this->windowIndex as $window){ $this->removeAllWindows(true);
$this->removeWindow($window);
}
$this->windows = null; $this->windows = null;
$this->windowIndex = []; $this->windowIndex = [];
@ -3789,12 +3789,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
public function teleport(Vector3 $pos, float $yaw = null, float $pitch = null) : bool{ public function teleport(Vector3 $pos, float $yaw = null, float $pitch = null) : bool{
if(parent::teleport($pos, $yaw, $pitch)){ if(parent::teleport($pos, $yaw, $pitch)){
foreach($this->windowIndex as $window){ $this->removeAllWindows();
if($window === $this->inventory){
continue;
}
$this->removeWindow($window);
}
$this->sendPosition($this, $this->yaw, $this->pitch, MovePlayerPacket::MODE_TELEPORT); $this->sendPosition($this, $this->yaw, $this->pitch, MovePlayerPacket::MODE_TELEPORT);
$this->sendPosition($this, $this->yaw, $this->pitch, MovePlayerPacket::MODE_TELEPORT, $this->getViewers()); $this->sendPosition($this, $this->yaw, $this->pitch, MovePlayerPacket::MODE_TELEPORT, $this->getViewers());
@ -3828,10 +3823,10 @@ 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, true);
$this->cursorInventory = new PlayerCursorInventory($this); $this->cursorInventory = new PlayerCursorInventory($this);
$this->addWindow($this->cursorInventory, ContainerIds::CURSOR); $this->addWindow($this->cursorInventory, ContainerIds::CURSOR, true);
//TODO: more windows //TODO: more windows
} }
@ -3841,19 +3836,26 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
} }
/** /**
* Returns the window ID which the inventory has for this player, or -1 if the window is not open to the player.
*
* @param Inventory $inventory * @param Inventory $inventory
* *
* @return int * @return int
*/ */
public function getWindowId(Inventory $inventory){ public function getWindowId(Inventory $inventory){
if($this->windows->contains($inventory)){ if($this->windows->contains($inventory)){
return $this->windows[$inventory]; /** @var int $id */
$id = $this->windows[$inventory];
return $id;
} }
return ContainerIds::NONE; return ContainerIds::NONE;
} }
/** /**
* Returns the inventory window open to the player with the specified window ID, or null if no window is open with
* that ID.
*
* @param int $windowId * @param int $windowId
* *
* @return Inventory|null * @return Inventory|null
@ -3863,16 +3865,18 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
} }
/** /**
* Returns the created/existing window id * Opens an inventory window to the player. Returns the ID of the created window, or the existing window ID if the
* player is already viewing the specified inventory.
* *
* @param Inventory $inventory * @param Inventory $inventory
* @param int|null $forceId * @param int|null $forceId Forces a special ID for the window
* @param bool $isPermanent Prevents the window being removed if true.
* *
* @return int * @return int
*/ */
public function addWindow(Inventory $inventory, int $forceId = null) : int{ public function addWindow(Inventory $inventory, int $forceId = null, bool $isPermanent = false) : int{
if($this->windows->contains($inventory)){ if(($id = $this->getWindowId($inventory)) !== ContainerIds::NONE){
return $this->windows[$inventory]; return $id;
} }
if($forceId === null){ if($forceId === null){
@ -3883,6 +3887,9 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
$this->windowIndex[$cnt] = $inventory; $this->windowIndex[$cnt] = $inventory;
$this->windows->attach($inventory, $cnt); $this->windows->attach($inventory, $cnt);
if($inventory->open($this)){ if($inventory->open($this)){
if($isPermanent){
$this->permanentWindows[$cnt] = true;
}
return $cnt; return $cnt;
}else{ }else{
$this->removeWindow($inventory); $this->removeWindow($inventory);
@ -3891,13 +3898,41 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
} }
} }
public function removeWindow(Inventory $inventory){ /**
$inventory->close($this); * Removes an inventory window from the player.
*
* @param Inventory $inventory
* @param bool $force Forces removal of permanent windows such as normal inventory, cursor
*
* @throws \BadMethodCallException if trying to remove a fixed inventory window without the `force` parameter as true
*/
public function removeWindow(Inventory $inventory, bool $force = false){
if($this->windows->contains($inventory)){ if($this->windows->contains($inventory)){
/** @var int $id */ /** @var int $id */
$id = $this->windows[$inventory]; $id = $this->windows[$inventory];
if(!$force and isset($this->permanentWindows[$id])){
throw new \BadMethodCallException("Cannot remove fixed window $id (" . get_class($inventory) . ") from " . $this->getName());
}
$this->windows->detach($this->windowIndex[$id]); $this->windows->detach($this->windowIndex[$id]);
unset($this->windowIndex[$id]); unset($this->windowIndex[$id]);
unset($this->permanentWindows[$id]);
}
$inventory->close($this);
}
/**
* Removes all inventory windows from the player. By default this WILL NOT remove permanent windows.
*
* @param bool $removePermanentWindows Whether to remove permanent windows.
*/
public function removeAllWindows(bool $removePermanentWindows = false){
foreach($this->windowIndex as $id => $window){
if(!$removePermanentWindows and isset($this->permanentWindows[$id])){
continue;
}
$this->removeWindow($window, $removePermanentWindows);
} }
} }