Rough OffHand implementation

this doesn't do stuff like taking arrows from offhand yet.
This commit is contained in:
Dylan K. Taylor
2021-05-05 14:46:51 +01:00
parent e8cb49f7ae
commit 652de2632a
9 changed files with 101 additions and 11 deletions

View File

@@ -1599,6 +1599,7 @@ abstract class Entity{
$properties->setLong(EntityMetadataProperties::TARGET_EID, $this->targetId ?? 0);
$properties->setString(EntityMetadataProperties::NAMETAG, $this->nameTag);
$properties->setString(EntityMetadataProperties::SCORE_TAG, $this->scoreTag);
$properties->setByte(EntityMetadataProperties::COLOR, 0);
$properties->setGenericFlag(EntityMetadataFlags::AFFECTED_BY_GRAVITY, true);
$properties->setGenericFlag(EntityMetadataFlags::CAN_CLIMB, $this->canClimb);

View File

@@ -239,6 +239,7 @@ class ExperienceManager{
public function onPickupXp(int $xpValue) : void{
static $mainHandIndex = -1;
static $offHandIndex = -2;
//TODO: replace this with a more generic equipment getting/setting interface
/** @var Durable[] $equipment */
@@ -247,7 +248,9 @@ class ExperienceManager{
if(($item = $this->entity->getInventory()->getItemInHand()) instanceof Durable and $item->hasEnchantment(VanillaEnchantments::MENDING())){
$equipment[$mainHandIndex] = $item;
}
//TODO: check offhand
if(($item = $this->entity->getOffHandInventory()->getItem(0)) instanceof Durable and $item->hasEnchantment(VanillaEnchantments::MENDING())){
$equipment[$offHandIndex] = $item;
}
foreach($this->entity->getArmorInventory()->getContents() as $k => $armorItem){
if($armorItem instanceof Durable and $armorItem->hasEnchantment(VanillaEnchantments::MENDING())){
$equipment[$k] = $armorItem;
@@ -263,6 +266,8 @@ class ExperienceManager{
if($k === $mainHandIndex){
$this->entity->getInventory()->setItemInHand($repairItem);
}elseif($k === $offHandIndex){
$this->entity->getOffHandInventory()->setItem(0, $repairItem);
}else{
$this->entity->getArmorInventory()->setItem($k, $repairItem);
}

View File

@@ -34,6 +34,7 @@ use pocketmine\inventory\Inventory;
use pocketmine\inventory\InventoryHolder;
use pocketmine\inventory\PlayerEnderInventory;
use pocketmine\inventory\PlayerInventory;
use pocketmine\inventory\PlayerOffHandInventory;
use pocketmine\item\enchantment\VanillaEnchantments;
use pocketmine\item\Item;
use pocketmine\item\Totem;
@@ -73,6 +74,9 @@ class Human extends Living implements ProjectileSource, InventoryHolder{
/** @var PlayerInventory */
protected $inventory;
/** @var PlayerOffHandInventory */
protected $offHandInventory;
/** @var PlayerEnderInventory */
protected $enderInventory;
@@ -193,6 +197,8 @@ class Human extends Living implements ProjectileSource, InventoryHolder{
return $this->inventory;
}
public function getOffHandInventory() : PlayerOffHandInventory{ return $this->offHandInventory; }
public function getEnderInventory() : PlayerEnderInventory{
return $this->enderInventory;
}
@@ -218,7 +224,7 @@ class Human extends Living implements ProjectileSource, InventoryHolder{
$this->inventory = new PlayerInventory($this);
$syncHeldItem = function() : void{
foreach($this->getViewers() as $viewer){
$viewer->getNetworkSession()->onMobEquipmentChange($this);
$viewer->getNetworkSession()->onMobMainHandItemChange($this);
}
};
$this->inventory->getListeners()->add(new CallbackInventoryListener(
@@ -233,6 +239,7 @@ class Human extends Living implements ProjectileSource, InventoryHolder{
}
}
));
$this->offHandInventory = new PlayerOffHandInventory($this);
$this->enderInventory = new PlayerEnderInventory($this);
$this->initHumanData($nbt);
@@ -258,6 +265,15 @@ class Human extends Living implements ProjectileSource, InventoryHolder{
$this->armorInventory->getListeners()->add(...$armorListeners);
$this->inventory->getListeners()->add(...$inventoryListeners);
}
$offHand = $nbt->getCompoundTag("OffHandItem");
if($offHand !== null){
$this->offHandInventory->setItem(0, Item::nbtDeserialize($offHand));
}
$this->offHandInventory->getListeners()->add(CallbackInventoryListener::onAnyChange(function() : void{
foreach($this->getViewers() as $viewer){
$viewer->getNetworkSession()->onMobOffHandItemChange($this);
}
}));
$enderChestInventoryTag = $nbt->getListTag("EnderChestInventory");
if($enderChestInventoryTag !== null){
@@ -270,7 +286,7 @@ class Human extends Living implements ProjectileSource, InventoryHolder{
$this->inventory->setHeldItemIndex($nbt->getInt("SelectedInventorySlot", 0));
$this->inventory->getHeldItemIndexChangeListeners()->add(function(int $oldIndex) : void{
foreach($this->getViewers() as $viewer){
$viewer->getNetworkSession()->onMobEquipmentChange($this);
$viewer->getNetworkSession()->onMobMainHandItemChange($this);
}
});
@@ -309,7 +325,7 @@ class Human extends Living implements ProjectileSource, InventoryHolder{
$type = $source->getCause();
if($type !== EntityDamageEvent::CAUSE_SUICIDE and $type !== EntityDamageEvent::CAUSE_VOID
and $this->inventory->getItemInHand() instanceof Totem){ //TODO: check offhand as well (when it's implemented)
and ($this->inventory->getItemInHand() instanceof Totem || $this->offHandInventory->getItem(0) instanceof Totem)){
$compensation = $this->getHealth() - $source->getFinalDamage() - 1;
if($compensation < 0){
@@ -335,6 +351,9 @@ class Human extends Living implements ProjectileSource, InventoryHolder{
if($hand instanceof Totem){
$hand->pop(); //Plugins could alter max stack size
$this->inventory->setItemInHand($hand);
}elseif(($offHand = $this->offHandInventory->getItem(0)) instanceof Totem){
$offHand->pop();
$this->offHandInventory->setItem(0, $offHand);
}
}
}
@@ -342,7 +361,8 @@ class Human extends Living implements ProjectileSource, InventoryHolder{
public function getDrops() : array{
return array_filter(array_merge(
$this->inventory !== null ? array_values($this->inventory->getContents()) : [],
$this->armorInventory !== null ? array_values($this->armorInventory->getContents()) : []
$this->armorInventory !== null ? array_values($this->armorInventory->getContents()) : [],
$this->offHandInventory !== null ? array_values($this->offHandInventory->getContents()) : [],
), function(Item $item) : bool{ return !$item->hasEnchantment(VanillaEnchantments::VANISHING()); });
}
@@ -381,6 +401,10 @@ class Human extends Living implements ProjectileSource, InventoryHolder{
$nbt->setInt("SelectedInventorySlot", $this->inventory->getHeldItemIndex());
}
$offHandItem = $this->offHandInventory->getItem(0);
if(!$offHandItem->isNull()){
$nbt->setTag("OffHandItem", $offHandItem->nbtSerialize());
}
if($this->enderInventory !== null){
/** @var CompoundTag[] $items */
@@ -437,6 +461,7 @@ class Human extends Living implements ProjectileSource, InventoryHolder{
$this->sendData([$player], [EntityMetadataProperties::NAMETAG => new StringMetadataProperty($this->getNameTag())]);
$player->getNetworkSession()->onMobArmorChange($this);
$player->getNetworkSession()->onMobOffHandItemChange($this);
if(!($this instanceof Player)){
$player->getNetworkSession()->sendDataPacket(PlayerListPacket::remove([PlayerListEntry::createRemovalEntry($this->uuid)]));
@@ -466,12 +491,14 @@ class Human extends Living implements ProjectileSource, InventoryHolder{
protected function onDispose() : void{
$this->inventory->removeAllViewers();
$this->inventory->getHeldItemIndexChangeListeners()->clear();
$this->offHandInventory->removeAllViewers();
$this->enderInventory->removeAllViewers();
parent::onDispose();
}
protected function destroyCycles() : void{
$this->inventory = null;
$this->offHandInventory = null;
$this->enderInventory = null;
$this->hungerManager = null;
$this->xpManager = null;