Player: Tighten validity checks for addWindow() (#2419)

- Don't allow the same window ID to be used when another window is already using it
- Detect window ID collisions when selecting IDs for regular containers (should never happen, but anything is possible)
This commit is contained in:
Dylan K. Taylor 2018-09-01 15:25:46 +01:00 committed by GitHub
parent 2738e38aee
commit e621cde8f1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -3801,6 +3801,9 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
* @param bool $isPermanent Prevents the window being removed if true.
*
* @return int
*
* @throws \InvalidArgumentException if a forceID which is already in use is specified
* @throws \InvalidStateException if trying to add a window without forceID when no slots are free
*/
public function addWindow(Inventory $inventory, int $forceId = null, bool $isPermanent = false) : int{
if(($id = $this->getWindowId($inventory)) !== ContainerIds::NONE){
@ -3808,10 +3811,21 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{
}
if($forceId === null){
$this->windowCnt = $cnt = max(ContainerIds::FIRST, ++$this->windowCnt % ContainerIds::LAST);
$cnt = $this->windowCnt;
do{
$cnt = max(ContainerIds::FIRST, ($cnt + 1) % ContainerIds::LAST);
if($cnt === $this->windowCnt){ //wraparound, no free slots
throw new \InvalidStateException("No free window IDs found");
}
}while(isset($this->windowIndex[$cnt]));
$this->windowCnt = $cnt;
}else{
$cnt = $forceId;
if(isset($this->windowIndex[$cnt])){
throw new \InvalidArgumentException("Requested force ID $forceId already in use");
}
}
$this->windowIndex[$cnt] = $inventory;
$this->windows[spl_object_hash($inventory)] = $cnt;
if($inventory->open($this)){