mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-05-16 18:59:00 +00:00
Implemented new Inventory windows on Player, Chest and Furnace
This commit is contained in:
parent
27e82ea60a
commit
53749483c3
@ -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);
|
||||
}
|
||||
}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);
|
||||
}
|
||||
if(isset($this->windowIndex[$packet->windowid])){
|
||||
$this->removeWindow($this->windowIndex[$packet->windowid]);
|
||||
}else{
|
||||
unset($this->windowIndex[$packet->windowid]);
|
||||
}
|
||||
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{
|
||||
break;
|
||||
}
|
||||
$item = Item::get($packet->item->getID(), $packet->item->getDamage(), $packet->item->getCount());
|
||||
$inv = $this->windowIndex[$packet->windowid];
|
||||
if($packet->slot < 0 or $packet->slot >= $inv->getSize()){
|
||||
break;
|
||||
}
|
||||
|
||||
$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()){
|
||||
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->getCount() - $item->getCount());
|
||||
$this->addItem($it);
|
||||
/** @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());
|
||||
$remaining = $this->inventory->removeItem($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;
|
||||
}elseif($slot->getCount() > $item->getCount()){
|
||||
$it = clone $item;
|
||||
$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());
|
||||
}
|
||||
$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;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}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;
|
||||
}
|
||||
$tile->setSlot($packet->slot, $item);
|
||||
$this->inventory->addItem($slot);
|
||||
}
|
||||
$inv->setItem($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();
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
$slot = $this->inventory[$s];
|
||||
$pk = new ContainerSetSlotPacket;
|
||||
$pk->windowid = 0;
|
||||
$pk->slot = (int) $s;
|
||||
$pk->item = $slot;
|
||||
$this->dataPacket($pk);
|
||||
|
||||
return true;
|
||||
return $cnt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the full inventory
|
||||
*/
|
||||
public function sendInventory(){
|
||||
if(($this->gamemode & 0x01) === 1){
|
||||
return;
|
||||
public function removeWindow(Inventory $inventory){
|
||||
$inventory->onClose($this);
|
||||
if($this->windows->contains($inventory)){
|
||||
$inventory->onClose($this);
|
||||
$id = $this->windows[$inventory];
|
||||
unset($this->windowIndex[$id]);
|
||||
}
|
||||
$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){
|
||||
|
@ -89,7 +89,7 @@ namespace pocketmine {
|
||||
const PHP_VERSION = "5.5";
|
||||
|
||||
if(\Phar::running(true) !== ""){
|
||||
@define("pocketmine\\PATH", \Phar::running(true)."/");
|
||||
@define("pocketmine\\PATH", \Phar::running(true) . "/");
|
||||
}else{
|
||||
@define("pocketmine\\PATH", \getcwd() . DIRECTORY_SEPARATOR);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
@ -1830,7 +1830,7 @@ class Server{
|
||||
}
|
||||
|
||||
$this->lastSendUsage = new SendUsageTask("http://stats.pocketmine.net/usage.php", array(
|
||||
"serverid" => Binary::readLong(substr(Utils::getUniqueID(true, $this->getIp() .":". $this->getPort()), 0, 8)),
|
||||
"serverid" => Binary::readLong(substr(Utils::getUniqueID(true, $this->getIp() . ":" . $this->getPort()), 0, 8)),
|
||||
"port" => $this->getPort(),
|
||||
"os" => Utils::getOS(),
|
||||
"memory_total" => $this->getConfigString("memory-limit"),
|
||||
|
@ -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){
|
||||
|
@ -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;
|
||||
@ -753,11 +752,11 @@ abstract class Block extends Position implements Metadatable{
|
||||
}
|
||||
|
||||
public function getMetadata($metadataKey){
|
||||
return null;//return $this->server->getPlayerMetadata()->getMetadata($this, $metadataKey);
|
||||
return null; //return $this->server->getPlayerMetadata()->getMetadata($this, $metadataKey);
|
||||
}
|
||||
|
||||
public function hasMetadata($metadataKey){
|
||||
return false;//return $this->server->getPlayerMetadata()->hasMetadata($this, $metadataKey);
|
||||
return false; //return $this->server->getPlayerMetadata()->hasMetadata($this, $metadataKey);
|
||||
}
|
||||
|
||||
public function removeMetadata($metadataKey, Plugin $plugin){
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -301,7 +301,7 @@ abstract class Command{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
|
@ -28,7 +28,7 @@ class RemoteConsoleCommandSender extends ConsoleCommandSender{
|
||||
private $messages = "";
|
||||
|
||||
public function sendMessage($message){
|
||||
$this->messages .= trim($message, "\r\n")."\n";
|
||||
$this->messages .= trim($message, "\r\n") . "\n";
|
||||
}
|
||||
|
||||
public function getMessage(){
|
||||
|
@ -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{
|
||||
|
@ -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{
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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,19 +50,22 @@ 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){
|
||||
$level = Server::getInstance()->getDefaultLevel();
|
||||
$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);
|
||||
$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);
|
||||
Command::broadcastCommandMessage($sender, "Set world " . $level->getName() . "'s spawnpoint to " . $pos->x . ", " . $pos->y . ", " . $pos->z);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -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]);
|
||||
$sender->sendMessage(TextFormat::RED . "Can't find player " . $args[0]);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -69,22 +71,26 @@ class SpawnpointCommand extends VanillaCommand{
|
||||
$y = (int) $this->getRelativeDouble($sender->y, $sender, $args[2], 0, 128);
|
||||
$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);
|
||||
Command::broadcastCommandMessage($sender, "Set " . $target->getName() . "'s spawnpoint to " . $x . ", " . $y . ", " . $z);
|
||||
|
||||
return true;
|
||||
}
|
||||
}elseif(count($args) <= 1){
|
||||
if($sender instanceof Player) {
|
||||
if($sender instanceof Player){
|
||||
$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);
|
||||
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);
|
||||
$sender->sendMessage(TextFormat::RED . "Usage: " . $this->usageMessage);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,6 @@
|
||||
namespace pocketmine\command\defaults;
|
||||
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\Server;
|
||||
use pocketmine\utils\TextFormat;
|
||||
|
||||
@ -43,11 +42,12 @@ class StatusCommand extends VanillaCommand{
|
||||
}
|
||||
|
||||
$server = Server::getInstance();
|
||||
$sender->sendMessage(TextFormat::GREEN . "---- ".TextFormat::WHITE . "Server status".TextFormat::GREEN. " ----");
|
||||
$sender->sendMessage(TextFormat::GOLD . "TPS: ".TextFormat::WHITE.$server->getTicksPerSecond());
|
||||
$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");
|
||||
$sender->sendMessage(TextFormat::GREEN . "---- " . TextFormat::WHITE . "Server status" . TextFormat::GREEN . " ----");
|
||||
$sender->sendMessage(TextFormat::GOLD . "TPS: " . TextFormat::WHITE . $server->getTicksPerSecond());
|
||||
$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;
|
||||
}
|
||||
}
|
@ -46,7 +46,8 @@ class TeleportCommand extends VanillaCommand{
|
||||
}
|
||||
|
||||
if(count($args) < 1 or count($args) > 4){
|
||||
$sender->sendMessage(TextFormat::RED . "Usage: ".$this->usageMessage);
|
||||
$sender->sendMessage(TextFormat::RED . "Usage: " . $this->usageMessage);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -58,19 +59,22 @@ 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]);
|
||||
$sender->sendMessage(TextFormat::RED . "Can't find player " . $args[0]);
|
||||
|
||||
return true;
|
||||
}
|
||||
if(count($args) === 2){
|
||||
$origin = $target;
|
||||
$target = Server::getInstance()->getPlayer($args[1]);
|
||||
if($target === null){
|
||||
$sender->sendMessage(TextFormat::RED . "Can't find player ".$args[1]);
|
||||
$sender->sendMessage(TextFormat::RED . "Can't find player " . $args[1]);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -79,19 +83,22 @@ class TeleportCommand extends VanillaCommand{
|
||||
if(count($args) < 3){
|
||||
$pos = new Position($target->x, $target->y, $target->z, $target->getLevel());
|
||||
$origin->teleport($pos);
|
||||
Command::broadcastCommandMessage($sender, "Teleported ".$origin->getName()." to ".$target->getName());
|
||||
Command::broadcastCommandMessage($sender, "Teleported " . $origin->getName() . " to " . $target->getName());
|
||||
|
||||
return true;
|
||||
}elseif($target->getLevel() !== null){
|
||||
$pos = count($args) === 4 ? 1:0;
|
||||
$pos = count($args) === 4 ? 1 : 0;
|
||||
$x = $this->getRelativeDouble($target->x, $sender, $args[$pos++]);
|
||||
$y = $this->getRelativeDouble($target->y, $sender, $args[$pos++], 0, 128);
|
||||
$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));
|
||||
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);
|
||||
$sender->sendMessage(TextFormat::RED . "Usage: " . $this->usageMessage);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -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){
|
||||
@ -17,20 +16,22 @@ class TimeCommand extends VanillaCommand{
|
||||
);
|
||||
$this->setPermission("pocketmine.command.time.add;pocketmine.command.set;");
|
||||
}
|
||||
|
||||
|
||||
public function execute(CommandSender $sender, $label, array $args){
|
||||
if (count($args) < 2) {
|
||||
$sender->sendMessage(TextFormat::RED."Incorrect usage. Correct usage:\n".$this->getUsage());
|
||||
if(count($args) < 2){
|
||||
$sender->sendMessage(TextFormat::RED . "Incorrect usage. Correct usage:\n" . $this->getUsage());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
switch(strtolower($args[0])){
|
||||
case "set":
|
||||
if(!$sender->hasPermission("pocketmine.command.time.add")){
|
||||
$sender->sendMessage(TextFormat::RED."You don't have permission to set the time");
|
||||
$sender->sendMessage(TextFormat::RED . "You don't have permission to set the time");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
if($args[1] === "day"){
|
||||
$value = 0;
|
||||
}elseif($args[1] === "night"){
|
||||
@ -38,30 +39,31 @@ class TimeCommand extends VanillaCommand{
|
||||
}else{
|
||||
$value = $this->getInteger($sender, $args[1], 0);
|
||||
}
|
||||
|
||||
|
||||
foreach(Server::getInstance()->getLevels() as $level){
|
||||
$level->setTime($value);
|
||||
}
|
||||
Command::broadcastCommandMessage($sender, "Set time to ".$value);
|
||||
|
||||
return true;
|
||||
Command::broadcastCommandMessage($sender, "Set time to " . $value);
|
||||
|
||||
return true;
|
||||
case "add":
|
||||
if (!$sender->hasPermission("pocketmine.command.time.add")){
|
||||
$sender->sendMessage(TextFormat::RED."You don't have permission to set the time");
|
||||
if(!$sender->hasPermission("pocketmine.command.time.add")){
|
||||
$sender->sendMessage(TextFormat::RED . "You don't have permission to set the time");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
$value = $this->getInteger($sender, $args[1], 0);
|
||||
|
||||
|
||||
foreach(Server::getInstance()->getLevels() as $level){
|
||||
$level->setTime($level->getTime() + $value);
|
||||
}
|
||||
|
||||
Command::broadcastCommandMessage($sender, "Added ".$value." to time");
|
||||
|
||||
return true;
|
||||
|
||||
Command::broadcastCommandMessage($sender, "Added " . $value . " to time");
|
||||
|
||||
return true;
|
||||
default:
|
||||
$sender->sendMessage("Unknown method. Usage: ".$this->getUsage());
|
||||
$sender->sendMessage("Unknown method. Usage: " . $this->getUsage());
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -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];
|
||||
unset($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);
|
||||
}
|
||||
|
67
src/pocketmine/inventory/ChestInventory.php
Normal file
67
src/pocketmine/inventory/ChestInventory.php
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
55
src/pocketmine/inventory/ContainerInventory.php
Normal file
55
src/pocketmine/inventory/ContainerInventory.php
Normal 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);
|
||||
}
|
||||
}
|
101
src/pocketmine/inventory/DoubleChestInventory.php
Normal file
101
src/pocketmine/inventory/DoubleChestInventory.php
Normal 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;
|
||||
}
|
||||
}
|
92
src/pocketmine/inventory/FurnaceInventory.php
Normal file
92
src/pocketmine/inventory/FurnaceInventory.php
Normal 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
|
||||
}
|
||||
}
|
@ -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);
|
||||
|
||||
@ -164,7 +175,7 @@ interface Inventory{
|
||||
public function onClose(Player $who);
|
||||
|
||||
/**
|
||||
* @param int $index
|
||||
* @param int $index
|
||||
* @param Item|null $before
|
||||
*/
|
||||
public function onSlotChange($index, $before);
|
||||
|
@ -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
|
||||
@ -53,7 +55,7 @@ class InventoryType{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $defaultSize
|
||||
* @param int $defaultSize
|
||||
* @param string $defaultTitle
|
||||
*/
|
||||
private function __construct($defaultSize, $defaultTitle){
|
||||
|
@ -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,16 +102,47 @@ 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);
|
||||
$item = $this->getItemInHand();
|
||||
$this->sendHeldItem($this->getHolder()->getViewers());
|
||||
|
||||
$pk = new PlayerEquipmentPacket;
|
||||
$pk->eid = $this->getHolder()->getID();
|
||||
$pk->item = $item->getID();
|
||||
$pk->meta = $item->getDamage();
|
||||
$pk->slot = 0;
|
||||
if($this->getHolder() instanceof Player){
|
||||
$this->sendHeldItem($this->getHolder());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach($this->getHolder()->getViewers() as $player){
|
||||
/**
|
||||
* @param Player|Player[] $target
|
||||
*/
|
||||
public function sendHeldItem($target){
|
||||
if($target instanceof Player){
|
||||
$target = [$target];
|
||||
}
|
||||
|
||||
$item = $this->getItemInHand();
|
||||
|
||||
$pk = new PlayerEquipmentPacket;
|
||||
$pk->eid = $this->getHolder()->getID();
|
||||
$pk->item = $item->getID();
|
||||
$pk->meta = $item->getDamage();
|
||||
$pk->slot = 0;
|
||||
|
||||
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 = [];
|
||||
$this->sendArmorContents($this->getHolder()->getViewers());
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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
|
||||
*/
|
||||
|
@ -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;
|
||||
|
@ -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{
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -52,11 +52,11 @@ interface Chunk{
|
||||
public function getBlock($x, $y, $z, &$blockId, &$meta = null);
|
||||
|
||||
/**
|
||||
* @param int $x 0-15
|
||||
* @param int $y 0-127
|
||||
* @param int $z 0-15
|
||||
* @param int $blockId, if null, do not change
|
||||
* @param int $meta 0-15, if null, do not change
|
||||
* @param int $x 0-15
|
||||
* @param int $y 0-127
|
||||
* @param int $z 0-15
|
||||
* @param int $blockId , if null, do not change
|
||||
* @param int $meta 0-15, if null, do not change
|
||||
*/
|
||||
public function setBlock($x, $y, $z, $blockId = null, $meta = null);
|
||||
|
||||
@ -70,9 +70,9 @@ interface Chunk{
|
||||
public function getBlockId($x, $y, $z);
|
||||
|
||||
/**
|
||||
* @param int $x 0-15
|
||||
* @param int $y 0-127
|
||||
* @param int $z 0-15
|
||||
* @param int $x 0-15
|
||||
* @param int $y 0-127
|
||||
* @param int $z 0-15
|
||||
* @param int $id 0-255
|
||||
*/
|
||||
public function setBlockId($x, $y, $z, $id);
|
||||
@ -87,9 +87,9 @@ interface Chunk{
|
||||
public function getBlockData($x, $y, $z);
|
||||
|
||||
/**
|
||||
* @param int $x 0-15
|
||||
* @param int $y 0-127
|
||||
* @param int $z 0-15
|
||||
* @param int $x 0-15
|
||||
* @param int $y 0-127
|
||||
* @param int $z 0-15
|
||||
* @param int $data 0-15
|
||||
*/
|
||||
public function setBlockData($x, $y, $z, $data);
|
||||
@ -104,9 +104,9 @@ interface Chunk{
|
||||
public function getBlockSkyLight($x, $y, $z);
|
||||
|
||||
/**
|
||||
* @param int $x 0-15
|
||||
* @param int $y 0-127
|
||||
* @param int $z 0-15
|
||||
* @param int $x 0-15
|
||||
* @param int $y 0-127
|
||||
* @param int $z 0-15
|
||||
* @param int $level 0-15
|
||||
*/
|
||||
public function setBlockSkyLight($x, $y, $z, $level);
|
||||
@ -121,9 +121,9 @@ interface Chunk{
|
||||
public function getBlockLight($x, $y, $z);
|
||||
|
||||
/**
|
||||
* @param int $x 0-15
|
||||
* @param int $y 0-127
|
||||
* @param int $z 0-15
|
||||
* @param int $x 0-15
|
||||
* @param int $y 0-127
|
||||
* @param int $z 0-15
|
||||
* @param int $level 0-15
|
||||
*/
|
||||
public function setBlockLight($x, $y, $z, $level);
|
||||
|
@ -33,9 +33,9 @@ interface ChunkSection{
|
||||
public function getBlockId($x, $y, $z);
|
||||
|
||||
/**
|
||||
* @param int $x 0-15
|
||||
* @param int $y 0-15
|
||||
* @param int $z 0-15
|
||||
* @param int $x 0-15
|
||||
* @param int $y 0-15
|
||||
* @param int $z 0-15
|
||||
* @param int $id 0-255
|
||||
*/
|
||||
public function setBlockId($x, $y, $z, $id);
|
||||
@ -50,9 +50,9 @@ interface ChunkSection{
|
||||
public function getBlockData($x, $y, $z);
|
||||
|
||||
/**
|
||||
* @param int $x 0-15
|
||||
* @param int $y 0-15
|
||||
* @param int $z 0-15
|
||||
* @param int $x 0-15
|
||||
* @param int $y 0-15
|
||||
* @param int $z 0-15
|
||||
* @param int $data 0-15
|
||||
*/
|
||||
public function setBlockData($x, $y, $z, $data);
|
||||
@ -69,11 +69,11 @@ interface ChunkSection{
|
||||
public function getBlock($x, $y, $z, &$blockId, &$meta = null);
|
||||
|
||||
/**
|
||||
* @param int $x 0-15
|
||||
* @param int $y 0-15
|
||||
* @param int $z 0-15
|
||||
* @param int $blockId, if null, do not change
|
||||
* @param int $meta 0-15, if null, do not change
|
||||
* @param int $x 0-15
|
||||
* @param int $y 0-15
|
||||
* @param int $z 0-15
|
||||
* @param int $blockId , if null, do not change
|
||||
* @param int $meta 0-15, if null, do not change
|
||||
*/
|
||||
public function setBlock($x, $y, $z, $blockId = null, $meta = null);
|
||||
|
||||
@ -87,9 +87,9 @@ interface ChunkSection{
|
||||
public function getBlockSkyLight($x, $y, $z);
|
||||
|
||||
/**
|
||||
* @param int $x 0-15
|
||||
* @param int $y 0-15
|
||||
* @param int $z 0-15
|
||||
* @param int $x 0-15
|
||||
* @param int $y 0-15
|
||||
* @param int $z 0-15
|
||||
* @param int $level 0-15
|
||||
*/
|
||||
public function setBlockSkyLight($x, $y, $z, $level);
|
||||
@ -104,9 +104,9 @@ interface ChunkSection{
|
||||
public function getBlockLight($x, $y, $z);
|
||||
|
||||
/**
|
||||
* @param int $x 0-15
|
||||
* @param int $y 0-15
|
||||
* @param int $z 0-15
|
||||
* @param int $x 0-15
|
||||
* @param int $y 0-15
|
||||
* @param int $z 0-15
|
||||
* @param int $level 0-15
|
||||
*/
|
||||
public function setBlockLight($x, $y, $z, $level);
|
||||
|
@ -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
|
||||
@ -48,8 +49,8 @@ interface LevelFormat{
|
||||
* Gets the Chunk object
|
||||
* This method must be implemented by all the level formats.
|
||||
*
|
||||
* @param int $X absolute Chunk X value
|
||||
* @param int $Z absolute Chunk Z value
|
||||
* @param int $X absolute Chunk X value
|
||||
* @param int $Z absolute Chunk Z value
|
||||
* @param bool $create Whether to generate the chunk if it does not exist
|
||||
*
|
||||
* @return ChunkSnapshot
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
*/
|
||||
|
||||
namespace pocketmine\level\format\generic;
|
||||
|
||||
use pocketmine\level\format\Chunk;
|
||||
use pocketmine\level\format\ChunkSection;
|
||||
use pocketmine\level\Level;
|
||||
@ -34,9 +35,9 @@ abstract class BaseChunk implements Chunk{
|
||||
protected $z;
|
||||
|
||||
/**
|
||||
* @param Level $level
|
||||
* @param int $x
|
||||
* @param int $z
|
||||
* @param Level $level
|
||||
* @param int $x
|
||||
* @param int $z
|
||||
* @param ChunkSection[] $sections
|
||||
*/
|
||||
public function __construct(Level $level, $x, $z, array $sections){
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
*/
|
||||
|
||||
namespace pocketmine\level\format\generic;
|
||||
|
||||
use pocketmine\level\format\ChunkSection;
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -33,7 +33,7 @@ abstract class MetadataStore{
|
||||
/**
|
||||
* Adds a metadata value to an object.
|
||||
*
|
||||
* @param mixed $subject
|
||||
* @param mixed $subject
|
||||
* @param string $metadataKey
|
||||
* @param MetadataValue $newMetadataValue
|
||||
*/
|
||||
@ -41,6 +41,7 @@ abstract class MetadataStore{
|
||||
$owningPlugin = $newMetadataValue->getOwningPlugin();
|
||||
if($owningPlugin === null){
|
||||
trigger_error("Plugin cannot be null", E_USER_WARNING);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -58,7 +59,7 @@ abstract class MetadataStore{
|
||||
* Returns all metadata values attached to an object. If multiple
|
||||
* have attached metadata, each will value will be included.
|
||||
*
|
||||
* @param mixed $subject
|
||||
* @param mixed $subject
|
||||
* @param string $metadataKey
|
||||
*
|
||||
* @return MetadataValue[]
|
||||
@ -75,7 +76,7 @@ abstract class MetadataStore{
|
||||
/**
|
||||
* Tests to see if a metadata attribute has been set on an object.
|
||||
*
|
||||
* @param mixed $subject
|
||||
* @param mixed $subject
|
||||
* @param string $metadataKey
|
||||
*
|
||||
* @return bool
|
||||
@ -87,7 +88,7 @@ abstract class MetadataStore{
|
||||
/**
|
||||
* Removes a metadata item owned by a plugin from a subject.
|
||||
*
|
||||
* @param mixed $subject
|
||||
* @param mixed $subject
|
||||
* @param string $metadataKey
|
||||
* @param Plugin $owningPlugin
|
||||
*/
|
||||
@ -121,7 +122,7 @@ abstract class MetadataStore{
|
||||
* Creates a unique name for the object receiving metadata by combining
|
||||
* unique data from the subject with a metadataKey.
|
||||
*
|
||||
* @param mixed $subject
|
||||
* @param mixed $subject
|
||||
* @param string $metadataKey
|
||||
*
|
||||
* @return string
|
||||
|
@ -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
|
||||
|
@ -22,7 +22,6 @@
|
||||
namespace pocketmine\network\protocol;
|
||||
|
||||
use pocketmine\utils\Binary;
|
||||
use pocketmine\utils\Utils;
|
||||
|
||||
class AddMobPacket extends DataPacket{
|
||||
public $eid;
|
||||
|
@ -22,7 +22,6 @@
|
||||
namespace pocketmine\network\protocol;
|
||||
|
||||
use pocketmine\utils\Binary;
|
||||
use pocketmine\utils\Utils;
|
||||
|
||||
class AddPlayerPacket extends DataPacket{
|
||||
public $clientID;
|
||||
|
@ -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;
|
||||
|
@ -22,7 +22,6 @@
|
||||
namespace pocketmine\network\protocol;
|
||||
|
||||
use pocketmine\utils\Binary;
|
||||
use pocketmine\utils\Utils;
|
||||
|
||||
class SetEntityDataPacket extends DataPacket{
|
||||
public $eid;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -22,7 +22,6 @@
|
||||
namespace pocketmine\network\rcon;
|
||||
|
||||
use pocketmine\utils\Binary;
|
||||
use pocketmine\utils\Utils;
|
||||
|
||||
class RCONInstance extends \Thread{
|
||||
public $stop;
|
||||
|
@ -23,6 +23,7 @@
|
||||
* Plugin related classes
|
||||
*/
|
||||
namespace pocketmine\plugin;
|
||||
|
||||
use pocketmine\command\CommandExecutor;
|
||||
|
||||
|
||||
@ -71,7 +72,7 @@ interface Plugin extends CommandExecutor{
|
||||
* Saves an embedded resource to its relative location in the data folder
|
||||
*
|
||||
* @param string $filename
|
||||
* @param bool $replace
|
||||
* @param bool $replace
|
||||
*/
|
||||
public function saveResource($filename, $replace = false);
|
||||
|
||||
|
@ -30,7 +30,7 @@ class PluginLogger{
|
||||
*/
|
||||
public function __construct(Plugin $context){
|
||||
$prefix = $context->getDescription()->getPrefix();
|
||||
$this->pluginName = $prefix != null ? "[$prefix] " : "[".$context->getDescription()->getName()."] ";
|
||||
$this->pluginName = $prefix != null ? "[$prefix] " : "[" . $context->getDescription()->getName() . "] ";
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -148,6 +148,7 @@ class PluginManager{
|
||||
if(count($pluginCommands) > 0){
|
||||
$this->commandMap->registerAll($plugin->getDescription()->getName(), $pluginCommands);
|
||||
}
|
||||
|
||||
return $plugin;
|
||||
}
|
||||
}
|
||||
@ -159,7 +160,7 @@ class PluginManager{
|
||||
|
||||
/**
|
||||
* @param string $directory
|
||||
* @param array $newLoaders
|
||||
* @param array $newLoaders
|
||||
*
|
||||
* @return Plugin[]
|
||||
*/
|
||||
|
@ -52,8 +52,9 @@ abstract class AsyncTask extends \Threaded{
|
||||
* @return mixed
|
||||
*/
|
||||
public function getResult(){
|
||||
return $this->synchronized(function(){
|
||||
return $this->synchronized(function (){
|
||||
$this->finished = true;
|
||||
|
||||
return @unserialize($this->result);
|
||||
});
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -205,11 +205,13 @@ class ServerScheduler{
|
||||
}
|
||||
|
||||
if($this->asyncTasks > 0){ //Garbage collector
|
||||
$this->asyncPool->collect(function(AsyncTask $task){
|
||||
$this->asyncPool->collect(function (AsyncTask $task){
|
||||
if($task->isCompleted() or ($task->isFinished() and !$task->hasResult())){
|
||||
--$this->asyncTasks;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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]);
|
||||
}
|
||||
}
|
||||
|
@ -171,6 +171,7 @@ class Binary{
|
||||
|
||||
return $m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a byte boolean
|
||||
*
|
||||
@ -197,7 +198,7 @@ class Binary{
|
||||
* Reads an unsigned/signed byte
|
||||
*
|
||||
* @param string $c
|
||||
* @param bool $signed
|
||||
* @param bool $signed
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
|
@ -262,12 +262,13 @@ class Config{
|
||||
$currPath = null;
|
||||
}
|
||||
}
|
||||
|
||||
return $currPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param mixed $value
|
||||
* @param mixed $value
|
||||
*/
|
||||
public function &setPath($path, $value){
|
||||
$currPath =& $this->config;
|
||||
|
@ -69,6 +69,7 @@ class Random{
|
||||
if($t > 2147483647){
|
||||
$t -= 4294967296;
|
||||
}
|
||||
|
||||
return (int) $t;
|
||||
}
|
||||
|
||||
|
@ -274,6 +274,7 @@ class TextFormat{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $newString;
|
||||
}
|
||||
|
||||
|
@ -24,8 +24,6 @@
|
||||
*/
|
||||
namespace pocketmine\utils;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
|
||||
/**
|
||||
* Big collection of functions
|
||||
*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user