Implemented new Inventory windows on Player, Chest and Furnace

This commit is contained in:
Shoghi Cervantes 2014-05-23 20:53:06 +02:00
parent 27e82ea60a
commit 53749483c3
71 changed files with 1189 additions and 1009 deletions

View File

@ -28,7 +28,6 @@ use pocketmine\event\player\PlayerAchievementAwardedEvent;
use pocketmine\event\player\PlayerChatEvent;
use pocketmine\event\player\PlayerCommandPreprocessEvent;
use pocketmine\event\player\PlayerGameModeChangeEvent;
use pocketmine\event\player\PlayerItemHeldEvent;
use pocketmine\event\player\PlayerJoinEvent;
use pocketmine\event\player\PlayerKickEvent;
use pocketmine\event\player\PlayerLoginEvent;
@ -37,7 +36,10 @@ use pocketmine\event\player\PlayerQuitEvent;
use pocketmine\event\player\PlayerRespawnEvent;
use pocketmine\event\server\DataPacketReceiveEvent;
use pocketmine\event\server\DataPacketSendEvent;
use pocketmine\inventory\Inventory;
use pocketmine\inventory\InventoryHolder;
use pocketmine\item\Item;
use pocketmine\level\format\pmf\LevelFormat;
use pocketmine\level\Level;
use pocketmine\level\Position;
use pocketmine\math\Vector3;
@ -48,9 +50,6 @@ use pocketmine\nbt\tag\Compound;
use pocketmine\nbt\tag\String;
use pocketmine\network\protocol\AdventureSettingsPacket;
use pocketmine\network\protocol\ChunkDataPacket;
use pocketmine\network\protocol\ContainerClosePacket;
use pocketmine\network\protocol\ContainerSetContentPacket;
use pocketmine\network\protocol\ContainerSetSlotPacket;
use pocketmine\network\protocol\DataPacket;
use pocketmine\network\protocol\DisconnectPacket;
use pocketmine\network\protocol\Info as ProtocolInfo;
@ -61,7 +60,6 @@ use pocketmine\network\protocol\ServerHandshakePacket;
use pocketmine\network\protocol\SetSpawnPositionPacket;
use pocketmine\network\protocol\SetTimePacket;
use pocketmine\network\protocol\StartGamePacket;
use pocketmine\network\protocol\TileEventPacket;
use pocketmine\network\protocol\UnknownPacket;
use pocketmine\network\protocol\UpdateBlockPacket;
use pocketmine\network\raknet\Info;
@ -69,11 +67,8 @@ use pocketmine\network\raknet\Packet;
use pocketmine\permission\PermissibleBase;
use pocketmine\permission\PermissionAttachment;
use pocketmine\plugin\Plugin;
use pocketmine\level\format\pmf\LevelFormat;
use pocketmine\recipes\Crafting;
use pocketmine\scheduler\CallbackTask;
use pocketmine\tile\Chest;
use pocketmine\tile\Furnace;
use pocketmine\tile\Sign;
use pocketmine\tile\Spawnable;
use pocketmine\tile\Tile;
@ -84,7 +79,7 @@ use pocketmine\utils\TextFormat;
* Main class that handles networking, recovery, and packet sending to the server part
* TODO: Move reliability layer
*/
class Player extends Human implements CommandSender, IPlayer{
class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
const SURVIVAL = 0;
const CREATIVE = 1;
@ -102,8 +97,13 @@ class Player extends Human implements CommandSender, IPlayer{
public $loggedIn = false;
public $gamemode;
public $lastBreak;
public $windowCnt = 2;
public $windows = [];
protected $windowCnt = 2;
/** @var \SplObjectStorage<Inventory> */
protected $windows;
/** @var Inventory[] */
protected $windowIndex = [];
public $blocked = true;
public $achievements = [];
public $chunksLoaded = [];
@ -358,6 +358,7 @@ class Player extends Human implements CommandSender, IPlayer{
* @param integer $MTU
*/
public function __construct($clientID, $ip, $port, $MTU){
$this->windows = new \SplObjectStorage();
$this->perm = new PermissibleBase($this);
$this->namedtag = new Compound();
$this->bigCnt = 0;
@ -1322,6 +1323,7 @@ class Player extends Human implements CommandSender, IPlayer{
if($p !== $this and strtolower($p->getName()) === strtolower($this->getName())){
if($p->kick("logged in from another location") === false){
$this->close($this->getName() . " has left the game", "already logged in");
return;
}else{
break;
@ -1432,9 +1434,9 @@ class Player extends Human implements CommandSender, IPlayer{
$this->spawned = true;
$this->spawnToAll();
$this->sendInventory();
$this->sendSettings();
$this->sendArmor();
$this->getInventory()->sendContents($this);
$this->getInventory()->sendArmorContents($this);
$this->tasks[] = $this->server->getScheduler()->scheduleDelayedTask(new CallbackTask(array($this, "orderChunks")), 30);
$this->blocked = false;
@ -1510,26 +1512,13 @@ class Player extends Human implements CommandSender, IPlayer{
}
}
}else{
$item = $this->getSlot($packet->slot);
$item = $this->inventory->getItem($packet->slot);
}
if(!isset($item) or $packet->slot === false){
$this->sendInventorySlot($packet->slot);
$this->inventory->sendSlot($packet->slot, $this);
}else{
$this->server->getPluginManager()->callEvent($ev = new PlayerItemHeldEvent($this, $item, $packet->slot, 0));
if($ev->isCancelled()){
$this->sendInventorySlot($packet->slot);
}elseif($item instanceof Item){
$this->setEquipmentSlot(0, $packet->slot);
$this->setCurrentEquipmentSlot(0);
if(($this->gamemode & 0x01) === 0){
if(!in_array($this->slot, $this->hotbar)){
array_pop($this->hotbar);
array_unshift($this->hotbar, $this->slot);
}
}
}
$this->inventory->setHeldItemSlot($packet->slot);
}
if($this->inAction === true){
@ -1576,18 +1565,21 @@ class Player extends Human implements CommandSender, IPlayer{
if($blockVector->distance($this) > 10){
}elseif(($this->gamemode & 0x01) === 1){
$item = Item::get(Block::$creative[$this->getCurrentEquipment()][0], Block::$creative[$this->getCurrentEquipment()][1], 1);
$item = Item::get(
Block::$creative[$this->inventory->getHeldItemSlot()][0],
Block::$creative[$this->inventory->getHeldItemSlot()][1],
1
);
if($this->getLevel()->useItemOn($blockVector, $item, $packet->face, $packet->fx, $packet->fy, $packet->fz, $this) === true){
break;
}
}elseif($this->getSlot($this->getCurrentEquipment())->getID() !== $packet->item or ($this->getSlot($this->getCurrentEquipment())->isTool() === false and $this->getSlot($this->getCurrentEquipment())->getDamage() !== $packet->meta)){
$this->sendInventorySlot($this->getCurrentEquipment());
}elseif($this->inventory->getItemInHand()->getID() !== $packet->item or ($this->inventory->getItemInHand()->isTool() === false and $this->inventory->getItemInHand()->getDamage() !== $packet->meta)){
$this->inventory->sendHeldItem($this);
}else{
$item = clone $this->getSlot($this->getCurrentEquipment());
$item = clone $this->inventory->getItemInHand();
//TODO: Implement adventure mode checks
if($this->getLevel()->useItemOn($blockVector, $item, $packet->face, $packet->fx, $packet->fy, $packet->fz, $this) === true){
$this->setSlot($this->getCurrentEquipment(), $item);
$this->sendInventorySlot($this->getCurrentEquipment());
$this->inventory->setItemInHand($item);
break;
}
}
@ -1704,15 +1696,19 @@ class Player extends Human implements CommandSender, IPlayer{
if(($this->gamemode & 0x01) === 1){
$item = Item::get(Block::$creative[$this->getCurrentEquipment()][0], Block::$creative[$this->getCurrentEquipment()][1], 1);
$item = Item::get(
Block::$creative[$this->inventory->getHeldItemSlot()][0],
Block::$creative[$this->inventory->getHeldItemSlot()][1],
1
);
}else{
$item = clone $this->getSlot($this->getCurrentEquipment());
$item = clone $this->inventory->getItemInHand();
}
if(($drops = $this->getLevel()->useBreakOn($vector, $item)) !== true){
if(($this->gamemode & 0x01) === 0){
//TODO: drop items
$this->setSlot($this->getCurrentEquipment(), $item);
$this->inventory->setItemInHand($item);
}
break;
}
@ -1739,33 +1735,22 @@ class Player extends Human implements CommandSender, IPlayer{
}else{
$s = Item::get($s + 256, 0, 1);
}
$slot = $this->getArmorSlot($i);
$slot = $this->inventory->getArmorItem($i);
if($slot->getID() !== Item::AIR and $s->getID() === Item::AIR){
if($this->setArmorSlot($i, Item::get(Item::AIR, 0, 0)) === false){
$this->sendArmor();
$this->sendInventory();
$this->inventory->setArmorItem($i, Item::get(Item::AIR, 0, 0));
}elseif($s->getID() !== Item::AIR and $slot->getID() === Item::AIR and ($sl = $this->inventory->first($s)) !== -1){
if($this->inventory->setArmorItem($i, $this->inventory->getItem($sl)) === false){
$this->inventory->sendContents($this);
}else{
$this->addItem($slot);
$packet->slots[$i] = 255;
$this->inventory->setItem($sl, Item::get(Item::AIR, 0, 0));
}
}elseif($s->getID() !== Item::AIR and $slot->getID() === Item::AIR and ($sl = $this->hasItem($s, false)) !== false){
if($this->setArmorSlot($i, $this->getSlot($sl)) === false){
$this->sendArmor();
$this->sendInventory();
}elseif($s->getID() !== Item::AIR and $slot->getID() !== Item::AIR and ($slot->getID() !== $s->getID() or $slot->getDamage() !== $s->getDamage()) and ($sl = $this->inventory->first($s)) !== -1){
if($this->inventory->setArmorItem($i, $this->inventory->getItem($sl)) === false){
$this->inventory->sendContents($this);
}else{
$this->setSlot($sl, Item::get(Item::AIR, 0, 0));
$this->inventory->setItem($sl, $slot);
}
}elseif($s->getID() !== Item::AIR and $slot->getID() !== Item::AIR and ($slot->getID() !== $s->getID() or $slot->getDamage() !== $s->getDamage()) and ($sl = $this->hasItem($s, false)) !== false){
if($this->setArmorSlot($i, $this->getSlot($sl)) === false){
$this->sendArmor();
$this->sendInventory();
}else{
$this->setSlot($sl, $slot);
}
}else{
$packet->slots[$i] = 255;
}
}
if($this->inAction === true){
@ -1884,7 +1869,10 @@ class Player extends Human implements CommandSender, IPlayer{
//$this->entity->setHealth(20, "respawn", true);
//$this->entity->updateMetadata();
$this->sendInventory();
$this->sendSettings();
$this->inventory->sendContents($this);
$this->inventory->sendArmorContents($this);
$this->blocked = false;
break;
case ProtocolInfo::SET_HEALTH_PACKET: //Not used
@ -1989,37 +1977,16 @@ class Player extends Human implements CommandSender, IPlayer{
}
break;
case ProtocolInfo::CONTAINER_CLOSE_PACKET:
if($this->spawned === false){
if($this->spawned === false or $packet->windowid === 0){
break;
}
$this->craftingItems = [];
$this->toCraft = [];
if(isset($this->windows[$packet->windowid])){
if(is_array($this->windows[$packet->windowid])){
foreach($this->windows[$packet->windowid] as $ob){
$pk = new TileEventPacket;
$pk->x = $ob->x;
$pk->y = $ob->y;
$pk->z = $ob->z;
$pk->case1 = 1;
$pk->case2 = 0;
Player::broadcastPacket($this->getLevel()->players, $pk);
if(isset($this->windowIndex[$packet->windowid])){
$this->removeWindow($this->windowIndex[$packet->windowid]);
}else{
unset($this->windowIndex[$packet->windowid]);
}
}elseif($this->windows[$packet->windowid] instanceof Chest){
$pk = new TileEventPacket;
$pk->x = $this->windows[$packet->windowid]->x;
$pk->y = $this->windows[$packet->windowid]->y;
$pk->z = $this->windows[$packet->windowid]->z;
$pk->case1 = 1;
$pk->case2 = 0;
Player::broadcastPacket($this->getLevel()->players, $pk);
}
}
unset($this->windows[$packet->windowid]);
$pk = new ContainerClosePacket;
$pk->windowid = $packet->windowid;
$this->dataPacket($pk);
break;
case ProtocolInfo::CONTAINER_SET_SLOT_PACKET:
if($this->spawned === false or $this->blocked === true){
@ -2035,9 +2002,9 @@ class Player extends Human implements CommandSender, IPlayer{
$this->craftingItems = [];
}
if($packet->windowid === 0){
if($packet->windowid === 0){ //Crafting!
$craft = false;
$slot = $this->getSlot($packet->slot);
$slot = $this->inventory->getItem($packet->slot);
if($slot->getCount() >= $packet->item->getCount() and (($slot->getID() === $packet->item->getID() and $slot->getDamage() === $packet->item->getDamage()) or ($packet->item->getID() === Item::AIR and $packet->item->getCount() === 0)) and !isset($this->craftingItems[$packet->slot])){ //Crafting recipe
$use = Item::get($slot->getID(), $slot->getDamage(), $slot->getCount() - $packet->item->getCount());
$this->craftingItems[$packet->slot] = $use;
@ -2066,7 +2033,7 @@ class Player extends Human implements CommandSender, IPlayer{
if($craft === true and count($this->craftingItems) > 0 and count($this->toCraft) > 0 and ($recipe = $this->craftItems($this->toCraft, $this->craftingItems, $this->toCraft[-1])) !== true){
if($recipe === false){
$this->sendInventory();
$this->inventory->sendContents($this);
$this->toCraft = [];
}else{
$this->toCraft = array(-1 => $this->toCraft[-1]);
@ -2077,129 +2044,57 @@ class Player extends Human implements CommandSender, IPlayer{
$this->toCraft = [];
$this->craftingItems = [];
}
if(!isset($this->windows[$packet->windowid])){
if(!isset($this->windowIndex[$packet->windowid])){
break;
}
if(is_array($this->windows[$packet->windowid])){
/** @var \pocketmine\tile\Container[] $tiles */
$tiles = $this->windows[$packet->windowid];
if($packet->slot >= 0 and $packet->slot < Chest::SLOTS){
$tile = $tiles[0];
$slotn = $packet->slot;
$offset = 0;
}elseif($packet->slot >= Chest::SLOTS and $packet->slot <= (Chest::SLOTS << 1)){
$tile = $tiles[1];
$slotn = $packet->slot - Chest::SLOTS;
$offset = Chest::SLOTS;
}else{
$inv = $this->windowIndex[$packet->windowid];
if($packet->slot < 0 or $packet->slot >= $inv->getSize()){
break;
}
$item = Item::get($packet->item->getID(), $packet->item->getDamage(), $packet->item->getCount());
$slot = $tile->getSlot($slotn);
//TODO: container access events?
/*if($this->server->api->dhandle("player.container.slot", array(
"tile" => $tile,
"slot" => $packet->slot,
"offset" => $offset,
"slotdata" => $slot,
"itemdata" => $item,
"player" => $this,
)) === false
){
$pk = new ContainerSetSlotPacket;
$pk->windowid = $packet->windowid;
$pk->slot = $packet->slot;
$pk->item = $slot;
$this->dataPacket($pk);
break;
}*/
if($item->getID() !== Item::AIR and $slot->getID() == $item->getID()){
/** @var Item $item */
$item = clone $packet->item;
$slot = $inv->getItem($packet->slot);
if($item->getID() !== Item::AIR and $slot->equals($item, true)){
if($slot->getCount() < $item->getCount()){
$it = clone $item;
$it->setCount($item->getCount() - $slot->getCount());
if($this->removeItem($it) === false){
$this->sendInventory();
break;
$remaining = $this->inventory->removeItem($it);
if(count($remaining) > 0){
/** @var Item $it */
$it = array_pop($remaining);
$item->setCount($item->getCount() - $it->getCount());
}
}elseif($slot->getCount() > $item->getCount()){
$it = clone $item;
$it->setCount($slot->getCount() - $item->getCount());
$this->addItem($it);
$it->setCount($slot->count - $item->count);
$remaining = $this->inventory->addItem($it);
if(count($remaining) > 0){
/** @var Item $it */
$it = array_pop($remaining);
$item->setCount($item->getCount() + $it->getCount());
}
}else{
if($this->removeItem($item) === false){
$this->sendInventory();
break;
}
$this->addItem($slot);
}
$tile->setSlot($slotn, $item, true, $offset);
}else{
$tile = $this->windows[$packet->windowid];
if(
!($tile instanceof Chest or $tile instanceof Furnace)
or $packet->slot < 0
or (
$tile instanceof Chest
and $packet->slot >= Chest::SLOTS
) or (
$tile instanceof Furnace and $packet->slot >= Furnace::SLOTS
)
){
break;
}
$item = Item::get($packet->item->getID(), $packet->item->getDamage(), $packet->item->getCount());
$slot = $tile->getSlot($packet->slot);
//TODO: container access events?
/*if($this->server->api->dhandle("player.container.slot", array(
"tile" => $tile,
"slot" => $packet->slot,
"slotdata" => $slot,
"itemdata" => $item,
"player" => $this,
)) === false
){
$pk = new ContainerSetSlotPacket;
$pk->windowid = $packet->windowid;
$pk->slot = $packet->slot;
$pk->item = $slot;
$this->dataPacket($pk);
break;
}*/
if($tile instanceof Furnace and $packet->slot == 2){
if($inv->getType()->getDefaultTitle() === "Furnace" and $packet->slot == 2){
switch($slot->getID()){
case Item::IRON_INGOT:
$this->awardAchievement("acquireIron");
break;
}
}
}else{ //TODO: check this. I don't know what is this for
$remaining = $this->inventory->removeItem($item);
if(count($remaining) > 0){
$this->inventory->removeItem();
break;
}
$this->inventory->addItem($slot);
}
$inv->setItem($packet->slot, $item);
if($item->getID() !== Item::AIR and $slot->getID() == $item->getID()){
if($slot->getCount() < $item->getCount()){
$it = clone $item;
$it->setCount($item->getCount() - $slot->getCount());
if($this->removeItem($it) === false){
$this->sendInventory();
break;
}
}elseif($slot->getCount() > $item->getCount()){
$it = clone $item;
$it->setCount($slot->count - $item->count);
$this->addItem($it);
}
}else{
if($this->removeItem($item) === false){
$this->sendInventory();
break;
}
$this->addItem($slot);
}
$tile->setSlot($packet->slot, $item);
}
break;
case ProtocolInfo::SEND_INVENTORY_PACKET: //TODO, Mojang, enable this ´^_^`
if($this->spawned === false){
@ -2323,9 +2218,8 @@ class Player extends Human implements CommandSender, IPlayer{
$this->server->getPluginManager()->unsubscribeFromPermission(Server::BROADCAST_CHANNEL_USERS, $this);
$this->spawned = false;
console("[INFO] " . TextFormat::AQUA . $this->username . TextFormat::RESET . "[/" . $this->ip . ":" . $this->port . "] logged out due to " . $reason);
$this->windows = [];
$this->armor = [];
$this->inventory = [];
$this->windows = new \SplObjectStorage();
$this->windowIndex = [];
$this->chunksLoaded = [];
$this->chunksOrder = [];
$this->chunkCount = [];
@ -2465,18 +2359,18 @@ class Player extends Human implements CommandSender, IPlayer{
//}
foreach($recipe as $slot => $item){
$s = $this->getSlot($slot);
$s = $this->inventory->getItem($slot);
$s->setCount($s->getCount() - $item->getCount());
if($s->getCount() <= 0){
$this->setSlot($slot, Item::get(Item::AIR, 0, 0));
$this->inventory->setItem($slot, Item::get(Item::AIR, 0, 0));
}
}
foreach($craft as $slot => $item){
$s = $this->getSlot($slot);
$s = $this->inventory->getItem($slot);
if($s->getCount() <= 0 or $s->getID() === Item::AIR){
$this->setSlot($slot, Item::get($item->getID(), $item->getDamage(), $item->getCount()));
$this->inventory->setItem($slot, Item::get($item->getID(), $item->getDamage(), $item->getCount()));
}else{
$this->setSlot($slot, Item::get($item->getID(), $item->getDamage(), $s->getCount() + $item->getCount()));
$this->inventory->setItem($slot, Item::get($item->getID(), $item->getDamage(), $s->getCount() + $item->getCount()));
}
switch($item->getID()){
@ -2497,7 +2391,7 @@ class Player extends Human implements CommandSender, IPlayer{
break;
case Item::CAKE:
$this->awardAchievement("bakeCake");
$this->addItem(Item::get(Item::BUCKET, 0, 3));
$this->inventory->addItem(Item::get(Item::BUCKET, 0, 3));
break;
case Item::STONE_PICKAXE:
case Item::GOLD_PICKAXE:
@ -2519,59 +2413,46 @@ class Player extends Human implements CommandSender, IPlayer{
return $res;
}
public function setSlot($slot, Item $item){
parent::setSlot($slot, $item);
$this->sendInventorySlot($slot);
/**
* @param Inventory $inventory
*
* @return int
*/
public function getWindowId(Inventory $inventory){
if($this->windows->contains($inventory)){
return $this->windows[$inventory];
}
return -1;
}
/**
* Sends a single slot
* TODO: Check if Mojang has implemented this on Minecraft: PE 0.9.0
* Returns the created/existing window id
*
* @param int $s
* @param Inventory $inventory
*
* @return bool
* @return int
*/
public function sendInventorySlot($s){
$this->sendInventory();
public function addWindow(Inventory $inventory){
if($this->windows->contains($inventory)){
return $this->windows[$inventory];
}
$this->windowCnt = $cnt = max(2, ++$this->windowCnt % 99);
$this->windowIndex[$cnt] = $inventory;
$this->windows->attach($inventory, $cnt);
$this->inventory->onOpen($this);
return; //TODO: Check if Mojang adds this
$s = (int) $s;
if(!isset($this->inventory[$s])){
$pk = new ContainerSetSlotPacket;
$pk->windowid = 0;
$pk->slot = (int) $s;
$pk->item = Item::get(Item::AIR, 0, 0);
$this->dataPacket($pk);
return $cnt;
}
$slot = $this->inventory[$s];
$pk = new ContainerSetSlotPacket;
$pk->windowid = 0;
$pk->slot = (int) $s;
$pk->item = $slot;
$this->dataPacket($pk);
return true;
public function removeWindow(Inventory $inventory){
$inventory->onClose($this);
if($this->windows->contains($inventory)){
$inventory->onClose($this);
$id = $this->windows[$inventory];
unset($this->windowIndex[$id]);
}
/**
* Sends the full inventory
*/
public function sendInventory(){
if(($this->gamemode & 0x01) === 1){
return;
}
$hotbar = [];
foreach($this->hotbar as $slot){
$hotbar[] = $slot <= -1 ? -1 : $slot + 9;
}
$pk = new ContainerSetContentPacket;
$pk->windowid = 0;
$pk->slots = $this->inventory;
$pk->hotbar = $hotbar;
$this->dataPacket($pk);
}
public function setMetadata($metadataKey, MetadataValue $metadataValue){

View File

@ -31,7 +31,6 @@ use pocketmine\block\Furnace;
use pocketmine\command\CommandReader;
use pocketmine\command\CommandSender;
use pocketmine\command\ConsoleCommandSender;
use pocketmine\command\PluginCommand;
use pocketmine\command\PluginIdentifiableCommand;
use pocketmine\command\SimpleCommandMap;
use pocketmine\entity\Entity;
@ -41,6 +40,7 @@ use pocketmine\event\server\PacketSendEvent;
use pocketmine\event\server\ServerCommandEvent;
use pocketmine\inventory\InventoryType;
use pocketmine\item\Item;
use pocketmine\level\format\pmf\LevelFormat;
use pocketmine\level\generator\Flat;
use pocketmine\level\generator\Generator;
use pocketmine\level\generator\Normal;
@ -73,7 +73,6 @@ use pocketmine\permission\DefaultPermissions;
use pocketmine\plugin\Plugin;
use pocketmine\plugin\PluginLoadOrder;
use pocketmine\plugin\PluginManager;
use pocketmine\level\format\pmf\LevelFormat;
use pocketmine\recipes\Crafting;
use pocketmine\scheduler\CallbackTask;
use pocketmine\scheduler\SendUsageTask;
@ -795,6 +794,7 @@ class Server{
return true;
}elseif(!$this->isLevelGenerated($name)){
console("[NOTICE] Level \"" . $name . "\" not found");
return false;
}

View File

@ -24,7 +24,6 @@ namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\network\protocol\ChatPacket;
use pocketmine\Player;
use pocketmine\Server;
class Bed extends Transparent{
public function __construct($type = 0){

View File

@ -25,7 +25,6 @@
namespace pocketmine\block;
use pocketmine\item\Item;
use pocketmine\level\Level;
use pocketmine\level\Position;
use pocketmine\metadata\Metadatable;
use pocketmine\metadata\MetadataValue;

View File

@ -118,8 +118,8 @@ class BurningFurnace extends Solid{
}
$t = $this->getLevel()->getTile($this);
if($t instanceof Furnace){
for($s = 0; $s < Furnace::SLOTS; ++$s){
$slot = $t->getSlot($s);
for($s = 0; $s < $t->getInventory()->getSize(); ++$s){
$slot = $t->getInventory()->getItem($s);
if($slot->getID() > Item::AIR and $slot->getCount() > 0){
$drops[] = array($slot->getID(), $slot->getDamage(), $slot->getCount());
}

View File

@ -59,8 +59,9 @@ class Chest extends Transparent{
continue;
}
$c = $this->getSide($side);
if(($c instanceof TileChest) and $c->getDamage() === $this->meta){
if((($tile = $this->getLevel()->getTile($c)) instanceof TileChest) and !$tile->isPaired()){
if($c instanceof Chest and $c->getDamage() === $this->meta){
$tile = $this->getLevel()->getTile($c);
if($tile instanceof TileChest and !$tile->isPaired()){
$chest = $tile;
break;
}
@ -104,7 +105,7 @@ class Chest extends Transparent{
}
$t = $this->getLevel()->getTile($this);
$chest = false;
$chest = null;
if($t instanceof TileChest){
$chest = $t;
}else{
@ -123,8 +124,7 @@ class Chest extends Transparent{
if(($player->gamemode & 0x01) === 0x01){
return true;
}
$chest->openInventory($player);
$player->addWindow($chest->getInventory());
}
return true;
@ -135,9 +135,9 @@ class Chest extends Transparent{
array($this->id, 0, 1),
);
$t = $this->getLevel()->getTile($this);
if($t instanceof Chest){
for($s = 0; $s < Chest::SLOTS; ++$s){
$slot = $t->getSlot($s);
if($t instanceof TileChest){
for($s = 0; $s < $t->getInventory()->getSize(); ++$s){
$slot = $t->getInventory()->getItem($s);
if($slot->getID() > Item::AIR and $slot->getCount() > 0){
$drops[] = array($slot->getID(), $slot->getDamage(), $slot->getCount());
}

View File

@ -50,10 +50,10 @@ use pocketmine\command\defaults\StatusCommand;
use pocketmine\command\defaults\StopCommand;
use pocketmine\command\defaults\TeleportCommand;
use pocketmine\command\defaults\TellCommand;
use pocketmine\command\defaults\TimeCommand;
use pocketmine\command\defaults\VanillaCommand;
use pocketmine\command\defaults\VersionCommand;
use pocketmine\command\defaults\WhitelistCommand;
use pocketmine\command\defaults\TimeCommand;
use pocketmine\Server;
class SimpleCommandMap implements CommandMap{

View File

@ -21,10 +21,8 @@
namespace pocketmine\command\defaults;
use pocketmine\command\Command;
use pocketmine\command\CommandSender;
use pocketmine\Player;
use pocketmine\Server;
use pocketmine\utils\TextFormat;
class KillCommand extends VanillaCommand{

View File

@ -23,7 +23,6 @@ namespace pocketmine\command\defaults;
use pocketmine\command\Command;
use pocketmine\command\CommandSender;
use pocketmine\event\HandlerList;
use pocketmine\Server;
use pocketmine\utils\TextFormat;

View File

@ -23,8 +23,6 @@ namespace pocketmine\command\defaults;
use pocketmine\command\Command;
use pocketmine\command\CommandSender;
use pocketmine\command\ConsoleCommandSender;
use pocketmine\level\Position;
use pocketmine\math\Vector3;
use pocketmine\Player;
use pocketmine\Server;
@ -52,6 +50,7 @@ class SetWorldSpawnCommand extends VanillaCommand{
$pos = $sender->round();
}else{
$sender->sendMessage(TextFormat::RED . "You can only perform this command as a player");
return true;
}
}elseif(count($args) === 3){
@ -59,12 +58,14 @@ class SetWorldSpawnCommand extends VanillaCommand{
$pos = new Vector3($this->getInteger($sender, $args[0]), $this->getInteger($sender, $args[1]), $this->getInteger($sender, $args[2]));
}else{
$sender->sendMessage(TextFormat::RED . "Usage: " . $this->usageMessage);
return true;
}
$level->setSpawn($pos);
Command::broadcastCommandMessage($sender, "Set world " . $level->getName() . "'s spawnpoint to " . $pos->x . ", " . $pos->y . ", " . $pos->z);
return true;
}
}

View File

@ -51,12 +51,14 @@ class SpawnpointCommand extends VanillaCommand{
$target = $sender;
}else{
$sender->sendMessage(TextFormat::RED . "Please provide a player!");
return true;
}
}else{
$target = Server::getInstance()->getPlayer($args[0]);
if($target === null){
$sender->sendMessage(TextFormat::RED . "Can't find player " . $args[0]);
return true;
}
}
@ -70,6 +72,7 @@ class SpawnpointCommand extends VanillaCommand{
$z = (int) $this->getRelativeDouble($sender->z, $sender, $args[3]);
$target->setSpawn(new Position($x, $y, $z, $level));
Command::broadcastCommandMessage($sender, "Set " . $target->getName() . "'s spawnpoint to " . $x . ", " . $y . ", " . $z);
return true;
}
}elseif(count($args) <= 1){
@ -77,14 +80,17 @@ class SpawnpointCommand extends VanillaCommand{
$pos = new Position((int) $sender->x, (int) $sender->y, (int) $sender->z, $sender->getLevel());
$target->setSpawn($pos);
Command::broadcastCommandMessage($sender, "Set " . $target->getName() . "'s spawnpoint to " . $pos->x . ", " . $pos->y . ", " . $pos->z);
return true;
}else{
$sender->sendMessage(TextFormat::RED . "Please provide a player!");
return true;
}
}
$sender->sendMessage(TextFormat::RED . "Usage: " . $this->usageMessage);
return true;
}
}

View File

@ -22,7 +22,6 @@
namespace pocketmine\command\defaults;
use pocketmine\command\CommandSender;
use pocketmine\Player;
use pocketmine\Server;
use pocketmine\utils\TextFormat;
@ -48,6 +47,7 @@ class StatusCommand extends VanillaCommand{
$sender->sendMessage(TextFormat::GOLD . "Upload: " . TextFormat::WHITE . round($server->getNetwork()->getUploadSpeed() / 1024, 2) . " kB/s");
$sender->sendMessage(TextFormat::GOLD . "Download: " . TextFormat::WHITE . round($server->getNetwork()->getDownloadSpeed() / 1024, 2) . " kB/s");
$sender->sendMessage(TextFormat::GOLD . "Memory: " . TextFormat::WHITE . round((memory_get_usage() / 1024) / 1024, 2) . TextFormat::YELLOW . "/" . TextFormat::WHITE . round((memory_get_usage(true) / 1024) / 1024, 2) . " MB");
return true;
}
}

View File

@ -47,6 +47,7 @@ class TeleportCommand extends VanillaCommand{
if(count($args) < 1 or count($args) > 4){
$sender->sendMessage(TextFormat::RED . "Usage: " . $this->usageMessage);
return true;
}
@ -58,12 +59,14 @@ class TeleportCommand extends VanillaCommand{
$target = $sender;
}else{
$sender->sendMessage(TextFormat::RED . "Please provide a player!");
return true;
}
}else{
$target = Server::getInstance()->getPlayer($args[0]);
if($target === null){
$sender->sendMessage(TextFormat::RED . "Can't find player " . $args[0]);
return true;
}
if(count($args) === 2){
@ -71,6 +74,7 @@ class TeleportCommand extends VanillaCommand{
$target = Server::getInstance()->getPlayer($args[1]);
if($target === null){
$sender->sendMessage(TextFormat::RED . "Can't find player " . $args[1]);
return true;
}
}
@ -80,6 +84,7 @@ class TeleportCommand extends VanillaCommand{
$pos = new Position($target->x, $target->y, $target->z, $target->getLevel());
$origin->teleport($pos);
Command::broadcastCommandMessage($sender, "Teleported " . $origin->getName() . " to " . $target->getName());
return true;
}elseif($target->getLevel() !== null){
$pos = count($args) === 4 ? 1 : 0;
@ -88,10 +93,12 @@ class TeleportCommand extends VanillaCommand{
$z = $this->getRelativeDouble($target->z, $sender, $args[$pos]);
$target->teleport(new Vector3($x, $y, $z));
Command::broadcastCommandMessage($sender, "Teleported " . $target->getName() . " to " . round($x, 2) . ", " . round($y, 2) . ", " . round($z, 2));
return true;
}
$sender->sendMessage(TextFormat::RED . "Usage: " . $this->usageMessage);
return true;
}
}

View File

@ -6,7 +6,6 @@ use pocketmine\command\Command;
use pocketmine\command\CommandSender;
use pocketmine\Server;
use pocketmine\utils\TextFormat;
use pocketmine\network\protocol\SetTimePacket;
class TimeCommand extends VanillaCommand{
public function __construct($name){
@ -21,6 +20,7 @@ class TimeCommand extends VanillaCommand{
public function execute(CommandSender $sender, $label, array $args){
if(count($args) < 2){
$sender->sendMessage(TextFormat::RED . "Incorrect usage. Correct usage:\n" . $this->getUsage());
return false;
}
@ -28,6 +28,7 @@ class TimeCommand extends VanillaCommand{
case "set":
if(!$sender->hasPermission("pocketmine.command.time.add")){
$sender->sendMessage(TextFormat::RED . "You don't have permission to set the time");
return true;
}
@ -48,6 +49,7 @@ class TimeCommand extends VanillaCommand{
case "add":
if(!$sender->hasPermission("pocketmine.command.time.add")){
$sender->sendMessage(TextFormat::RED . "You don't have permission to set the time");
return true;
}

View File

@ -29,6 +29,7 @@ use pocketmine\event\entity\EntityLevelChangeEvent;
use pocketmine\event\entity\EntityMotionEvent;
use pocketmine\event\entity\EntityMoveEvent;
use pocketmine\event\entity\EntitySpawnEvent;
use pocketmine\level\format\pmf\LevelFormat;
use pocketmine\level\Level;
use pocketmine\level\Position;
use pocketmine\math\AxisAlignedBB;
@ -36,14 +37,13 @@ use pocketmine\math\Vector3 as Vector3;
use pocketmine\metadata\Metadatable;
use pocketmine\metadata\MetadataValue;
use pocketmine\nbt\tag\Compound;
use pocketmine\Network;
use pocketmine\network\protocol\MoveEntityPacket_PosRot;
use pocketmine\network\protocol\MovePlayerPacket;
use pocketmine\network\protocol\RemoveEntityPacket;
use pocketmine\network\protocol\SetEntityMotionPacket;
use pocketmine\network\protocol\SetTimePacket;
use pocketmine\Network;
use pocketmine\Player;
use pocketmine\level\format\pmf\LevelFormat;
use pocketmine\plugin\Plugin;
use pocketmine\Server;
@ -176,6 +176,10 @@ abstract class Entity extends Position implements Metadatable{
protected abstract function initEntity();
public function getViewers(){
return $this->hasSpawned;
}
public function spawnTo(Player $player){
if(!isset($this->hasSpawned[$player->getID()]) and $player->chunksLoaded[$this->chunkIndex] !== 0xff){
$this->hasSpawned[$player->getID()] = $player;

View File

@ -21,54 +21,46 @@
namespace pocketmine\entity;
use pocketmine\event\entity\EntityArmorChangeEvent;
use pocketmine\event\entity\EntityInventoryChangeEvent;
use pocketmine\inventory\InventoryHolder;
use pocketmine\inventory\PlayerInventory;
use pocketmine\item\Item;
use pocketmine\nbt\NBT;
use pocketmine\nbt\tag\Byte;
use pocketmine\nbt\tag\Compound;
use pocketmine\nbt\tag\Enum;
use pocketmine\nbt\tag\Short;
use pocketmine\Network;
use pocketmine\network\protocol\AddPlayerPacket;
use pocketmine\network\protocol\ContainerSetContentPacket;
use pocketmine\network\protocol\PlayerArmorEquipmentPacket;
use pocketmine\network\protocol\PlayerEquipmentPacket;
use pocketmine\network\protocol\RemovePlayerPacket;
use pocketmine\network\protocol\SetEntityMotionPacket;
use pocketmine\Network;
use pocketmine\Player;
use pocketmine\Server;
class Human extends Creature implements ProjectileSource, InventorySource{
class Human extends Creature implements ProjectileSource, InventoryHolder{
protected $nameTag = "TESTIFICATE";
protected $inventory = [];
public $slot;
protected $hotbar = [];
protected $armor = [];
/** @var PlayerInventory */
protected $inventory;
public function getInventory(){
return $this->inventory;
}
protected function initEntity(){
$this->inventory = new PlayerInventory($this);
if(isset($this->namedtag->NameTag)){
$this->nameTag = $this->namedtag["NameTag"];
}
$this->hotbar = array(-1, -1, -1, -1, -1, -1, -1, -1, -1);
$this->armor = array(
0 => Item::get(Item::AIR, 0, 0),
1 => Item::get(Item::AIR, 0, 0),
2 => Item::get(Item::AIR, 0, 0),
3 => Item::get(Item::AIR, 0, 0)
);
foreach($this->namedtag->Inventory as $item){
if($item["Slot"] >= 0 and $item["Slot"] < 9){ //Hotbar
$this->hotbar[$item["Slot"]] = isset($item["TrueSlot"]) ? $item["TrueSlot"] : -1;
$this->inventory->setHotbarSlotIndex($item["Slot"], isset($item["TrueSlot"]) ? $item["TrueSlot"] : -1);
}elseif($item["Slot"] >= 100 and $item["Slot"] < 104){ //Armor
$this->armor[$item["Slot"] - 100] = Item::get($item["id"], $item["Damage"], $item["Count"]);
$this->inventory->setItem($this->inventory->getSize() + $item["Slot"] - 100, Item::get($item["id"], $item["Damage"], $item["Count"]));
}else{
$this->inventory[$item["Slot"] - 9] = Item::get($item["id"], $item["Damage"], $item["Count"]);
$this->inventory->setItem($item["Slot"] - 9, Item::get($item["id"], $item["Damage"], $item["Count"]));
}
}
$this->slot = $this->hotbar[0];
$this->height = 1.8; //Or 1.62?
$this->width = 0.6;
@ -79,14 +71,15 @@ class Human extends Creature implements ProjectileSource, InventorySource{
$this->namedtag->Inventory = new Enum("Inventory", []);
$this->namedtag->Inventory->setTagType(NBT::TAG_Compound);
for($slot = 0; $slot < 9; ++$slot){
if(isset($this->hotbar[$slot]) and $this->hotbar[$slot] !== -1){
$item = $this->getSlot($this->hotbar[$slot]);
$hotbarSlot = $this->inventory->getHotbarSlotIndex($slot);
if($hotbarSlot !== -1){
$item = $this->inventory->getItem($hotbarSlot);
if($item->getID() !== 0 and $item->getCount() > 0){
$this->namedtag->Inventory[$slot] = new Compound(false, array(
new Byte("Count", $item->getCount()),
new Short("Damage", $item->getDamage()),
new Byte("Slot", $slot),
new Byte("TrueSlot", $this->hotbar[$slot]),
new Byte("TrueSlot", $hotbarSlot),
new Short("id", $item->getID()),
));
continue;
@ -105,7 +98,7 @@ class Human extends Creature implements ProjectileSource, InventorySource{
$slotCount = Player::SURVIVAL_SLOTS + 9;
//$slotCount = (($this instanceof Player and ($this->gamemode & 0x01) === 1) ? Player::CREATIVE_SLOTS : Player::SURVIVAL_SLOTS) + 9;
for($slot = 9; $slot < $slotCount; ++$slot){
$item = $this->getSlot($slot - 9);
$item = $this->inventory->getItem($slot - 9);
$this->namedtag->Inventory[$slot] = new Compound(false, array(
new Byte("Count", $item->getCount()),
new Short("Damage", $item->getDamage()),
@ -116,8 +109,8 @@ class Human extends Creature implements ProjectileSource, InventorySource{
//Armor
for($slot = 100; $slot < 104; ++$slot){
$item = $this->armor[$slot - 100];
if($item instanceof Item){
$item = $this->inventory->getItem($this->inventory->getSize() + $slot - 100);
if($item instanceof Item and $item->getID() !== Item::AIR){
$this->namedtag->Inventory[$slot] = new Compound(false, array(
new Byte("Count", $item->getCount()),
new Short("Damage", $item->getDamage()),
@ -135,7 +128,7 @@ class Human extends Creature implements ProjectileSource, InventorySource{
$pk = new AddPlayerPacket;
$pk->clientID = 0;
$pk->username = $this->nameTag;
$pk->eid = $this->id;
$pk->eid = $this->getID();
$pk->x = $this->x;
$pk->y = $this->y;
$pk->z = $this->z;
@ -147,15 +140,15 @@ class Human extends Creature implements ProjectileSource, InventorySource{
$player->dataPacket($pk);
$pk = new SetEntityMotionPacket;
$pk->eid = $this->id;
$pk->eid = $this->getID();
$pk->speedX = $this->motionX;
$pk->speedY = $this->motionY;
$pk->speedZ = $this->motionZ;
$player->dataPacket($pk);
$this->sendCurrentEquipmentSlot($player);
$this->inventory->sendHeldItem($player);
$this->sendArmor($player);
$this->inventory->sendArmorContents($player);
}
}
@ -169,104 +162,6 @@ class Human extends Creature implements ProjectileSource, InventorySource{
}
}
public function setEquipmentSlot($equipmentSlot, $inventorySlot){
$this->hotbar[$equipmentSlot] = $inventorySlot;
if($equipmentSlot === $this->slot){
foreach($this->hasSpawned as $p){
$this->sendCurrentEquipmentSlot($p);
}
}
}
public function getEquipmentSlot($equipmentSlot){
if(isset($this->hotbar[$equipmentSlot])){
return $this->hotbar[$equipmentSlot];
}
return -1;
}
public function setCurrentEquipmentSlot($slot){
if(isset($this->hotbar[$slot])){
$this->slot = (int) $slot;
foreach($this->hasSpawned as $p){
$this->sendCurrentEquipmentSlot($p);
}
}
}
public function getCurrentEquipmentSlot(){
return $this->slot;
}
public function getCurrentEquipment(){
if($this->slot > -1) {
return $this->hotbar[$this->slot];
}
}
public function sendCurrentEquipmentSlot(Player $player){
$pk = new PlayerEquipmentPacket;
$pk->eid = $this->id;
$pk->item = $this->getSlot($this->slot)->getID();
$pk->meta = $this->getSlot($this->slot)->getDamage();
$pk->slot = 0;
$player->dataPacket($pk);
}
public function setArmorSlot($slot, Item $item){
Server::getInstance()->getPluginManager()->callEvent($ev = new EntityArmorChangeEvent($this, $this->getArmorSlot($slot), $item, $slot));
if($ev->isCancelled()){
return false;
}
$this->armor[(int) $slot] = $ev->getNewItem();
foreach($this->hasSpawned as $p){
$this->sendArmor($p);
}
if($this instanceof Player){
$this->sendArmor();
}
return true;
}
/**
* @param int $slot
*
* @return Item
*/
public function getArmorSlot($slot){
$slot = (int) $slot;
if(!isset($this->armor[$slot])){
$this->armor[$slot] = Item::get(Item::AIR, 0, 0);
}
return $this->armor[$slot];
}
public function sendArmor($player = null){
$slots = [];
for($i = 0; $i < 4; ++$i){
if(isset($this->armor[$i]) and ($this->armor[$i] instanceof Item) and $this->armor[$i]->getID() > Item::AIR){
$slots[$i] = $this->armor[$i]->getID() !== Item::AIR ? $this->armor[$i]->getID() - 256 : 0;
}else{
$this->armor[$i] = Item::get(Item::AIR, 0, 0);
$slots[$i] = 255;
}
}
if($player instanceof Player){
$pk = new PlayerArmorEquipmentPacket();
$pk->eid = $this->id;
$pk->slots = $slots;
$player->dataPacket($pk);
}elseif($this instanceof Player){
$pk = new ContainerSetContentPacket;
$pk->windowid = 0x78; //Armor window id
$pk->slots = $this->armor;
$this->dataPacket($pk);
}
}
public function getData(){ //TODO
$flags = 0;
$flags |= $this->fireTicks > 0 ? 1 : 0;
@ -305,132 +200,4 @@ class Human extends Creature implements ProjectileSource, InventorySource{
}
public function hasItem(Item $item, $checkDamage = true){
foreach($this->inventory as $s => $i){
if($i->equals($item, $checkDamage)){
return $i;
}
}
return false;
}
public function canAddItem(Item $item){
$inv = $this->inventory;
while($item->getCount() > 0){
$add = 0;
foreach($inv as $s => $i){
if($i->getID() === Item::AIR){
$add = min($i->getMaxStackSize(), $item->getCount());
$inv[$s] = clone $item;
$inv[$s]->setCount($add);
break;
}elseif($i->equals($item)){
$add = min($i->getMaxStackSize() - $i->getCount(), $item->getCount());
if($add <= 0){
continue;
}
$inv[$s] = clone $item;
$inv[$s]->setCount($i->getCount() + $add);
break;
}
}
if($add <= 0){
return false;
}
$item->setCount($item->getCount() - $add);
}
return true;
}
public function addItem(Item $item){
while($item->getCount() > 0){
$add = 0;
foreach($this->inventory as $s => $i){
if($i->getID() === Item::AIR){
$add = min($i->getMaxStackSize(), $item->getCount());
$i2 = clone $item;
$i2->setCount($add);
$this->setSlot($s, $i2);
break;
}elseif($i->equals($item)){
$add = min($i->getMaxStackSize() - $i->getCount(), $item->getCount());
if($add <= 0){
continue;
}
$i2 = clone $item;
$i2->setCount($i->getCount() + $add);
$this->setSlot($s, $i2);
break;
}
}
if($add <= 0){
return false;
}
$item->setCount($item->getCount() - $add);
}
return true;
}
public function canRemoveItem(Item $item, $checkDamage = true){
return $this->hasItem($item, $checkDamage);
}
public function removeItem(Item $item, $checkDamage = true){
while($item->getCount() > 0){
$remove = 0;
foreach($this->inventory as $s => $i){
if($i->equals($item, $checkDamage)){
$remove = min($item->getCount(), $i->getCount());
if($item->getCount() < $i->getCount()){
$i->setCount($i->getCount() - $item->getCount());
$this->setSlot($s, $i);
}else{
$this->setSlot($s, Item::get(Item::AIR, 0, 0));
}
break;
}
}
if($remove <= 0){
return false;
}
$item->setCount($item->getCount() - $remove);
}
return true;
}
public function setSlot($slot, Item $item){
Server::getInstance()->getPluginManager()->callEvent($ev = new EntityInventoryChangeEvent($this, $this->getSlot($slot), $item, $slot));
if($ev->isCancelled()){
return false;
}
$this->inventory[(int) $slot] = $ev->getNewItem();
return true;
}
/**
* @param int $slot
*
* @return Item
*/
public function getSlot($slot){
$slot = (int) $slot;
if(!isset($this->inventory[$slot])){
$this->inventory[$slot] = Item::get(Item::AIR, 0, 0);
}
return $this->inventory[$slot];
}
public function getAllSlots(){
return $this->inventory;
}
public function getSlotCount(){
return count($this->inventory);
}
}

View File

@ -21,8 +21,8 @@
namespace pocketmine\event\player;
use pocketmine\event\Cancellable;
use pocketmine\Event;
use pocketmine\event\Cancellable;
use pocketmine\item\Item;
use pocketmine\Player;

View File

@ -21,8 +21,8 @@
namespace pocketmine\event\server;
use pocketmine\event;
use pocketmine\event\Cancellable;
use pocketmine\event;
use pocketmine\network\protocol\DataPacket;
use pocketmine\Player;

View File

@ -21,8 +21,8 @@
namespace pocketmine\event\server;
use pocketmine\event;
use pocketmine\event\Cancellable;
use pocketmine\event;
use pocketmine\network\protocol\DataPacket;
use pocketmine\Player;

View File

@ -1,35 +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/
*
*
*/
/**
* Events used by Tiles
*/
namespace pocketmine\event\tile;
use pocketmine\event\Event;
abstract class TileEvent extends Event{
protected $tile;
public function getTile(){
return $this->tile;
}
}

View File

@ -1,60 +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/
*
*
*/
namespace pocketmine\event\tile;
use pocketmine\Event;
use pocketmine\event\Cancellable;
use pocketmine\item\Item;
use pocketmine\tile\Tile;
class TileInventoryChangeEvent extends TileEvent implements Cancellable{
public static $handlerList = null;
private $oldItem;
private $newItem;
private $slot;
public function __construct(Tile $tile, Item $oldItem, Item $newItem, $slot){
$this->tile = $tile;
$this->oldItem = $oldItem;
$this->newItem = $newItem;
$this->slot = (int) $slot;
}
public function getSlot(){
return $this->slot;
}
public function getNewItem(){
return $this->newItem;
}
public function setNewItem(Item $item){
$this->newItem = $item;
}
public function getOldItem(){
return $this->oldItem;
}
}

View File

@ -21,9 +21,13 @@
namespace pocketmine\inventory;
use pocketmine\entity\Entity;
use pocketmine\event\entity\EntityInventoryChangeEvent;
use pocketmine\item\Item;
use pocketmine\network\protocol\ContainerSetContentPacket;
use pocketmine\network\protocol\ContainerSetSlotPacket;
use pocketmine\Player;
use pocketmine\item\Item;
use pocketmine\Server;
abstract class BaseInventory implements Inventory{
@ -57,7 +61,7 @@ abstract class BaseInventory implements Inventory{
//A holder can be a plugin, or an entity
if($this->holder instanceof Player){
$this->viewers->attach($this->holder);
$this->holder->addWindow($this, 0);
}
@ -123,18 +127,34 @@ abstract class BaseInventory implements Inventory{
}
public function setItem($index, Item $item){
if($index < 0 or $index >= $this->size or $item->getID() === 0){
return;
if($index < 0 or $index >= $this->size){
return false;
}elseif($item->getID() === 0){
$this->clear($index);
}
$holder = $this->getHolder();
if($holder instanceof Entity){
Server::getInstance()->getPluginManager()->callEvent($ev = new EntityInventoryChangeEvent($holder, $this->getItem($index), $item, $index));
if($ev->isCancelled()){
$this->sendContents($this->getViewers());
return false;
}
$item = $ev->getNewItem();
}
$old = $this->slots[$index];
$this->slots[$index] = clone $item;
$this->onSlotChange($index, $old);
return true;
}
public function contains(Item $item){
$count = max(1, $item->getCount());
$checkDamage = $item->getDamage() === null ? false : true;
foreach($this->slots as $i){
foreach($this->getContents() as $i){
if($item->equals($i, $checkDamage)){
$count -= $i->getCount();
if($count <= 0){
@ -149,7 +169,7 @@ abstract class BaseInventory implements Inventory{
public function all(Item $item){
$slots = [];
$checkDamage = $item->getDamage() === null ? false : true;
foreach($this->slots as $index => $i){
foreach($this->getContents() as $index => $i){
if($item->equals($i, $checkDamage)){
$slots[$index] = $i;
}
@ -160,7 +180,7 @@ abstract class BaseInventory implements Inventory{
public function remove(Item $item){
$checkDamage = $item->getDamage() === null ? false : true;
foreach($this->slots as $index => $i){
foreach($this->getContents() as $index => $i){
if($item->equals($i, $checkDamage)){
$this->clear($index);
}
@ -170,7 +190,7 @@ abstract class BaseInventory implements Inventory{
public function first(Item $item){
$count = max(1, $item->getCount());
$checkDamage = $item->getDamage() === null ? false : true;
foreach($this->slots as $index => $i){
foreach($this->getContents() as $index => $i){
if($item->equals($i, $checkDamage) and $i->getCount() >= $count){
return $index;
}
@ -181,10 +201,7 @@ abstract class BaseInventory implements Inventory{
public function firstEmpty(){
for($i = 0; $i < $this->size; ++$i){
if(!isset($this->slots[$i])){
return $i;
}elseif(!($this->slots[$i] instanceof Item) or $this->slots[$i]->getID() === 0 or $this->slots[$i]->getCount() <= 0){
unset($this->slots[$i]);
if($this->getItem($i)->getID() === Item::AIR){
return $i;
}
}
@ -196,11 +213,10 @@ abstract class BaseInventory implements Inventory{
/** @var Item[] $slots */
$slots = func_get_args();
for($i = 0; $i < $this->size; ++$i){
if(!isset($this->slots[$i])){
$item = $this->slots[$i] = array_shift($slots);
$this->onSlotChange($i, null);
}else{
$item = $this->slots[$i];
$item = $this->getItem($i);
if($item->getID() === Item::AIR){
$item = array_shift($slots);
$this->setItem($i, $item);
}
foreach($slots as $index => $slot){
@ -230,10 +246,9 @@ abstract class BaseInventory implements Inventory{
/** @var Item[] $slots */
$slots = func_get_args();
for($i = 0; $i < $this->size; ++$i){
if(!isset($this->slots[$i])){
$item = $this->getItem($i);
if($item->getID() === Item::AIR){
continue;
}else{
$item = $this->slots[$i];
}
foreach($slots as $index => $slot){
@ -263,14 +278,32 @@ abstract class BaseInventory implements Inventory{
public function clear($index){
if(isset($this->slots[$index])){
$item = Item::get(Item::AIR, null, 0);
$old = $this->slots[$index];
$holder = $this->getHolder();
if($holder instanceof Entity){
Server::getInstance()->getPluginManager()->callEvent($ev = new EntityInventoryChangeEvent($holder, $old, $item, $index));
if($ev->isCancelled()){
$this->sendContents($this->getViewers());
return false;
}
$item = $ev->getNewItem();
}
if($item->getID() !== Item::AIR){
$this->slots[$index] = clone $item;
}else{
unset($this->slots[$index]);
}
$this->onSlotChange($index, $old);
}
return true;
}
public function clearAll(){
foreach($this->slots as $index => $i){
foreach($this->getContents() as $index => $i){
$this->clear($index);
}
}
@ -280,6 +313,7 @@ abstract class BaseInventory implements Inventory{
foreach($this->viewers as $viewer){
$viewers[] = $viewer;
}
return $viewers;
}
@ -300,12 +334,44 @@ abstract class BaseInventory implements Inventory{
}
public function onSlotChange($index, $before){
$this->sendSlot($index, $this->getViewers());
}
/**
* @param Player|Player[] $target
*/
public function sendContents($target){
if($target instanceof Player){
$target = [$target];
}
$pk = new ContainerSetContentPacket();
$pk->slots = [];
for($i = 0; $i < $this->getSize(); ++$i){
$pk->slots[$i] = $this->getItem($i);
}
foreach($target as $player){
$pk->windowid = $player->getWindowId($this);
$player->dataPacket(clone $pk);
}
}
/**
* @param int $index
* @param Player|Player[] $target
*/
public function sendSlot($index, $target){
if($target instanceof Player){
$target = [$target];
}
$pk = new ContainerSetSlotPacket;
$pk->slot = $index;
$pk->item = clone $this->getItem($index);
/** @var Player $player */
foreach($this->getViewers() as $player){
foreach($target as $player){
$pk->windowid = $player->getWindowId($this);
$player->dataPacket(clone $pk);
}

View File

@ -0,0 +1,67 @@
<?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/
*
*
*/
namespace pocketmine\inventory;
use pocketmine\network\protocol\TileEventPacket;
use pocketmine\Player;
use pocketmine\tile\Chest;
class ChestInventory extends ContainerInventory{
public function __construct(Chest $tile){
parent::__construct($tile, InventoryType::get(InventoryType::CHEST));
}
/**
* @return Chest
*/
public function getHolder(){
return $this->holder;
}
public function onOpen(Player $who){
parent::onOpen($who);
if(count($this->getViewers()) === 1){
$pk = new TileEventPacket;
$pk->x = $this->getHolder()->getX();
$pk->y = $this->getHolder()->getY();
$pk->z = $this->getHolder()->getZ();
$pk->case1 = 1;
$pk->case2 = 2;
Player::broadcastPacket($this->getHolder()->getLevel()->getPlayers(), $pk);
}
}
public function onClose(Player $who){
parent::onClose($who);
if(count($this->getViewers()) === 1){
$pk = new TileEventPacket;
$pk->x = $this->getHolder()->getX();
$pk->y = $this->getHolder()->getY();
$pk->z = $this->getHolder()->getZ();
$pk->case1 = 1;
$pk->case2 = 0;
Player::broadcastPacket($this->getHolder()->getLevel()->getPlayers(), $pk);
}
}
}

View File

@ -0,0 +1,55 @@
<?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/
*
*
*/
namespace pocketmine\inventory;
use pocketmine\network\protocol\ContainerClosePacket;
use pocketmine\network\protocol\ContainerOpenPacket;
use pocketmine\Player;
use pocketmine\tile\Chest;
use pocketmine\tile\Furnace;
abstract class ContainerInventory extends BaseInventory{
/**
* @return Chest|Furnace
*/
public function getHolder(){
return $this->holder;
}
public function onOpen(Player $who){
$pk = new ContainerOpenPacket;
$pk->windowid = $who->getWindowId($this);
$pk->type = 0;
$pk->slots = $this->getSize();
$pk->x = $this->getHolder()->getX();
$pk->y = $this->getHolder()->getY();
$pk->z = $this->getHolder()->getZ();
$who->dataPacket($pk);
}
public function onClose(Player $who){
$pk = new ContainerClosePacket;
$pk->windowid = $who->getWindowId($this);
$who->dataPacket($pk);
}
}

View File

@ -0,0 +1,101 @@
<?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/
*
*
*/
namespace pocketmine\inventory;
use pocketmine\item\Item;
use pocketmine\tile\Chest;
class DoubleChestInventory extends ChestInventory implements InventoryHolder{
/** @var ChestInventory */
private $left;
/** @var ChestInventory */
private $right;
public function __construct(Chest $left, Chest $right){
$this->left = $left->getRealInventory();
$this->right = $right->getRealInventory();
BaseInventory::__construct($this, InventoryType::get(InventoryType::DOUBLE_CHEST));
}
//TODO
public function getInventory(){
return $this;
}
//TODO
public function getHolder(){
return $this->left;
}
public function getItem($index){
return $index < $this->left->getSize() ? $this->left->getItem($index) : $this->right->getItem($index - $this->right->getSize());
}
public function setItem($index, Item $item){
return $index < $this->left->getSize() ? $this->left->setItem($index, $item) : $this->right->setItem($index - $this->right->getSize(), $item);
}
public function clear($index){
return $index < $this->left->getSize() ? $this->left->clear($index) : $this->right->clear($index - $this->right->getSize());
}
public function getContents(){
$contents = [];
for($i = 0; $i < $this->getSize(); ++$i){
$contents[$i] = $this->getItem($i);
}
return $contents;
}
/**
* @param Item[] $items
*/
public function setContents(array $items){
if(count($items) > $this->size){
$items = array_slice($items, 0, $this->size, true);
}
parent::setContents($items);
$leftItems = array_slice($items, 0, $this->left->getSize(), true);
$this->left->setContents($leftItems);
if(count($items) > $this->left->getSize()){
$rightItems = array_slice($items, $this->left->getSize() - 1, $this->right->getSize(), true);
$this->right->setContents($rightItems);
}
}
/**
* @return ChestInventory
*/
public function getLeftSide(){
return $this->left;
}
/**
* @return ChestInventory
*/
public function getRightSide(){
return $this->right;
}
}

View File

@ -0,0 +1,92 @@
<?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/
*
*
*/
namespace pocketmine\inventory;
use pocketmine\item\Item;
use pocketmine\tile\Furnace;
class FurnaceInventory extends ContainerInventory{
public function __construct(Furnace $tile){
parent::__construct($tile, InventoryType::get(InventoryType::FURNACE));
}
/**
* @return Furnace
*/
public function getHolder(){
return $this->holder;
}
/**
* @return Item
*/
public function getResult(){
return $this->getItem(2);
}
/**
* @return Item
*/
public function getFuel(){
return $this->getItem(1);
}
/**
* @return Item
*/
public function getSmelting(){
return $this->getItem(0);
}
/**
* @param Item $item
*
* @return bool
*/
public function setResult(Item $item){
return $this->setItem(2, $item);
}
/**
* @param Item $item
*
* @return bool
*/
public function setFuel(Item $item){
return $this->setItem(1, $item);
}
/**
* @param Item $item
*
* @return bool
*/
public function setSmelting(Item $item){
return $this->setItem(0, $item);
}
public function onSlotChange($index, $before){
parent::onSlotChange($index, $before);
//TODO: implement Furnace scheduled update
}
}

View File

@ -50,6 +50,15 @@ interface Inventory{
*/
public function getItem($index);
/**
* Puts an Item in a slot.
* If a plugin refuses the update or $index is invalid, it'll return false
*
* @param int $index
* @param Item $item
*
* @return bool
*/
public function setItem($index, Item $item);
/**
@ -127,6 +136,8 @@ interface Inventory{
* Will clear a specific slot
*
* @param int $index
*
* @return bool
*/
public function clear($index);

View File

@ -26,10 +26,11 @@ namespace pocketmine\inventory;
*/
class InventoryType{
const CHEST = 0;
const PLAYER = 1;
const FURNACE = 2;
const CRAFTING = 3;
const WORKBENCH = 4;
const DOUBLE_CHEST = 1;
const PLAYER = 2;
const FURNACE = 3;
const CRAFTING = 4;
const WORKBENCH = 5;
private static $default = [];
@ -46,6 +47,7 @@ class InventoryType{
}
static::$default[static::CHEST] = new InventoryType(27, "Chest");
static::$default[static::DOUBLE_CHEST] = new InventoryType(27 + 27, "Double Chest");
static::$default[static::PLAYER] = new InventoryType(31, "Player"); //27 CONTAINER, 4 ARMOR (9 reference HOTBAR slots)
static::$default[static::FURNACE] = new InventoryType(3, "Furnace");
static::$default[static::CRAFTING] = new InventoryType(5, "Crafting"); //4 CRAFTING slots, 1 RESULT

View File

@ -22,11 +22,15 @@
namespace pocketmine\inventory;
use pocketmine\entity\Human;
use pocketmine\event\entity\EntityArmorChangeEvent;
use pocketmine\event\player\PlayerItemHeldEvent;
use pocketmine\item\Item;
use pocketmine\network\protocol\ContainerSetContentPacket;
use pocketmine\network\protocol\ContainerSetSlotPacket;
use pocketmine\network\protocol\PlayerArmorEquipmentPacket;
use pocketmine\network\protocol\PlayerEquipmentPacket;
use pocketmine\Player;
use pocketmine\Server;
class PlayerInventory extends BaseInventory{
@ -83,8 +87,13 @@ class PlayerInventory extends BaseInventory{
}
}
/**
* @param Item $item
*
* @return bool
*/
public function setItemInHand(Item $item){
$this->setItem($this->getHeldItemSlot(), $item);
return $this->setItem($this->getHeldItemSlot(), $item);
}
public function getHeldItemSlot(){
@ -93,7 +102,33 @@ class PlayerInventory extends BaseInventory{
public function setHeldItemSlot($slot){
if($slot >= 0 and $slot < $this->getSize()){
$item = $this->getItem($slot);
if($this->getHolder() instanceof Player){
Server::getInstance()->getPluginManager()->callEvent($ev = new PlayerItemHeldEvent($this->getHolder(), $item, $slot, 0));
if($ev->isCancelled()){
$this->sendHeldItem($this->getHolder());
return;
}
}
$this->setHotbarSlotIndex($this->itemInHandIndex, $slot);
$this->sendHeldItem($this->getHolder()->getViewers());
if($this->getHolder() instanceof Player){
$this->sendHeldItem($this->getHolder());
}
}
}
/**
* @param Player|Player[] $target
*/
public function sendHeldItem($target){
if($target instanceof Player){
$target = [$target];
}
$item = $this->getItemInHand();
$pk = new PlayerEquipmentPacket;
@ -102,7 +137,12 @@ class PlayerInventory extends BaseInventory{
$pk->meta = $item->getDamage();
$pk->slot = 0;
foreach($this->getHolder()->getViewers() as $player){
foreach($target as $player){
if($player === $this->getHolder()){
//TODO: Check if Mojang enabled sending a single slot this
//$this->sendSlot($this->getHeldItemSlot());
$this->sendContents($this->getHolder());
}else{
$player->dataPacket(clone $pk);
}
}
@ -112,34 +152,11 @@ class PlayerInventory extends BaseInventory{
parent::onSlotChange($index, $before);
if($index >= $this->getSize()){
$armor = $this->getArmorContents();
$slots = [];
foreach($armor as $i => $slot){
if($slot->getID() === Item::AIR){
$slots[$i] = 255;
}else{
$slots[$i] = $slot->getID();
}
$this->sendArmorContents($this->getHolder()->getViewers());
}
$pk = new PlayerArmorEquipmentPacket;
$pk->eid = $this->getHolder()->getID();
$pk->slots = $slots;
if($index >= $this->getSize()){ //Armor change
foreach($this->getHolder()->getViewers() as $player){
if($player === $this->getHolder()){
/** @var Player $player */
$pk2 = new ContainerSetContentPacket;
$pk2->windowid = 0x78; //Armor window id constant
$pk2->slots = $armor;
$player->dataPacket($pk2);
}else{
$player->dataPacket(clone $pk);
}
}
}
if($this->getHolder() instanceof Player){
$this->sendArmorContents($this->getHolder());
}
}
@ -147,6 +164,14 @@ class PlayerInventory extends BaseInventory{
return 9;
}
public function getArmorItem($index){
return $this->getItem($this->getSize() + $index);
}
public function setArmorItem($index, Item $item){
return $this->setItem($this->getSize() + $index, $item);
}
public function getHelmet(){
return $this->getItem($this->getSize() + 3);
}
@ -164,19 +189,66 @@ class PlayerInventory extends BaseInventory{
}
public function setHelmet(Item $helmet){
$this->setItem($this->getSize() + 3, $helmet);
return $this->setItem($this->getSize() + 3, $helmet);
}
public function setChestplate(Item $chestplate){
$this->setItem($this->getSize() + 2, $chestplate);
return $this->setItem($this->getSize() + 2, $chestplate);
}
public function setLeggings(Item $leggings){
$this->setItem($this->getSize() + 1, $leggings);
return $this->setItem($this->getSize() + 1, $leggings);
}
public function setBoots(Item $boots){
$this->setItem($this->getSize(), $boots);
return $this->setItem($this->getSize(), $boots);
}
public function setItem($index, Item $item){
if($index < 0 or $index >= $this->size){
return false;
}
if($index >= $this->getSize()){ //Armor change
Server::getInstance()->getPluginManager()->callEvent($ev = new EntityArmorChangeEvent($this->getHolder(), $this->getItem($index), $item, $index));
if($ev->isCancelled()){
$this->sendArmorContents($this);
$this->sendContents($this);
return false;
}
$item = $ev->getNewItem();
}
$old = $this->slots[$index];
$this->slots[$index] = clone $item;
$this->onSlotChange($index, $old);
return true;
}
public function clear($index){
if(isset($this->slots[$index])){
$item = Item::get(Item::AIR, null, 0);
$old = $this->slots[$index];
if($index >= $this->getSize() and $index < $this->size){ //Armor change
Server::getInstance()->getPluginManager()->callEvent($ev = new EntityArmorChangeEvent($this->getHolder(), $old, $item, $index));
if($ev->isCancelled()){
$this->sendArmorContents($this);
$this->sendContents($this);
return;
}
$item = $ev->getNewItem();
}
if($item->getID() !== Item::AIR){
$this->slots[$index] = clone $item;
}else{
unset($this->slots[$index]);
}
$this->onSlotChange($index, $old);
}
}
/**
@ -192,6 +264,41 @@ class PlayerInventory extends BaseInventory{
return $armor;
}
/**
* @param Player|Player[] $target
*/
public function sendArmorContents($target){
if($target instanceof Player){
$target = [$target];
}
$armor = $this->getArmorContents();
$slots = [];
foreach($armor as $i => $slot){
if($slot->getID() === Item::AIR){
$slots[$i] = 255;
}else{
$slots[$i] = $slot->getID();
}
}
$pk = new PlayerArmorEquipmentPacket;
$pk->eid = $this->getHolder()->getID();
$pk->slots = $slots;
foreach($target as $player){
if($player === $this->getHolder()){
/** @var Player $player */
$pk2 = new ContainerSetContentPacket;
$pk2->windowid = 0x78; //Armor window id constant
$pk2->slots = $armor;
$player->dataPacket($pk2);
}else{
$player->dataPacket(clone $pk);
}
}
}
/**
* @param Item[] $items
*/
@ -209,6 +316,62 @@ class PlayerInventory extends BaseInventory{
}
}
/**
* @param Player|Player[] $target
*/
public function sendContents($target){
if($target instanceof Player){
$target = [$target];
}
$holder = $this->getHolder();
if($holder instanceof Player and ($holder->getGamemode() & 0x01) === 1){
return;
}
$pk = new ContainerSetContentPacket();
$pk->slots = [];
for($i = 0; $i < $this->getSize(); ++$i){ //Do not send armor by error here
$pk->slots[$i] = $this->getItem($i);
}
foreach($target as $player){
$pk->hotbar = [];
if($player === $this->getHolder()){
for($i = 0; $i < $this->getHotbarSize(); ++$i){
$index = $this->getHotbarSlotIndex($i);
$pk->hotbar[] = $index <= -1 ? -1 : $index + 9;
}
}
$pk->windowid = $player->getWindowId($this);
$player->dataPacket(clone $pk);
}
}
/**
* @param int $index
* @param Player|Player[] $target
*/
public function sendSlot($index, $target){
if($target instanceof Player){
$target = [$target];
}
$pk = new ContainerSetSlotPacket;
$pk->slot = $index;
$pk->item = clone $this->getItem($index);
foreach($target as $player){
if($player === $this->getHolder()){
//TODO: Check if Mojang has implemented this (for the player inventory) on Minecraft: PE 0.9.0
$this->sendContents($player);
}else{
$pk->windowid = $player->getWindowId($this);
$player->dataPacket(clone $pk);
}
}
}
/**
* @return Human
*/

View File

@ -31,6 +31,7 @@ use pocketmine\event\block\BlockBreakEvent;
use pocketmine\event\block\BlockPlaceEvent;
use pocketmine\event\player\PlayerInteractEvent;
use pocketmine\item\Item;
use pocketmine\level\format\pmf\LevelFormat;
use pocketmine\level\generator\Generator;
use pocketmine\math\Vector2;
use pocketmine\math\Vector3 as Vector3;
@ -42,7 +43,6 @@ use pocketmine\nbt\tag\String;
use pocketmine\network\protocol\SetTimePacket;
use pocketmine\network\protocol\UpdateBlockPacket;
use pocketmine\Player;
use pocketmine\level\format\pmf\LevelFormat;
use pocketmine\Server;
use pocketmine\tile\Chest;
use pocketmine\tile\Furnace;

View File

@ -21,9 +21,9 @@
namespace pocketmine\level;
use pocketmine\level\format\pmf\LevelFormat;
use pocketmine\level\format\PocketChunkParser;
use pocketmine\nbt\NBT;
use pocketmine\level\format\pmf\LevelFormat;
use pocketmine\utils\Config;
class LevelImport{

View File

@ -106,6 +106,7 @@ class Position extends Vector3{
if(!$this->isValid()){
throw new \RuntimeException("Undefined Level reference");
}
return Position::fromObject(parent::getSide($side, $step), $this->getLevel());
}

View File

@ -21,8 +21,8 @@
namespace pocketmine\level;
use pocketmine\level\generator\Generator;
use pocketmine\level\format\pmf\LevelFormat;
use pocketmine\level\generator\Generator;
use pocketmine\Server;
use pocketmine\utils\Binary;
use pocketmine\utils\Random;

View File

@ -20,8 +20,9 @@
*/
namespace pocketmine\level\format;
use pocketmine\Server;
use pocketmine\math\Vector3;
use pocketmine\Server;
/**
* All Level formats must implement this interface

View File

@ -22,7 +22,6 @@
namespace pocketmine\level\format;
use pocketmine\utils\Binary;
use pocketmine\utils\Utils;
/**
* WARNING: This code is old, and only supports the file format partially (reverse engineering)

View File

@ -138,6 +138,7 @@ class ChunkSection implements \pocketmine\level\format\ChunkSection{
for($y = 15; $y >= 0; --$y){
$column{15 - $y} = $this->blocks{($y << 8) + $i};
}
return $column;
}
@ -147,6 +148,7 @@ class ChunkSection implements \pocketmine\level\format\ChunkSection{
for($y = 7; $y >= 0; --$y){
$column{7 - $y} = $this->data{($y << 7) + $i};
}
return $column;
}

View File

@ -21,7 +21,6 @@
namespace pocketmine\level\format\anvil;
use pocketmine\level\Level;
use pocketmine\nbt\NBT;
use pocketmine\nbt\tag\Byte;
use pocketmine\nbt\tag\ByteArray;
@ -45,10 +44,12 @@ class RegionLoader{
protected $lastSector;
protected $locationTable = [];
public function __construct($path,/*Level $level, */$regionX, $regionZ){
public function __construct($path, /*Level $level, */
$regionX, $regionZ){
$this->x = $regionX;
$this->z = $regionZ;
$this->filePath = /*$level->getPath()*/$path . "region/r.$regionX.$regionZ.mca";
$this->filePath = /*$level->getPath()*/
$path . "region/r.$regionX.$regionZ.mca";
touch($this->filePath);
$this->filePointer = fopen($this->filePath, "r+b");
flock($this->filePointer, LOCK_EX);
@ -103,6 +104,7 @@ class RegionLoader{
$this->writeLocationIndex($index);
}elseif($compression !== self::COMPRESSION_ZLIB and $compression !== self::COMPRESSION_GZIP){
trigger_error("Invalid compression type", E_USER_WARNING);
return false;
}
@ -113,6 +115,7 @@ class RegionLoader{
if(!$chunk instanceof Compound){
return false;
}
return $chunk;
//$chunk = new Chunk($level, $chunk);
}
@ -183,6 +186,7 @@ class RegionLoader{
$this->writeLocationTable();
$n = $this->cleanGarbage();
$this->writeLocationTable();
return $n;
}

View File

@ -20,6 +20,7 @@
*/
namespace pocketmine\level\format\generic;
use pocketmine\level\format\Chunk;
use pocketmine\level\format\ChunkSection;
use pocketmine\level\Level;
@ -48,11 +49,13 @@ abstract class BaseChunk implements Chunk{
$this->sections[$Y] = $section;
}else{
trigger_error("Received invalid ChunkSection instance", E_USER_ERROR);
return;
}
if($section >= self::SECTION_COUNT){
trigger_error("Invalid amount of chunks", E_USER_WARNING);
return;
}
}

View File

@ -20,6 +20,7 @@
*/
namespace pocketmine\level\format\generic;
use pocketmine\level\format\ChunkSection;
/**

View File

@ -32,6 +32,7 @@ class ChunkSection implements \pocketmine\level\format\ChunkSection{
if($section !== null){
if(strlen($section) !== 8192){
trigger_error("Invalid ChunkSection generated", E_USER_WARNING);
return;
}
$this->section = $section;

View File

@ -26,7 +26,6 @@ use pocketmine\nbt\NBT;
use pocketmine\nbt\tag\Compound;
use pocketmine\nbt\tag\Enum;
use pocketmine\utils\Binary;
use pocketmine\utils\Utils;
class LevelFormat extends PMF{
const VERSION = 2;

View File

@ -41,6 +41,7 @@ abstract class MetadataStore{
$owningPlugin = $newMetadataValue->getOwningPlugin();
if($owningPlugin === null){
trigger_error("Plugin cannot be null", E_USER_WARNING);
return;
}

View File

@ -39,7 +39,6 @@ use pocketmine\nbt\tag\Short;
use pocketmine\nbt\tag\String;
use pocketmine\nbt\tag\Tag;
use pocketmine\utils\Binary;
use pocketmine\utils\Utils;
/**
* Named Binary Tag encoder/decoder

View File

@ -22,7 +22,6 @@
namespace pocketmine\network\protocol;
use pocketmine\utils\Binary;
use pocketmine\utils\Utils;
class AddMobPacket extends DataPacket{
public $eid;

View File

@ -22,7 +22,6 @@
namespace pocketmine\network\protocol;
use pocketmine\utils\Binary;
use pocketmine\utils\Utils;
class AddPlayerPacket extends DataPacket{
public $clientID;

View File

@ -23,7 +23,6 @@ namespace pocketmine\network\protocol;
use pocketmine\item\Item;
use pocketmine\utils\Binary;
use pocketmine\utils\Utils;
abstract class DataPacket extends \stdClass{
private $offset = 0;

View File

@ -22,7 +22,6 @@
namespace pocketmine\network\protocol;
use pocketmine\utils\Binary;
use pocketmine\utils\Utils;
class SetEntityDataPacket extends DataPacket{
public $eid;

View File

@ -23,7 +23,6 @@ namespace pocketmine\network\query;
use pocketmine\network\Packet;
use pocketmine\utils\Binary;
use pocketmine\utils\Utils;
class QueryPacket extends Packet{
const HANDSHAKE = 9;

View File

@ -79,7 +79,6 @@ use pocketmine\network\protocol\UnknownPacket;
use pocketmine\network\protocol\UpdateBlockPacket;
use pocketmine\network\protocol\UseItemPacket;
use pocketmine\utils\Binary;
use pocketmine\utils\Utils;
class Packet extends NetworkPacket{
private $packetID;

View File

@ -22,7 +22,6 @@
namespace pocketmine\network\rcon;
use pocketmine\utils\Binary;
use pocketmine\utils\Utils;
class RCONInstance extends \Thread{
public $stop;

View File

@ -23,6 +23,7 @@
* Plugin related classes
*/
namespace pocketmine\plugin;
use pocketmine\command\CommandExecutor;

View File

@ -148,6 +148,7 @@ class PluginManager{
if(count($pluginCommands) > 0){
$this->commandMap->registerAll($plugin->getDescription()->getName(), $pluginCommands);
}
return $plugin;
}
}

View File

@ -54,6 +54,7 @@ abstract class AsyncTask extends \Threaded{
public function getResult(){
return $this->synchronized(function (){
$this->finished = true;
return @unserialize($this->result);
});
}

View File

@ -26,6 +26,7 @@ class AsyncWorker extends \Worker{
public function start($options = PTHREADS_INHERIT_CLASSES){
$this->path = \pocketmine\PATH;
return parent::start($options & ~PTHREADS_INHERIT_CLASSES);
}

View File

@ -208,8 +208,10 @@ class ServerScheduler{
$this->asyncPool->collect(function (AsyncTask $task){
if($task->isCompleted() or ($task->isFinished() and !$task->hasResult())){
--$this->asyncTasks;
return true;
}
return false;
});
}

View File

@ -21,23 +21,134 @@
namespace pocketmine\tile;
use pocketmine\inventory\ChestInventory;
use pocketmine\inventory\DoubleChestInventory;
use pocketmine\inventory\InventoryHolder;
use pocketmine\item\Item;
use pocketmine\level\Level;
use pocketmine\math\Vector3 as Vector3;
use pocketmine\nbt\NBT;
use pocketmine\nbt\tag\Byte;
use pocketmine\nbt\tag\Compound;
use pocketmine\nbt\tag\Int;
use pocketmine\nbt\tag\Short;
use pocketmine\nbt\tag\String;
use pocketmine\network\protocol\EntityDataPacket;
use pocketmine\Player;
class Chest extends Spawnable{
use Container;
class Chest extends Spawnable implements InventoryHolder, Container{
const SLOTS = 27;
/** @var ChestInventory */
protected $inventory;
/** @var DoubleChestInventory */
protected $doubleInventory = null;
public function __construct(Level $level, Compound $nbt){
$nbt["id"] = Tile::CHEST;
parent::__construct($level, $nbt);
$this->inventory = new ChestInventory($this);
for($i = 0; $i < $this->getSize(); ++$i){
$this->inventory->setItem($i, $this->getItem($i));
}
$this->checkPairing();
}
/**
* @return int
*/
public function getSize(){
return 27;
}
/**
* @param $index
*
* @return int
*/
protected function getSlotIndex($index){
foreach($this->namedtag->Items as $i => $slot){
if($slot["Slot"] === $s){
return $i;
}
}
return -1;
}
/**
* This method should not be used by plugins, use the Inventory
*
* @param int $index
*
* @return Item
*/
public function getItem($index){
$i = $this->getSlotIndex($index);
if($i < 0){
return Item::get(Item::AIR, 0, 0);
}else{
return Item::get($this->namedtag->Items[$i]["id"], $this->namedtag->Items[$i]["Damage"], $this->namedtag->Items[$i]["Count"]);
}
}
/**
* This method should not be used by plugins, use the Inventory
*
* @param int $index
* @param Item $item
*
* @return bool
*/
public function setItem($index, Item $item){
$i = $this->getSlotIndex($index);
if($i < 0){
return false;
}
$d = new Compound(false, array(
new Byte("Count", $item->getCount()),
new Byte("Slot", $index),
new Short("id", $item->getID()),
new Short("Damage", $item->getDamage()),
));
if($item->getID() === Item::AIR or $item->getCount() <= 0){
if($i >= 0){
unset($this->namedtag->Items[$i]);
}
}elseif($i < 0){
$this->namedtag->Items[] = $d;
}else{
$this->namedtag->Items[$i] = $d;
}
return true;
}
/**
* @return ChestInventory|DoubleChestInventory
*/
public function getInventory(){
return $this->doubleInventory instanceof DoubleChestInventory ? $this->doubleInventory : $this->inventory;
}
/**
* @return ChestInventory
*/
public function getRealInventory(){
return $this->inventory;
}
protected function checkPairing(){
if(($pair = $this->getPair()) instanceof Chest){
if(($pair->x + ($pair->z << 15)) > ($this->x + ($this->z << 15))){ //Order them correctly
$this->doubleInventory = new DoubleChestInventory($pair, $this);
}else{
$this->doubleInventory = new DoubleChestInventory($this, $pair);
}
}else{
$this->doubleInventory = null;
}
}
public function isPaired(){
@ -48,12 +159,18 @@ class Chest extends Spawnable{
return true;
}
/**
* @return Chest
*/
public function getPair(){
if($this->isPaired()){
return $this->getLevel()->getTile(new Vector3((int) $this->namedtag->pairx, $this->y, (int) $this->namedtag->pairz));
$tile = $this->getLevel()->getTile(new Vector3((int) $this->namedtag->pairx, $this->y, (int) $this->namedtag->pairz));
if($tile instanceof Chest){
return $tile;
}
}
return false;
return null;
}
public function pairWith(Chest $tile){
@ -69,10 +186,11 @@ class Chest extends Spawnable{
$this->spawnToAll();
$tile->spawnToAll();
$this->checkPairing();
//TODO: Update to new events
$this->server->handle("tile.update", $this);
$this->server->handle("tile.update", $tile);
//$this->server->handle("tile.update", $this);
//$this->server->handle("tile.update", $tile);
return true;
}
@ -86,10 +204,12 @@ class Chest extends Spawnable{
unset($this->namedtag->pairx, $this->namedtag->pairz, $tile->namedtag->pairx, $tile->namedtag->pairz);
$this->spawnToAll();
$this->server->handle("tile.update", $this);
$this->checkPairing();
//TODO: tile update event
//$this->server->handle("tile.update", $this);
if($tile instanceof Chest){
$tile->spawnToAll();
$this->server->handle("tile.update", $tile);
//$this->server->handle("tile.update", $tile);
}
return true;

View File

@ -23,178 +23,12 @@ namespace pocketmine\tile;
use pocketmine\event\tile\TileInventoryChangeEvent;
use pocketmine\item\Item;
use pocketmine\nbt\tag\Byte;
use pocketmine\nbt\tag\Compound;
use pocketmine\nbt\tag\Short;
use pocketmine\Network;
use pocketmine\network\protocol\ContainerOpenPacket;
use pocketmine\network\protocol\ContainerSetContentPacket;
use pocketmine\network\protocol\TileEventPacket;
use pocketmine\Player;
use pocketmine\Server;
trait Container{
public function openInventory(Player $player){
if($this instanceof 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;
}
interface Container{
public function getItem($index);
$pk = new ContainerOpenPacket();
$pk->windowid = $id;
$pk->type = 0;
$pk->slots = is_array($player->windows[$id]) ? Chest::SLOTS << 1 : Chest::SLOTS;
$pk->x = $this->x;
$pk->y = $this->y;
$pk->z = $this->z;
$player->dataPacket($pk);
$slots = [];
public function setItem($index, Item $item);
if(is_array($player->windows[$id])){
$all = $this->getLevel()->getPlayers();
foreach($player->windows[$id] as $ob){
$pk = new TileEventPacket();
$pk->x = $ob->x;
$pk->y = $ob->y;
$pk->z = $ob->z;
$pk->case1 = 1;
$pk->case2 = 2;
Player::broadcastPacket($all, $pk);
for($s = 0; $s < Chest::SLOTS; ++$s){
$slot = $ob->getSlot($s);
if($slot->getID() > Item::AIR and $slot->getCount() > 0){
$slots[] = $slot;
}else{
$slots[] = Item::get(Item::AIR, 0, 0);
}
}
}
}else{
$pk = new TileEventPacket();
$pk->x = $this->x;
$pk->y = $this->y;
$pk->z = $this->z;
$pk->case1 = 1;
$pk->case2 = 2;
Player::broadcastPacket($this->getLevel()->getPlayers(), $pk);
for($s = 0; $s < Chest::SLOTS; ++$s){
$slot = $this->getSlot($s);
if($slot->getID() > Item::AIR and $slot->getCount() > 0){
$slots[] = $slot;
}else{
$slots[] = Item::get(Item::AIR, 0, 0);
}
}
}
$pk = new ContainerSetContentPacket();
$pk->windowid = $id;
$pk->slots = $slots;
$player->dataPacket($pk);
return true;
}elseif($this instanceof Furnace){
$player->windowCnt++;
$player->windowCnt = $id = max(2, $player->windowCnt % 99);
$player->windows[$id] = $this;
$pk = new ContainerOpenPacket();
$pk->windowid = $id;
$pk->type = 2;
$pk->slots = Furnace::SLOTS;
$pk->x = $this->x;
$pk->y = $this->y;
$pk->z = $this->z;
$player->dataPacket($pk);
$slots = [];
for($s = 0; $s < Furnace::SLOTS; ++$s){
$slot = $this->getSlot($s);
if($slot->getID() > Item::AIR and $slot->getCount() > 0){
$slots[] = $slot;
}else{
$slots[] = Item::get(Item::AIR, 0, 0);
}
}
$pk = new ContainerSetContentPacket();
$pk->windowid = $id;
$pk->slots = $slots;
$player->dataPacket($pk);
return true;
}
}
public function getSlotIndex($s){
foreach($this->namedtag->Items as $i => $slot){
if($slot["Slot"] === $s){
return $i;
}
}
return -1;
}
/**
* @param int $s
*
* @return Item
*/
public function getSlot($s){
$i = $this->getSlotIndex($s);
if($i === false or $i < 0){
return Item::get(Item::AIR, 0, 0);
}else{
return Item::get($this->namedtag->Items[$i]["id"], $this->namedtag->Items[$i]["Damage"], $this->namedtag->Items[$i]["Count"]);
}
}
public function setSlot($s, Item $item, $update = true, $offset = 0){
$i = $this->getSlotIndex($s);
if($i === false){
return false;
}
Server::getInstance()->getPluginManager()->callEvent($ev = new TileInventoryChangeEvent($this, $this->getSlot($s), $item, $s, $offset));
if($ev->isCancelled()){
return false;
}
$item = $ev->getNewItem();
$d = new Compound(false, array(
new Byte("Count", $item->getCount()),
new Byte("Slot", $s),
new Short("id", $item->getID()),
new Short("Damage", $item->getDamage()),
));
if($item->getID() === Item::AIR or $item->getCount() <= 0){
if($i >= 0){
unset($this->namedtag->Items[$i]);
}
}elseif($i < 0){
$this->namedtag->Items[] = $d;
}else{
$this->namedtag->Items[$i] = $d;
}
if($update === true){
$this->scheduleUpdate();
}
return true;
}
public function getSize();
}

View File

@ -22,18 +22,26 @@
namespace pocketmine\tile;
use pocketmine\block\Block;
use pocketmine\inventory\FurnaceInventory;
use pocketmine\inventory\InventoryHolder;
use pocketmine\item\Item;
use pocketmine\level\Level;
use pocketmine\nbt\tag\Byte;
use pocketmine\nbt\tag\Compound;
use pocketmine\nbt\tag\Short;
class Furnace extends Tile{
use Container;
const SLOTS = 3;
class Furnace extends Tile implements InventoryHolder, Container{
/** @var FurnaceInventory */
protected $inventory;
public function __construct(Level $level, Compound $nbt){
$nbt["id"] = Tile::FURNACE;
parent::__construct($level, $nbt);
$this->inventory = new FurnaceInventory($this);
for($i = 0; $i < $this->getSize(); ++$i){
$this->inventory->setItem($i, $this->getItem($i));
}
if(!isset($this->namedtag->BurnTime) or $this->namedtag->BurnTime < 0){
$this->namedtag->BurnTime = 0;
}
@ -49,6 +57,85 @@ class Furnace extends Tile{
}
}
/**
* @return int
*/
public function getSize(){
return 3;
}
/**
* @param $index
*
* @return int
*/
protected function getSlotIndex($index){
foreach($this->namedtag->Items as $i => $slot){
if($slot["Slot"] === $s){
return $i;
}
}
return -1;
}
/**
* This method should not be used by plugins, use the Inventory
*
* @param int $index
*
* @return Item
*/
public function getItem($index){
$i = $this->getSlotIndex($index);
if($i < 0){
return Item::get(Item::AIR, 0, 0);
}else{
return Item::get($this->namedtag->Items[$i]["id"], $this->namedtag->Items[$i]["Damage"], $this->namedtag->Items[$i]["Count"]);
}
}
/**
* This method should not be used by plugins, use the Inventory
*
* @param int $index
* @param Item $item
*
* @return bool
*/
public function setItem($index, Item $item){
$i = $this->getSlotIndex($index);
if($i < 0){
return false;
}
$d = new Compound(false, array(
new Byte("Count", $item->getCount()),
new Byte("Slot", $index),
new Short("id", $item->getID()),
new Short("Damage", $item->getDamage()),
));
if($item->getID() === Item::AIR or $item->getCount() <= 0){
if($i >= 0){
unset($this->namedtag->Items[$i]);
}
}elseif($i < 0){
$this->namedtag->Items[] = $d;
}else{
$this->namedtag->Items[$i] = $d;
}
return true;
}
/**
* @return FurnaceInventory
*/
public function getInventory(){
return $this->inventory;
}
public function onUpdate(){
if($this->closed === true){
return false;
@ -56,9 +143,9 @@ class Furnace extends Tile{
$ret = false;
$fuel = $this->getSlot(1);
$raw = $this->getSlot(0);
$product = $this->getSlot(2);
$fuel = $this->inventory->getFuel();
$raw = $this->inventory->getSmelting();
$product = $this->inventory->getResult();
$smelt = $raw->getSmeltItem();
$canSmelt = ($smelt !== false and $raw->getCount() > 0 and (($product->getID() === $smelt->getID() and $product->getDamage() === $smelt->getDamage() and $product->getCount() < $product->getMaxStackSize()) or $product->getID() === Item::AIR));
if($this->namedtag->BurnTime <= 0 and $canSmelt and $fuel->getFuelTime() !== false and $fuel->getCount() > 0){
@ -69,7 +156,7 @@ class Furnace extends Tile{
if($fuel->getCount() === 0){
$fuel = Item::get(Item::AIR, 0, 0);
}
$this->setSlot(1, $fuel, false);
$this->inventory->setFuel($fuel);
$current = $this->getLevel()->getBlock($this);
if($current->getID() === Item::FURNACE){
$this->getLevel()->setBlock($this, Block::get(Item::BURNING_FURNACE, $current->getDamage()), true, false, true);
@ -83,12 +170,12 @@ class Furnace extends Tile{
$this->namedtag->CookTime += $ticks;
if($this->namedtag->CookTime >= 200){ //10 seconds
$product = Item::get($smelt->getID(), $smelt->getDamage(), $product->getCount() + 1);
$this->setSlot(2, $product, false);
$this->inventory->setResult($product);
$raw->setCount($raw->getCount() - 1);
if($raw->getCount() === 0){
$raw = Item::get(Item::AIR, 0, 0);
}
$this->setSlot(0, $raw, false);
$this->inventory->setSmelting($raw);
$this->namedtag->CookTime -= 200;
}
}elseif($this->namedtag->BurnTime <= 0){
@ -109,8 +196,8 @@ class Furnace extends Tile{
$this->namedtag->BurnTicks = 0;
}
$this->server->handle("tile.update", $this);
//TODO: tile update event
//$this->server->handle("tile.update", $this);
$this->lastUpdate = microtime(true);
return $ret;

View File

@ -28,7 +28,7 @@ abstract class Spawnable extends Tile{
public function spawnToAll(){
foreach($this->getLevel()->getPlayers() as $player){
if($player->eid !== false or $player->spawned !== true){
if($player->spawned === true){
$this->spawnTo($player);
}
}

View File

@ -25,10 +25,10 @@
*/
namespace pocketmine\tile;
use pocketmine\level\format\pmf\LevelFormat;
use pocketmine\level\Level;
use pocketmine\level\Position;
use pocketmine\nbt\tag\Compound;
use pocketmine\level\format\pmf\LevelFormat;
use pocketmine\Server;
abstract class Tile extends Position{
@ -36,6 +36,8 @@ abstract class Tile extends Position{
const CHEST = "Chest";
const FURNACE = "Furnace";
//TODO: pre-close step NBT data saving method
public static $tileCount = 1;
/**
@ -89,8 +91,8 @@ abstract class Tile extends Position{
$index = LevelFormat::getIndex($this->x >> 4, $this->z >> 4);
$this->chunkIndex = $index;
$this->level->tiles[$this->id] = $this;
$this->level->chunkTiles[$this->chunkIndex][$this->id] = $this;
$this->getLevel()->tiles[$this->id] = $this;
$this->getLevel()->chunkTiles[$this->chunkIndex][$this->id] = $this;
}
public function onUpdate(){
@ -105,8 +107,8 @@ abstract class Tile extends Position{
if($this->closed === false){
$this->closed = true;
unset(Tile::$needUpdate[$this->id]);
unset($this->level->tiles[$this->id]);
unset($this->level->chunkTiles[$this->chunkIndex][$this->id]);
unset($this->getLevel()->tiles[$this->id]);
unset($this->getLevel()->chunkTiles[$this->chunkIndex][$this->id]);
unset(Tile::$list[$this->id]);
}
}

View File

@ -171,6 +171,7 @@ class Binary{
return $m;
}
/**
* Reads a byte boolean
*

View File

@ -262,6 +262,7 @@ class Config{
$currPath = null;
}
}
return $currPath;
}

View File

@ -69,6 +69,7 @@ class Random{
if($t > 2147483647){
$t -= 4294967296;
}
return (int) $t;
}

View File

@ -274,6 +274,7 @@ class TextFormat{
break;
}
}
return $newString;
}

View File

@ -24,8 +24,6 @@
*/
namespace pocketmine\utils;
use pocketmine\item\Item;
/**
* Big collection of functions
*/