mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-05-14 01:39:52 +00:00
Items can be picked up
This commit is contained in:
parent
03d7127e33
commit
274f972b58
@ -23,6 +23,7 @@ namespace pocketmine;
|
||||
|
||||
use pocketmine\block\Block;
|
||||
use pocketmine\command\CommandSender;
|
||||
use pocketmine\entity\DroppedItem;
|
||||
use pocketmine\entity\Human;
|
||||
use pocketmine\event\player\PlayerAchievementAwardedEvent;
|
||||
use pocketmine\event\player\PlayerChatEvent;
|
||||
@ -60,6 +61,7 @@ use pocketmine\network\protocol\ServerHandshakePacket;
|
||||
use pocketmine\network\protocol\SetSpawnPositionPacket;
|
||||
use pocketmine\network\protocol\SetTimePacket;
|
||||
use pocketmine\network\protocol\StartGamePacket;
|
||||
use pocketmine\network\protocol\TakeItemEntityPacket;
|
||||
use pocketmine\network\protocol\UnknownPacket;
|
||||
use pocketmine\network\protocol\UpdateBlockPacket;
|
||||
use pocketmine\network\raknet\Info;
|
||||
@ -858,31 +860,6 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "player.pickup":
|
||||
if($data["eid"] === $this->id){
|
||||
$data["eid"] = 0;
|
||||
$pk = new TakeItemEntityPacket;
|
||||
$pk->eid = 0;
|
||||
$pk->target = $data["entity"]->getID();
|
||||
$this->dataPacket($pk);
|
||||
if(($this->gamemode & 0x01) === 0x00){
|
||||
//$this->addItem($data["entity"]->type, $data["entity"]->meta, $data["entity"]->stack);
|
||||
}
|
||||
switch($data["entity"]->type){
|
||||
case Item::WOOD:
|
||||
$this->awardAchievement("mineWood");
|
||||
break;
|
||||
case Item::DIAMOND:
|
||||
$this->awardAchievement("diamond");
|
||||
break;
|
||||
}
|
||||
}elseif($data["entity"]->getLevel() === $this->getLevel()){
|
||||
$pk = new TakeItemEntityPacket;
|
||||
$pk->eid = $data["eid"];
|
||||
$pk->target = $data["entity"]->getID();
|
||||
$this->dataPacket($pk);
|
||||
}
|
||||
break;
|
||||
case "entity.animate":
|
||||
if($data["eid"] === $this->id or $data["entity"]->getLevel() !== $this->getLevel()){
|
||||
break;
|
||||
@ -1212,6 +1189,48 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
}
|
||||
}
|
||||
|
||||
public function onUpdate(){
|
||||
if($this->spawned === false){
|
||||
return true;
|
||||
}
|
||||
$hasUpdate = $this->entityBaseTick();
|
||||
foreach($this->getNearbyEntities($this->boundingBox->expand(3, 3, 3)) as $entity){
|
||||
if($entity instanceof DroppedItem){
|
||||
if($entity->dead !== true and $entity->getPickupDelay() <= 0){
|
||||
$item = $entity->getItem();
|
||||
|
||||
if($item instanceof Item){
|
||||
if(($this->gamemode & 0x01) === 0 and !$this->inventory->canAddItem($item)){
|
||||
continue;
|
||||
}
|
||||
|
||||
switch($item->getID()){
|
||||
case Item::WOOD:
|
||||
$this->awardAchievement("mineWood");
|
||||
break;
|
||||
case Item::DIAMOND:
|
||||
$this->awardAchievement("diamond");
|
||||
break;
|
||||
}
|
||||
$pk = new TakeItemEntityPacket;
|
||||
$pk->eid = 0;
|
||||
$pk->target = $entity->getID();
|
||||
$this->dataPacket($pk);
|
||||
|
||||
$pk = new TakeItemEntityPacket;
|
||||
$pk->eid = $this->getID();
|
||||
$pk->target = $entity->getID();
|
||||
$this->server->broadcastPacket($entity->getViewers(), $pk);
|
||||
$this->inventory->addItem(clone $item);
|
||||
$entity->kill();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->updateMovement();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a Minecraft packet
|
||||
* TODO: Separate all of this in handlers
|
||||
@ -1409,7 +1428,6 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
//$this->evid[] = $this->server->event("entity.animate", array($this, "eventHandler"));
|
||||
//$this->evid[] = $this->server->event("entity.event", array($this, "eventHandler"));
|
||||
//$this->evid[] = $this->server->event("entity.metadata", array($this, "eventHandler"));
|
||||
//$this->evid[] = $this->server->event("player.pickup", array($this, "eventHandler"));
|
||||
//$this->evid[] = $this->server->event("tile.container.slot", array($this, "eventHandler"));
|
||||
//$this->evid[] = $this->server->event("tile.update", array($this, "eventHandler"));
|
||||
$this->lastMeasure = microtime(true);
|
||||
@ -2001,7 +2019,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
$this->craftingItems = [];
|
||||
}
|
||||
|
||||
if($packet->windowid === 0){ //Crafting!
|
||||
if($packet->windowid == 0){ //Crafting!
|
||||
$craft = false;
|
||||
$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
|
||||
@ -2039,6 +2057,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
|
||||
}
|
||||
$this->craftingItems = [];
|
||||
}
|
||||
break;
|
||||
}else{
|
||||
$this->toCraft = [];
|
||||
$this->craftingItems = [];
|
||||
|
@ -62,12 +62,15 @@ class DroppedItem extends Entity{
|
||||
if(isset($this->namedtag->Thrower)){
|
||||
$this->thrower = $this->namedtag["Thrower"];
|
||||
}
|
||||
$this->item = Item::get($this->namedtag->Item["id"], $this->namedtag->Item["Damage"], min(64, $this->namedtag->Item["Count"]));
|
||||
$this->item = Item::get($this->namedtag->Item["id"], $this->namedtag->Item["Damage"], $this->namedtag->Item["Count"]);
|
||||
}
|
||||
|
||||
public function onUpdate(){
|
||||
$this->entityBaseTick();
|
||||
//TODO: manage pickupDelay
|
||||
|
||||
if($this->pickupDelay > 0 and $this->pickupDelay < 32767){ //Infinite delay
|
||||
--$this->pickupDelay;
|
||||
}
|
||||
|
||||
$this->motionY -= $this->gravity;
|
||||
$this->inBlock = $this->checkObstruction($this->x, ($this->boundingBox->minY + $this->boundingBox->maxY) / 2, $this->z);
|
||||
@ -94,10 +97,13 @@ class DroppedItem extends Entity{
|
||||
$this->motionZ = 0;
|
||||
}
|
||||
|
||||
//TODO: update age in base entity tick
|
||||
//TODO: kill entity if it's old enough
|
||||
if($this->age > 6000){
|
||||
$this->kill();
|
||||
}
|
||||
$this->updateMovement();
|
||||
//$this->server->broadcastMessage("{$this->ticksLived}: ".round($this->x, 2).",".round($this->y, 2).",".round($this->z, 2));
|
||||
|
||||
//TODO: handle scheduled updates
|
||||
return true;
|
||||
}
|
||||
|
||||
public function attack($damage, $source = "generic"){
|
||||
|
@ -360,6 +360,11 @@ abstract class Entity extends Position implements Metadatable{
|
||||
|
||||
public function entityBaseTick(){
|
||||
//TODO: check vehicles
|
||||
if($this->dead === true){
|
||||
$this->close();
|
||||
return false;
|
||||
}
|
||||
|
||||
$hasUpdate = false;
|
||||
$this->lastX = $this->x;
|
||||
$this->lastY = $this->y;
|
||||
@ -600,7 +605,7 @@ abstract class Entity extends Position implements Metadatable{
|
||||
$minX = ($bb->minX - 2) >> 4;
|
||||
$maxX = ($bb->maxX + 2) >> 4;
|
||||
$minZ = ($bb->minZ - 2) >> 4;
|
||||
$maxZ = ($bb->maxX + 2) >> 4;
|
||||
$maxZ = ($bb->maxZ + 2) >> 4;
|
||||
|
||||
for($x = $minX; $x <= $maxX; ++$x){
|
||||
for($z = $minZ; $z <= $maxZ; ++$z){
|
||||
@ -904,6 +909,7 @@ abstract class Entity extends Position implements Metadatable{
|
||||
|
||||
public function kill(){
|
||||
$this->dead = true;
|
||||
$this->scheduleUpdate();
|
||||
}
|
||||
|
||||
public function teleport(Vector3 $pos, $yaw = false, $pitch = false){
|
||||
|
@ -202,25 +202,44 @@ abstract class BaseInventory implements Inventory{
|
||||
return -1;
|
||||
}
|
||||
|
||||
public function canAddItem(Item $item){
|
||||
$item = clone $item;
|
||||
$checkDamage = $item->getDamage() === null ? false : true;
|
||||
for($i = 0; $i < $this->getSize(); ++$i){
|
||||
$slot = $this->getItem($i);
|
||||
if($item->equals($slot, $checkDamage)){
|
||||
if(($diff = $slot->getMaxStackSize() - $slot->getCount()) > 0){
|
||||
$item->setCount($item->getCount() - $diff);
|
||||
}
|
||||
}elseif($slot->getID() === Item::AIR){
|
||||
$item->setCount($item->getCount() - $this->getMaxStackSize());
|
||||
}
|
||||
|
||||
if($item->getCount() <= 0){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function addItem(){
|
||||
/** @var Item[] $slots */
|
||||
$slots = func_get_args();
|
||||
foreach($slots as $i => $slot){
|
||||
if($slot->getCount() > $slot->getMaxStackSize()){
|
||||
while($slot->getCount() > $slot->getMaxStackSize()){
|
||||
$slots[] = Item::get($slot->getID(), $slot->getDamage(), $slot->getMaxStackSize());
|
||||
$slot->setCount($slot->getCount() - $slot->getMaxStackSize());
|
||||
if(count($slots) > $this->getSize()){ //Protect against large give commands
|
||||
break;
|
||||
}
|
||||
while($slot->getCount() > $slot->getMaxStackSize()){
|
||||
$slots[] = Item::get($slot->getID(), $slot->getDamage(), $slot->getMaxStackSize());
|
||||
$slot->setCount($slot->getCount() - $slot->getMaxStackSize());
|
||||
if(count($slots) > $this->getSize()){ //Protect against large give commands
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
for($i = 0; $i < $this->size; ++$i){
|
||||
|
||||
for($i = 0; $i < $this->getSize(); ++$i){
|
||||
$item = $this->getItem($i);
|
||||
if($item->getID() === Item::AIR){
|
||||
$item = array_shift($slots);
|
||||
$this->setItem($i, $item);
|
||||
$this->setItem($i, array_shift($slots));
|
||||
$item = $this->getItem($i);
|
||||
}
|
||||
|
||||
foreach($slots as $index => $slot){
|
||||
@ -242,14 +261,13 @@ abstract class BaseInventory implements Inventory{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $slots;
|
||||
}
|
||||
|
||||
public function removeItem(){
|
||||
/** @var Item[] $slots */
|
||||
$slots = func_get_args();
|
||||
for($i = 0; $i < $this->size; ++$i){
|
||||
for($i = 0; $i < $this->getSize(); ++$i){
|
||||
$item = $this->getItem($i);
|
||||
if($item->getID() === Item::AIR){
|
||||
continue;
|
||||
|
@ -62,7 +62,7 @@ interface Inventory{
|
||||
public function setItem($index, Item $item);
|
||||
|
||||
/**
|
||||
* Stores the given Item in the inventory. This will try to fill
|
||||
* Stores the given Items in the inventory. This will try to fill
|
||||
* existing stacks and empty slots as well as it can.
|
||||
*
|
||||
* Returns the Items that did not fit
|
||||
@ -73,6 +73,15 @@ interface Inventory{
|
||||
*/
|
||||
public function addItem();
|
||||
|
||||
/**
|
||||
* Checks if a given Item can be added to the inventory
|
||||
*
|
||||
* @param Item $item
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function canAddItem(Item $item);
|
||||
|
||||
/**
|
||||
* Removes the given Item from the inventory.
|
||||
* It will return the Items that couldn't be removed.
|
||||
|
@ -114,10 +114,6 @@ class PlayerInventory extends BaseInventory{
|
||||
|
||||
$this->setHotbarSlotIndex($this->itemInHandIndex, $slot);
|
||||
$this->sendHeldItem($this->getHolder()->getViewers());
|
||||
|
||||
if($this->getHolder() instanceof Player){
|
||||
$this->sendHeldItem($this->getHolder());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -705,7 +705,9 @@ class Level{
|
||||
"Damage" => new Short("Damage", $item->getDamage()),
|
||||
"Count" => new Byte("Count", $item->getCount())
|
||||
]),
|
||||
"PickupDelay" => new Short("PickupDelay", 10)
|
||||
]));
|
||||
|
||||
$itemEntity->spawnToAll();
|
||||
}
|
||||
}
|
||||
@ -764,7 +766,9 @@ class Level{
|
||||
|
||||
if(!($player instanceof Player) or ($player->getGamemode() & 0x01) === 0){
|
||||
foreach($target->getDrops($item) as $drop){
|
||||
$this->dropItem($vector->add(0.5, 0.5, 0.5), Item::get($drop[0], $drop[1], $drop[2]), 5);
|
||||
if($drop[2] > 0){
|
||||
$this->dropItem($vector->add(0.5, 0.5, 0.5), Item::get($drop[0], $drop[1], $drop[2]), 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
Loading…
x
Reference in New Issue
Block a user