From 176c3713304dbbd8f3c5cda8b3e350a19bb916b5 Mon Sep 17 00:00:00 2001 From: Shoghi Cervantes Date: Tue, 27 Aug 2013 12:38:00 +0200 Subject: [PATCH] Added chest pairing --- src/Player.php | 153 ++++++++++++++------ src/material/block/solid/BurningFurnace.php | 27 +--- src/material/block/solid/Chest.php | 81 +++-------- src/network/CustomPacketHandler.php | 4 +- src/world/Tile.php | 118 ++++++++++++++- 5 files changed, 252 insertions(+), 131 deletions(-) diff --git a/src/Player.php b/src/Player.php index 0434d0ca8..a08bcff39 100644 --- a/src/Player.php +++ b/src/Player.php @@ -1184,7 +1184,7 @@ class Player{ "x" => $this->data->get("position")["x"], "y" => $this->data->get("position")["y"], "z" => $this->data->get("position")["z"], - "unknown1" => 0, + "generator" => 0, "gamemode" => ($this->gamemode & 0x01), "eid" => 0, )); @@ -1651,14 +1651,27 @@ class Player{ } $this->craftingItems = array(); $this->toCraft = array(); - if(isset($this->windows[$data["windowid"]]) and $this->windows[$data["windowid"]]->class === TILE_CHEST){ - $this->server->api->player->broadcastPacket($this->server->api->player->getAll($this->level), MC_TILE_EVENT, array( - "x" => $this->windows[$data["windowid"]]->x, - "y" => $this->windows[$data["windowid"]]->y, - "z" => $this->windows[$data["windowid"]]->z, - "case1" => 1, - "case2" => 0, - )); + if(isset($this->windows[$data["windowid"]])){ + if(is_array($this->windows[$data["windowid"]])){ + $all = $this->server->api->player->getAll($this->level); + foreach($this->windows[$data["windowid"]] as $ob){ + $this->server->api->player->broadcastPacket($all, MC_TILE_EVENT, array( + "x" => $ob->x, + "y" => $ob->y, + "z" => $ob->z, + "case1" => 1, + "case2" => 0, + )); + } + }elseif($this->windows[$data["windowid"]]->class === TILE_CHEST){ + $this->server->api->player->broadcastPacket($this->server->api->player->getAll($this->level), MC_TILE_EVENT, array( + "x" => $this->windows[$data["windowid"]]->x, + "y" => $this->windows[$data["windowid"]]->y, + "z" => $this->windows[$data["windowid"]]->z, + "case1" => 1, + "case2" => 0, + )); + } } unset($this->windows[$data["windowid"]]); @@ -1725,46 +1738,94 @@ class Player{ if(!isset($this->windows[$data["windowid"]])){ break; } - $tile = $this->windows[$data["windowid"]]; - if(($tile->class !== TILE_CHEST and $tile->class !== TILE_FURNACE) or $data["slot"] < 0 or ($tile->class === TILE_CHEST and $data["slot"] >= CHEST_SLOTS) or ($tile->class === TILE_FURNACE and $data["slot"] >= FURNACE_SLOTS)){ - break; - } - $done = false; - $item = BlockAPI::getItem($data["block"], $data["meta"], $data["stack"]); - - $slot = $tile->getSlot($data["slot"]); - $done = true; - if($this->server->api->dhandle("player.container.slot", array( - "tile" => $tile, - "slot" => $data["slot"], - "slotdata" => $slot, - "itemdata" => $item, - "player" => $this, - )) === false){ - $this->dataPacket(MC_CONTAINER_SET_SLOT, array( - "windowid" => $data["windowid"], - "slot" => $data["slot"], - "block" => $slot->getID(), - "stack" => $slot->count, - "meta" => $slot->getMetadata(), - )); - break; - } - if($item->getID() !== AIR and $slot->getID() == $item->getID()){ - if($slot->count < $item->count){ - if($this->removeItem($item->getID(), $item->getMetadata(), $item->count - $slot->count, false) === false){ - break; - } - }elseif($slot->count > $item->count){ - $this->addItem($item->getID(), $item->getMetadata(), $slot->count - $item->count, false); - } - }else{ - if($this->removeItem($item->getID(), $item->getMetadata(), $item->count, false) === false){ + if(is_array($this->windows[$data["windowid"]])){ + $tiles = $this->windows[$data["windowid"]]; + if($data["slot"] > 0 and $data["slot"] < CHEST_SLOTS){ + $tile = $tiles[0]; + $slotn = $data["slot"]; + $offset = 0; + }elseif($data["slot"] >= CHEST_SLOTS and $data["slot"] <= (CHEST_SLOTS << 1)){ + $tile = $tiles[1]; + $slotn = $data["slot"] - CHEST_SLOTS; + $offset = CHEST_SLOTS; + }else{ break; } - $this->addItem($slot->getID(), $slot->getMetadata(), $slot->count, false); + + $item = BlockAPI::getItem($data["block"], $data["meta"], $data["stack"]); + + $slot = $tile->getSlot($slotn); + if($this->server->api->dhandle("player.container.slot", array( + "tile" => $tile, + "slot" => $data["slot"], + "slotdata" => $slot, + "itemdata" => $item, + "player" => $this, + )) === false){ + $this->dataPacket(MC_CONTAINER_SET_SLOT, array( + "windowid" => $data["windowid"], + "slot" => $data["slot"], + "block" => $slot->getID(), + "stack" => $slot->count, + "meta" => $slot->getMetadata(), + )); + break; + } + if($item->getID() !== AIR and $slot->getID() == $item->getID()){ + if($slot->count < $item->count){ + if($this->removeItem($item->getID(), $item->getMetadata(), $item->count - $slot->count, false) === false){ + break; + } + }elseif($slot->count > $item->count){ + $this->addItem($item->getID(), $item->getMetadata(), $slot->count - $item->count, false); + } + }else{ + if($this->removeItem($item->getID(), $item->getMetadata(), $item->count, false) === false){ + break; + } + $this->addItem($slot->getID(), $slot->getMetadata(), $slot->count, false); + } + $tile->setSlot($slotn, $item, true, $offset); + }else{ + $tile = $this->windows[$data["windowid"]]; + if(($tile->class !== TILE_CHEST and $tile->class !== TILE_FURNACE) or $data["slot"] < 0 or ($tile->class === TILE_CHEST and $data["slot"] >= CHEST_SLOTS) or ($tile->class === TILE_FURNACE and $data["slot"] >= FURNACE_SLOTS)){ + break; + } + $item = BlockAPI::getItem($data["block"], $data["meta"], $data["stack"]); + + $slot = $tile->getSlot($data["slot"]); + if($this->server->api->dhandle("player.container.slot", array( + "tile" => $tile, + "slot" => $data["slot"], + "slotdata" => $slot, + "itemdata" => $item, + "player" => $this, + )) === false){ + $this->dataPacket(MC_CONTAINER_SET_SLOT, array( + "windowid" => $data["windowid"], + "slot" => $data["slot"], + "block" => $slot->getID(), + "stack" => $slot->count, + "meta" => $slot->getMetadata(), + )); + break; + } + if($item->getID() !== AIR and $slot->getID() == $item->getID()){ + if($slot->count < $item->count){ + if($this->removeItem($item->getID(), $item->getMetadata(), $item->count - $slot->count, false) === false){ + break; + } + }elseif($slot->count > $item->count){ + $this->addItem($item->getID(), $item->getMetadata(), $slot->count - $item->count, false); + } + }else{ + if($this->removeItem($item->getID(), $item->getMetadata(), $item->count, false) === false){ + break; + } + $this->addItem($slot->getID(), $slot->getMetadata(), $slot->count, false); + } + $tile->setSlot($data["slot"], $item); } - $tile->setSlot($data["slot"], $item); break; case MC_SEND_INVENTORY: //TODO, Mojang, enable this ยด^_^` if($this->spawned === false){ diff --git a/src/material/block/solid/BurningFurnace.php b/src/material/block/solid/BurningFurnace.php index ec1863583..b73c6bbca 100644 --- a/src/material/block/solid/BurningFurnace.php +++ b/src/material/block/solid/BurningFurnace.php @@ -65,32 +65,11 @@ class BurningFurnaceBlock extends SolidBlock{ )); } - if($furnace->class !== TILE_FURNACE or ($player->gamemode & 0x01) === 0x01){ + if(($player->gamemode & 0x01) === 0x01){ return true; } - $player->windowCnt++; - $player->windowCnt = $id = max(2, $player->windowCnt % 99); - $player->windows[$id] = $furnace; - $player->dataPacket(MC_CONTAINER_OPEN, array( - "windowid" => $id, - "type" => WINDOW_FURNACE, - "slots" => FURNACE_SLOTS, - "title" => "Furnace", - )); - $slots = array(); - for($s = 0; $s < FURNACE_SLOTS; ++$s){ - $slot = $furnace->getSlot($s); - if($slot->getID() > 0 and $slot->count > 0){ - $slots[] = $slot; - }else{ - $slots[] = BlockAPI::getItem(AIR, 0, 0); - } - } - $player->dataPacket(MC_CONTAINER_SET_CONTENT, array( - "windowid" => $id, - "count" => count($slots), - "slots" => $slots - )); + + $furnace->openInventory($player); return true; } diff --git a/src/material/block/solid/Chest.php b/src/material/block/solid/Chest.php index 7219c4747..70b7eefde 100644 --- a/src/material/block/solid/Chest.php +++ b/src/material/block/solid/Chest.php @@ -31,50 +31,44 @@ class ChestBlock extends TransparentBlock{ $this->isActivable = true; } public function place(Item $item, Player $player, Block $block, Block $target, $face, $fx, $fy, $fz){ - + $server = ServerAPI::request(); $faces = array( 0 => 4, 1 => 2, 2 => 5, 3 => 3, ); - $facesc = array( - 2 => 4, - 3 => 2, - 4 => 5, - 5 => 3, - ); + $chest = false; + $this->meta = $faces[$player->entity->getDirection()]; + for($side = 2; $side <= 5; ++$side){ + if(($this->meta === 4 or $this->meta === 5) and ($side === 4 or $side === 5)){ + continue; + }elseif(($this->meta === 3 or $this->meta === 2) and ($side === 2 or $side === 3)){ + continue; + } $c = $this->getSide($side); - if($c instanceof ChestBlock){ - /*if($chest !== false){ //No chests in the middle - return false; - }*/ - $chest = array($side, $c); - break; + if(($c instanceof ChestBlock) and $c->getMetadata() === $this->meta){ + if((($tile = $server->api->tile->get($c)) instanceof Tile) and !$tile->isPaired()){ + $chest = $tile; + break; + } } } - - if($chest !== false and ($chest[1]->getSide($chest[0]) instanceof ChestBlock)){ //Already double chest - return false; - } - - if($chest !== false){ - $this->meta = $facesc[$chest[0]]; - $this->level->setBlock($chest[1], new ChestBlock($this->meta)); - }else{ - $this->meta = $faces[$player->entity->getDirection()]; - } + $this->level->setBlock($block, $this); - $server = ServerAPI::request(); - $server->api->tile->add($this->level, TILE_CHEST, $this->x, $this->y, $this->z, array( + $tile = $server->api->tile->add($this->level, TILE_CHEST, $this->x, $this->y, $this->z, array( "Items" => array(), "id" => TILE_CHEST, "x" => $this->x, "y" => $this->y, "z" => $this->z )); + if($chest instanceof Tile){ + $chest->pairWith($tile); + $tile->pairWith($chest); + } return true; } @@ -104,40 +98,13 @@ class ChestBlock extends TransparentBlock{ )); } - if($chest->class !== TILE_CHEST or ($player->gamemode & 0x01) === 0x01){ + + + if(($player->gamemode & 0x01) === 0x01){ return true; } - $player->windowCnt++; - $player->windowCnt = $id = max(2, $player->windowCnt % 99); - $player->windows[$id] = $chest; - $player->dataPacket(MC_CONTAINER_OPEN, array( - "windowid" => $id, - "type" => WINDOW_CHEST, - "slots" => CHEST_SLOTS, - "title" => "Chest", - )); - $server->api->player->broadcastPacket($server->api->player->getAll($this->level), MC_TILE_EVENT, array( - "x" => $this->x, - "y" => $this->y, - "z" => $this->z, - "case1" => 1, - "case2" => 2, - )); - $slots = array(); - for($s = 0; $s < CHEST_SLOTS; ++$s){ - $slot = $chest->getSlot($s); - if($slot->getID() > AIR and $slot->count > 0){ - $slots[] = $slot; - }else{ - $slots[] = BlockAPI::getItem(AIR, 0, 0); - } - } - $player->dataPacket(MC_CONTAINER_SET_CONTENT, array( - "windowid" => $id, - "count" => count($slots), - "slots" => $slots - )); + $chest->openInventory($player); return true; } diff --git a/src/network/CustomPacketHandler.php b/src/network/CustomPacketHandler.php index 8208e7de3..4155a0912 100644 --- a/src/network/CustomPacketHandler.php +++ b/src/network/CustomPacketHandler.php @@ -202,7 +202,7 @@ class CustomPacketHandler{ case MC_START_GAME: if($this->c === false){ $this->data["seed"] = Utils::readInt($this->get(4)); - $this->data["unknown1"] = Utils::readInt($this->get(4)); + $this->data["generator"] = Utils::readInt($this->get(4)); $this->data["gamemode"] = Utils::readInt($this->get(4)); $this->data["eid"] = Utils::readInt($this->get(4)); $this->data["x"] = Utils::readFloat($this->get(4)); @@ -210,7 +210,7 @@ class CustomPacketHandler{ $this->data["z"] = Utils::readFloat($this->get(4)); }else{ $this->raw .= Utils::writeInt($this->data["seed"]); - $this->raw .= Utils::writeInt($this->data["unknown1"]); + $this->raw .= Utils::writeInt($this->data["generator"]); $this->raw .= Utils::writeInt($this->data["gamemode"]); $this->raw .= Utils::writeInt($this->data["eid"]); $this->raw .= Utils::writeFloat($this->data["x"]); diff --git a/src/world/Tile.php b/src/world/Tile.php index 7aa80e757..fafb4589c 100644 --- a/src/world/Tile.php +++ b/src/world/Tile.php @@ -106,6 +106,120 @@ class Tile extends Position{ $tile->data["pairx"] = $this->x; $tile->data["pairz"] = $this->z; + + $this->server->api->tile->spawnToAll($this); + $this->server->api->tile->spawnToAll($tile); + } + + public function unpair(){ + if(!$this->isPaired()){ + return false; + } + + $tile = $this->getPair(); + unset($this->data["pairx"], $this->data["pairz"], $ile->data["pairx"], $tile->data["pairz"]); + + $this->server->api->tile->spawnToAll($this); + if($tile instanceof Tile){ + $this->server->api->tile->spawnToAll($tile); + } + } + + public function openInventory(Player $player){ + if($this->class === TILE_CHEST){ + $player->windowCnt++; + $player->windowCnt = $id = max(2, $player->windowCnt % 99); + if(($pair = $this->getPair()) !== false){ + if(($pair->x + ($pair->z << 13)) > ($this->x + ($this->z << 13))){ //Order them correctly + $player->windows[$id] = array( + $pair, + $this + ); + }else{ + $player->windows[$id] = array( + $this, + $pair + ); + } + }else{ + $player->windows[$id] = $this; + } + $player->dataPacket(MC_CONTAINER_OPEN, array( + "windowid" => $id, + "type" => WINDOW_CHEST, + "slots" => is_array($player->windows[$id]) ? CHEST_SLOTS << 1:CHEST_SLOTS, + "title" => "Chest", + )); + $slots = array(); + + if(is_array($player->windows[$id])){ + $all = $this->server->api->player->getAll($this->level); + foreach($player->windows[$id] as $ob){ + $this->server->api->player->broadcastPacket($all, MC_TILE_EVENT, array( + "x" => $ob->x, + "y" => $ob->y, + "z" => $ob->z, + "case1" => 1, + "case2" => 2, + )); + for($s = 0; $s < CHEST_SLOTS; ++$s){ + $slot = $ob->getSlot($s); + if($slot->getID() > AIR and $slot->count > 0){ + $slots[] = $slot; + }else{ + $slots[] = BlockAPI::getItem(AIR, 0, 0); + } + } + } + }else{ + $this->server->api->player->broadcastPacket($this->server->api->player->getAll($this->level), MC_TILE_EVENT, array( + "x" => $this->x, + "y" => $this->y, + "z" => $this->z, + "case1" => 1, + "case2" => 2, + )); + for($s = 0; $s < CHEST_SLOTS; ++$s){ + $slot = $this->getSlot($s); + if($slot->getID() > AIR and $slot->count > 0){ + $slots[] = $slot; + }else{ + $slots[] = BlockAPI::getItem(AIR, 0, 0); + } + } + } + $player->dataPacket(MC_CONTAINER_SET_CONTENT, array( + "windowid" => $id, + "count" => count($slots), + "slots" => $slots + )); + return true; + }elseif($this->class === TILE_FURNACE){ + $player->windowCnt++; + $player->windowCnt = $id = max(2, $player->windowCnt % 99); + $player->windows[$id] = $this; + $player->dataPacket(MC_CONTAINER_OPEN, array( + "windowid" => $id, + "type" => WINDOW_FURNACE, + "slots" => FURNACE_SLOTS, + "title" => "Furnace", + )); + $slots = array(); + for($s = 0; $s < FURNACE_SLOTS; ++$s){ + $slot = $this->getSlot($s); + if($slot->getID() > AIR and $slot->count > 0){ + $slots[] = $slot; + }else{ + $slots[] = BlockAPI::getItem(AIR, 0, 0); + } + } + $player->dataPacket(MC_CONTAINER_SET_CONTENT, array( + "windowid" => $id, + "count" => count($slots), + "slots" => $slots + )); + return true; + } } public function update(){ @@ -195,7 +309,7 @@ class Tile extends Position{ } } - public function setSlot($s, Item $item, $update = true){ + public function setSlot($s, Item $item, $update = true, $offset = 0){ $i = $this->getSlotIndex($s); $d = array( "Count" => $item->count, @@ -216,7 +330,7 @@ class Tile extends Position{ } $this->server->api->dhandle("tile.container.slot", array( "tile" => $this, - "slot" => $s, + "slot" => $s + $offset, "slotdata" => $item, ));