Implement horse inventory (#4053)
* Implement horse inventory * Fix sign conversions * Add API doc for ItemCategory::IsHorseArmor * Improve HandleOpenHorseInventory comment and style fixes.
This commit is contained in:
parent
e585595ae6
commit
0bacda3269
@ -16977,6 +16977,24 @@ end
|
|||||||
},
|
},
|
||||||
Notes = "Returns true if the specified item type is any kind of a hoe.",
|
Notes = "Returns true if the specified item type is any kind of a hoe.",
|
||||||
},
|
},
|
||||||
|
IsHorseArmor=
|
||||||
|
{
|
||||||
|
IsStatic = true,
|
||||||
|
Params =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
Name = "ItemType",
|
||||||
|
Type = "number",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Returns =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
Type = "boolean",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Notes = "Returns true if the specified item type is any kind of a horse armor.",
|
||||||
|
},
|
||||||
IsLeggings =
|
IsLeggings =
|
||||||
{
|
{
|
||||||
IsStatic = true,
|
IsStatic = true,
|
||||||
|
@ -678,6 +678,18 @@ void cClientHandle::HandleNPCTrade(int a_SlotNum)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cClientHandle::HandleOpenHorseInventory(UInt32 a_EntityID)
|
||||||
|
{
|
||||||
|
if (m_Player->GetUniqueID() == a_EntityID)
|
||||||
|
{
|
||||||
|
m_Player->OpenHorseInventory();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cClientHandle::HandlePing(void)
|
void cClientHandle::HandlePing(void)
|
||||||
{
|
{
|
||||||
/* TODO: unused function, handles Legacy Server List Ping
|
/* TODO: unused function, handles Legacy Server List Ping
|
||||||
|
@ -338,6 +338,10 @@ public: // tolua_export
|
|||||||
the NPC UI. */
|
the NPC UI. */
|
||||||
void HandleNPCTrade(int a_SlotNum);
|
void HandleNPCTrade(int a_SlotNum);
|
||||||
|
|
||||||
|
/** Handles a player opening their inventory while riding a horse.
|
||||||
|
@param a_EntityID ID of the player that is to open the inventory. Should be the same as GetPlayer()->GetUniqueID(). */
|
||||||
|
void HandleOpenHorseInventory(UInt32 a_EntityID);
|
||||||
|
|
||||||
void HandlePing (void);
|
void HandlePing (void);
|
||||||
void HandlePlayerAbilities (bool a_CanFly, bool a_IsFlying, float FlyingSpeed, float WalkingSpeed);
|
void HandlePlayerAbilities (bool a_CanFly, bool a_IsFlying, float FlyingSpeed, float WalkingSpeed);
|
||||||
void HandlePlayerLook (float a_Rotation, float a_Pitch, bool a_IsOnGround);
|
void HandlePlayerLook (float a_Rotation, float a_Pitch, bool a_IsOnGround);
|
||||||
|
@ -1175,6 +1175,25 @@ namespace ItemCategory
|
|||||||
IsBoots(a_ItemType)
|
IsBoots(a_ItemType)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
inline bool IsHorseArmor(short a_ItemType)
|
||||||
|
{
|
||||||
|
switch (a_ItemType)
|
||||||
|
{
|
||||||
|
case E_ITEM_IRON_HORSE_ARMOR:
|
||||||
|
case E_ITEM_GOLD_HORSE_ARMOR:
|
||||||
|
case E_ITEM_DIAMOND_HORSE_ARMOR:
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// tolua_end
|
// tolua_end
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include "Player.h"
|
#include "Player.h"
|
||||||
#include "Mobs/Wolf.h"
|
#include "Mobs/Wolf.h"
|
||||||
|
#include "Mobs/Horse.h"
|
||||||
#include "../BoundingBox.h"
|
#include "../BoundingBox.h"
|
||||||
#include "../ChatColor.h"
|
#include "../ChatColor.h"
|
||||||
#include "../Server.h"
|
#include "../Server.h"
|
||||||
@ -2202,6 +2203,35 @@ bool cPlayer::LoadFromFile(const AString & a_FileName, cWorldPtr & a_World)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cPlayer::OpenHorseInventory()
|
||||||
|
{
|
||||||
|
if (
|
||||||
|
(m_AttachedTo == nullptr) ||
|
||||||
|
!m_AttachedTo->IsMob()
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto & Mob = static_cast<cMonster &>(*m_AttachedTo);
|
||||||
|
|
||||||
|
if (Mob.GetMobType() != mtHorse)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto & Horse = static_cast<cHorse &>(Mob);
|
||||||
|
// The client sends requests for untame horses as well but shouldn't actually open
|
||||||
|
if (Horse.IsTame())
|
||||||
|
{
|
||||||
|
Horse.PlayerOpenWindow(*this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cPlayer::SaveToDisk()
|
bool cPlayer::SaveToDisk()
|
||||||
{
|
{
|
||||||
cFile::CreateFolder(FILE_IO_PREFIX + AString("players/")); // Create the "players" folder, if it doesn't exist yet (#1268)
|
cFile::CreateFolder(FILE_IO_PREFIX + AString("players/")); // Create the "players" folder, if it doesn't exist yet (#1268)
|
||||||
|
@ -409,6 +409,10 @@ public:
|
|||||||
|
|
||||||
const AString & GetLoadedWorldName() { return m_LoadedWorldName; }
|
const AString & GetLoadedWorldName() { return m_LoadedWorldName; }
|
||||||
|
|
||||||
|
/** Opens the inventory of any tame horse the player is riding.
|
||||||
|
If the player is not riding a horse or if the horse is untamed, does nothing. */
|
||||||
|
void OpenHorseInventory();
|
||||||
|
|
||||||
void UseEquippedItem(int a_Amount = 1);
|
void UseEquippedItem(int a_Amount = 1);
|
||||||
|
|
||||||
void SendHealth(void);
|
void SendHealth(void);
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include "../EffectID.h"
|
#include "../EffectID.h"
|
||||||
#include "../Entities/Player.h"
|
#include "../Entities/Player.h"
|
||||||
#include "Broadcaster.h"
|
#include "Broadcaster.h"
|
||||||
|
#include "UI/HorseWindow.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -12,16 +13,15 @@
|
|||||||
|
|
||||||
cHorse::cHorse(int Type, int Color, int Style, int TameTimes) :
|
cHorse::cHorse(int Type, int Color, int Style, int TameTimes) :
|
||||||
super("Horse", mtHorse, "entity.horse.hurt", "entity.horse.death", 1.4, 1.6),
|
super("Horse", mtHorse, "entity.horse.hurt", "entity.horse.death", 1.4, 1.6),
|
||||||
|
cEntityWindowOwner(this),
|
||||||
m_bHasChest(false),
|
m_bHasChest(false),
|
||||||
m_bIsEating(false),
|
m_bIsEating(false),
|
||||||
m_bIsRearing(false),
|
m_bIsRearing(false),
|
||||||
m_bIsMouthOpen(false),
|
m_bIsMouthOpen(false),
|
||||||
m_bIsTame(false),
|
m_bIsTame(false),
|
||||||
m_bIsSaddled(false),
|
|
||||||
m_Type(Type),
|
m_Type(Type),
|
||||||
m_Color(Color),
|
m_Color(Color),
|
||||||
m_Style(Style),
|
m_Style(Style),
|
||||||
m_Armour(0),
|
|
||||||
m_TimesToTame(TameTimes),
|
m_TimesToTame(TameTimes),
|
||||||
m_TameAttemptTimes(0),
|
m_TameAttemptTimes(0),
|
||||||
m_RearTickCount(0),
|
m_RearTickCount(0),
|
||||||
@ -33,6 +33,19 @@ cHorse::cHorse(int Type, int Color, int Style, int TameTimes) :
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cHorse::~cHorse()
|
||||||
|
{
|
||||||
|
auto Window = GetWindow();
|
||||||
|
if (Window != nullptr)
|
||||||
|
{
|
||||||
|
Window->OwnerDestroyed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cHorse::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
void cHorse::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
||||||
{
|
{
|
||||||
super::Tick(a_Dt, a_Chunk);
|
super::Tick(a_Dt, a_Chunk);
|
||||||
@ -108,22 +121,24 @@ void cHorse::OnRightClicked(cPlayer & a_Player)
|
|||||||
|
|
||||||
if (m_bIsTame)
|
if (m_bIsTame)
|
||||||
{
|
{
|
||||||
if (!m_bIsSaddled)
|
if (a_Player.IsCrouched())
|
||||||
{
|
{
|
||||||
if (a_Player.GetEquippedItem().m_ItemType == E_ITEM_SADDLE)
|
PlayerOpenWindow(a_Player);
|
||||||
{
|
return;
|
||||||
// Saddle the horse:
|
|
||||||
if (!a_Player.IsGameModeCreative())
|
|
||||||
{
|
|
||||||
a_Player.GetInventory().RemoveOneEquippedItem();
|
|
||||||
}
|
}
|
||||||
m_bIsSaddled = true;
|
|
||||||
m_World->BroadcastEntityMetadata(*this);
|
auto EquipedItemType = a_Player.GetEquippedItem().m_ItemType;
|
||||||
}
|
|
||||||
else
|
if (
|
||||||
|
!IsSaddled() &&
|
||||||
|
(
|
||||||
|
(EquipedItemType == E_ITEM_SADDLE) ||
|
||||||
|
ItemCategory::IsHorseArmor(EquipedItemType)
|
||||||
|
)
|
||||||
|
)
|
||||||
{
|
{
|
||||||
a_Player.AttachTo(this);
|
// Player is holding a horse inventory item, open the window:
|
||||||
}
|
PlayerOpenWindow(a_Player);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -167,6 +182,65 @@ void cHorse::OnRightClicked(cPlayer & a_Player)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cHorse::SetHorseSaddle(cItem a_Saddle)
|
||||||
|
{
|
||||||
|
if (a_Saddle.m_ItemType == E_ITEM_SADDLE)
|
||||||
|
{
|
||||||
|
m_World->BroadcastSoundEffect("entity.horse.saddle", GetPosition(), 1.0f, 0.8f);
|
||||||
|
}
|
||||||
|
else if (!a_Saddle.IsEmpty())
|
||||||
|
{
|
||||||
|
return; // Invalid item
|
||||||
|
}
|
||||||
|
|
||||||
|
m_Saddle = std::move(a_Saddle);
|
||||||
|
m_World->BroadcastEntityMetadata(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cHorse::SetHorseArmor(cItem a_Armor)
|
||||||
|
{
|
||||||
|
if (ItemCategory::IsHorseArmor(a_Armor.m_ItemType))
|
||||||
|
{
|
||||||
|
m_World->BroadcastSoundEffect("entity.horse.armor", GetPosition(), 1.0f, 0.8f);
|
||||||
|
}
|
||||||
|
else if (!a_Armor.IsEmpty())
|
||||||
|
{
|
||||||
|
return; // Invalid item
|
||||||
|
}
|
||||||
|
|
||||||
|
m_Armor = std::move(a_Armor);
|
||||||
|
m_World->BroadcastEntityMetadata(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int cHorse::GetHorseArmour(void) const
|
||||||
|
{
|
||||||
|
switch (m_Armor.m_ItemType)
|
||||||
|
{
|
||||||
|
case E_ITEM_EMPTY: return 0;
|
||||||
|
case E_ITEM_IRON_HORSE_ARMOR: return 1;
|
||||||
|
case E_ITEM_GOLD_HORSE_ARMOR: return 2;
|
||||||
|
case E_ITEM_DIAMOND_HORSE_ARMOR: return 3;
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
LOGWARN("cHorse::GetHorseArmour: Invalid armour item (%d)", m_Armor.m_ItemType);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cHorse::GetDrops(cItems & a_Drops, cEntity * a_Killer)
|
void cHorse::GetDrops(cItems & a_Drops, cEntity * a_Killer)
|
||||||
{
|
{
|
||||||
if (IsBaby())
|
if (IsBaby())
|
||||||
@ -180,9 +254,13 @@ void cHorse::GetDrops(cItems & a_Drops, cEntity * a_Killer)
|
|||||||
LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting);
|
LootingLevel = a_Killer->GetEquippedWeapon().m_Enchantments.GetLevel(cEnchantments::enchLooting);
|
||||||
}
|
}
|
||||||
AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_LEATHER);
|
AddRandomDropItem(a_Drops, 0, 2 + LootingLevel, E_ITEM_LEATHER);
|
||||||
if (m_bIsSaddled)
|
if (IsSaddled())
|
||||||
{
|
{
|
||||||
a_Drops.push_back(cItem(E_ITEM_SADDLE, 1));
|
a_Drops.push_back(m_Saddle);
|
||||||
|
}
|
||||||
|
if (!m_Armor.IsEmpty())
|
||||||
|
{
|
||||||
|
a_Drops.push_back(m_Armor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,8 +283,24 @@ void cHorse::InStateIdle(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
|||||||
|
|
||||||
void cHorse::HandleSpeedFromAttachee(float a_Forward, float a_Sideways)
|
void cHorse::HandleSpeedFromAttachee(float a_Forward, float a_Sideways)
|
||||||
{
|
{
|
||||||
if ((m_bIsTame) && (m_bIsSaddled))
|
if ((m_bIsTame) && IsSaddled())
|
||||||
{
|
{
|
||||||
super::HandleSpeedFromAttachee(a_Forward * m_MaxSpeed, a_Sideways * m_MaxSpeed);
|
super::HandleSpeedFromAttachee(a_Forward * m_MaxSpeed, a_Sideways * m_MaxSpeed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cHorse::PlayerOpenWindow(cPlayer & a_Player)
|
||||||
|
{
|
||||||
|
auto Window = GetWindow();
|
||||||
|
if (Window == nullptr)
|
||||||
|
{
|
||||||
|
Window = new cHorseWindow(*this);
|
||||||
|
OpenWindow(Window);
|
||||||
|
}
|
||||||
|
|
||||||
|
a_Player.OpenWindow(*Window);
|
||||||
|
}
|
||||||
|
@ -2,18 +2,21 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "PassiveMonster.h"
|
#include "PassiveMonster.h"
|
||||||
|
#include "UI/WindowOwner.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class cHorse :
|
class cHorse :
|
||||||
public cPassiveMonster
|
public cPassiveMonster,
|
||||||
|
public cEntityWindowOwner
|
||||||
{
|
{
|
||||||
typedef cPassiveMonster super;
|
typedef cPassiveMonster super;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
cHorse(int Type, int Color, int Style, int TameTimes);
|
cHorse(int Type, int Color, int Style, int TameTimes);
|
||||||
|
virtual ~cHorse() override;
|
||||||
|
|
||||||
CLASS_PROTODEF(cHorse)
|
CLASS_PROTODEF(cHorse)
|
||||||
|
|
||||||
@ -23,7 +26,7 @@ public:
|
|||||||
virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
|
virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
|
||||||
virtual void OnRightClicked(cPlayer & a_Player) override;
|
virtual void OnRightClicked(cPlayer & a_Player) override;
|
||||||
|
|
||||||
bool IsSaddled (void) const {return m_bIsSaddled; }
|
bool IsSaddled (void) const {return !m_Saddle.IsEmpty(); }
|
||||||
bool IsChested (void) const {return m_bHasChest; }
|
bool IsChested (void) const {return m_bHasChest; }
|
||||||
bool IsEating (void) const {return m_bIsEating; }
|
bool IsEating (void) const {return m_bIsEating; }
|
||||||
bool IsRearing (void) const {return m_bIsRearing; }
|
bool IsRearing (void) const {return m_bIsRearing; }
|
||||||
@ -32,7 +35,18 @@ public:
|
|||||||
int GetHorseType (void) const {return m_Type; }
|
int GetHorseType (void) const {return m_Type; }
|
||||||
int GetHorseColor (void) const {return m_Color; }
|
int GetHorseColor (void) const {return m_Color; }
|
||||||
int GetHorseStyle (void) const {return m_Style; }
|
int GetHorseStyle (void) const {return m_Style; }
|
||||||
int GetHorseArmour (void) const {return m_Armour;}
|
int GetHorseArmour (void) const;
|
||||||
|
|
||||||
|
/** Set the horse's saddle to the given item.
|
||||||
|
@param a_SaddleItem should be either a saddle or empty. */
|
||||||
|
void SetHorseSaddle(cItem a_SaddleItem);
|
||||||
|
|
||||||
|
/** Set the horse's armor slot to the given item.
|
||||||
|
@param a_SaddleItem should be either a type of horse armor or empty. */
|
||||||
|
void SetHorseArmor(cItem a_ArmorItem);
|
||||||
|
|
||||||
|
const cItem & GetHorseSaddle() const { return m_Saddle; }
|
||||||
|
const cItem & GetHorseArmorItem() const { return m_Armor; }
|
||||||
|
|
||||||
virtual void GetBreedingItems(cItems & a_Items) override
|
virtual void GetBreedingItems(cItems & a_Items) override
|
||||||
{
|
{
|
||||||
@ -40,11 +54,15 @@ public:
|
|||||||
a_Items.Add(E_ITEM_GOLDEN_APPLE);
|
a_Items.Add(E_ITEM_GOLDEN_APPLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PlayerOpenWindow(cPlayer & a_Player);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
bool m_bHasChest, m_bIsEating, m_bIsRearing, m_bIsMouthOpen, m_bIsTame, m_bIsSaddled;
|
bool m_bHasChest, m_bIsEating, m_bIsRearing, m_bIsMouthOpen, m_bIsTame;
|
||||||
int m_Type, m_Color, m_Style, m_Armour, m_TimesToTame, m_TameAttemptTimes, m_RearTickCount;
|
int m_Type, m_Color, m_Style, m_TimesToTame, m_TameAttemptTimes, m_RearTickCount;
|
||||||
float m_MaxSpeed;
|
float m_MaxSpeed;
|
||||||
|
cItem m_Saddle;
|
||||||
|
cItem m_Armor;
|
||||||
|
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
@ -39,6 +39,7 @@ Implements the 1.8 protocol classes:
|
|||||||
|
|
||||||
#include "../Mobs/IncludeAllMonsters.h"
|
#include "../Mobs/IncludeAllMonsters.h"
|
||||||
#include "../UI/Window.h"
|
#include "../UI/Window.h"
|
||||||
|
#include "../UI/HorseWindow.h"
|
||||||
|
|
||||||
#include "../BlockEntities/BeaconEntity.h"
|
#include "../BlockEntities/BeaconEntity.h"
|
||||||
#include "../BlockEntities/CommandBlockEntity.h"
|
#include "../BlockEntities/CommandBlockEntity.h"
|
||||||
@ -1678,7 +1679,8 @@ void cProtocol_1_8_0::SendWindowOpen(const cWindow & a_Window)
|
|||||||
|
|
||||||
if (a_Window.GetWindowType() == cWindow::wtAnimalChest)
|
if (a_Window.GetWindowType() == cWindow::wtAnimalChest)
|
||||||
{
|
{
|
||||||
Pkt.WriteBEInt32(0); // TODO: The animal's EntityID
|
UInt32 HorseID = static_cast<const cHorseWindow &>(a_Window).GetHorseID();
|
||||||
|
Pkt.WriteBEInt32(static_cast<Int32>(HorseID));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2428,6 +2430,7 @@ void cProtocol_1_8_0::HandlePacketEntityAction(cByteBuffer & a_ByteBuffer)
|
|||||||
case 2: m_Client->HandleEntityLeaveBed(PlayerID); break; // Leave Bed
|
case 2: m_Client->HandleEntityLeaveBed(PlayerID); break; // Leave Bed
|
||||||
case 3: m_Client->HandleEntitySprinting(PlayerID, true); break; // Start sprinting
|
case 3: m_Client->HandleEntitySprinting(PlayerID, true); break; // Start sprinting
|
||||||
case 4: m_Client->HandleEntitySprinting(PlayerID, false); break; // Stop sprinting
|
case 4: m_Client->HandleEntitySprinting(PlayerID, false); break; // Stop sprinting
|
||||||
|
case 6: m_Client->HandleOpenHorseInventory(PlayerID); break; // Open horse inventory
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,6 +48,7 @@ Implements the 1.9 protocol classes:
|
|||||||
|
|
||||||
#include "../Mobs/IncludeAllMonsters.h"
|
#include "../Mobs/IncludeAllMonsters.h"
|
||||||
#include "../UI/Window.h"
|
#include "../UI/Window.h"
|
||||||
|
#include "../UI/HorseWindow.h"
|
||||||
|
|
||||||
#include "../BlockEntities/BeaconEntity.h"
|
#include "../BlockEntities/BeaconEntity.h"
|
||||||
#include "../BlockEntities/CommandBlockEntity.h"
|
#include "../BlockEntities/CommandBlockEntity.h"
|
||||||
@ -1723,7 +1724,8 @@ void cProtocol_1_9_0::SendWindowOpen(const cWindow & a_Window)
|
|||||||
|
|
||||||
if (a_Window.GetWindowType() == cWindow::wtAnimalChest)
|
if (a_Window.GetWindowType() == cWindow::wtAnimalChest)
|
||||||
{
|
{
|
||||||
Pkt.WriteBEInt32(0); // TODO: The animal's EntityID
|
UInt32 HorseID = static_cast<const cHorseWindow &>(a_Window).GetHorseID();
|
||||||
|
Pkt.WriteBEInt32(static_cast<Int32>(HorseID));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2517,6 +2519,7 @@ void cProtocol_1_9_0::HandlePacketEntityAction(cByteBuffer & a_ByteBuffer)
|
|||||||
case 2: m_Client->HandleEntityLeaveBed(PlayerID); break; // Leave Bed
|
case 2: m_Client->HandleEntityLeaveBed(PlayerID); break; // Leave Bed
|
||||||
case 3: m_Client->HandleEntitySprinting(PlayerID, true); break; // Start sprinting
|
case 3: m_Client->HandleEntitySprinting(PlayerID, true); break; // Start sprinting
|
||||||
case 4: m_Client->HandleEntitySprinting(PlayerID, false); break; // Stop sprinting
|
case 4: m_Client->HandleEntitySprinting(PlayerID, false); break; // Stop sprinting
|
||||||
|
case 7: m_Client->HandleOpenHorseInventory(PlayerID); break; // Open horse inventory
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ SET (SRCS
|
|||||||
EnderChestWindow.cpp
|
EnderChestWindow.cpp
|
||||||
FurnaceWindow.cpp
|
FurnaceWindow.cpp
|
||||||
HopperWindow.cpp
|
HopperWindow.cpp
|
||||||
|
HorseWindow.cpp
|
||||||
InventoryWindow.cpp)
|
InventoryWindow.cpp)
|
||||||
|
|
||||||
SET (HDRS
|
SET (HDRS
|
||||||
@ -30,6 +31,7 @@ SET (HDRS
|
|||||||
EnderChestWindow.h
|
EnderChestWindow.h
|
||||||
FurnaceWindow.h
|
FurnaceWindow.h
|
||||||
HopperWindow.h
|
HopperWindow.h
|
||||||
|
HorseWindow.h
|
||||||
InventoryWindow.h
|
InventoryWindow.h
|
||||||
MinecartWithChestWindow.h
|
MinecartWithChestWindow.h
|
||||||
WindowOwner.h)
|
WindowOwner.h)
|
||||||
|
61
src/UI/HorseWindow.cpp
Normal file
61
src/UI/HorseWindow.cpp
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
|
||||||
|
// HorseWindow.cpp
|
||||||
|
|
||||||
|
// Representing the UI window for a horse entity
|
||||||
|
|
||||||
|
#include "Globals.h"
|
||||||
|
#include "Mobs/Horse.h"
|
||||||
|
#include "UI/HorseWindow.h"
|
||||||
|
#include "UI/SlotArea.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cHorseWindow::cHorseWindow(cHorse & a_Horse):
|
||||||
|
Super(wtAnimalChest, "Horse"),
|
||||||
|
m_Horse(a_Horse)
|
||||||
|
{
|
||||||
|
m_SlotAreas.push_back(new cSlotAreaHorse(a_Horse, *this));
|
||||||
|
m_SlotAreas.push_back(new cSlotAreaInventory(*this));
|
||||||
|
m_SlotAreas.push_back(new cSlotAreaHotBar(*this));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cHorseWindow::DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply)
|
||||||
|
{
|
||||||
|
cSlotAreas AreasInOrder;
|
||||||
|
|
||||||
|
if (a_ClickedArea == m_SlotAreas[0])
|
||||||
|
{
|
||||||
|
// Horse Area
|
||||||
|
AreasInOrder.push_back(m_SlotAreas[2]); /* Hotbar */
|
||||||
|
AreasInOrder.push_back(m_SlotAreas[1]); /* Inventory */
|
||||||
|
Super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Inventory or Hotbar
|
||||||
|
if (ItemCategory::IsHorseArmor(a_ItemStack.m_ItemType) || (a_ItemStack.m_ItemType == E_ITEM_SADDLE))
|
||||||
|
{
|
||||||
|
AreasInOrder.push_back(m_SlotAreas[0]); /* Horse */
|
||||||
|
Super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
UInt32 cHorseWindow::GetHorseID() const
|
||||||
|
{
|
||||||
|
return m_Horse.GetUniqueID();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
34
src/UI/HorseWindow.h
Normal file
34
src/UI/HorseWindow.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
|
||||||
|
// HorseWindow.h
|
||||||
|
|
||||||
|
// Representing the UI window for a horse entity
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Window.h"
|
||||||
|
|
||||||
|
class cHorse;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class cHorseWindow :
|
||||||
|
public cWindow
|
||||||
|
{
|
||||||
|
using Super = cWindow;
|
||||||
|
public:
|
||||||
|
cHorseWindow(cHorse & a_Horse);
|
||||||
|
|
||||||
|
virtual void DistributeStack(cItem & a_ItemStack, int a_Slot, cPlayer & a_Player, cSlotArea * a_ClickedArea, bool a_ShouldApply) override;
|
||||||
|
|
||||||
|
/** Returns the horse's entity ID. */
|
||||||
|
UInt32 GetHorseID() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
cHorse & m_Horse;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -21,6 +21,7 @@
|
|||||||
#include "../BlockArea.h"
|
#include "../BlockArea.h"
|
||||||
#include "../EffectID.h"
|
#include "../EffectID.h"
|
||||||
#include "../ClientHandle.h"
|
#include "../ClientHandle.h"
|
||||||
|
#include "Mobs/Horse.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -2596,3 +2597,121 @@ cItem * cSlotAreaTemporary::GetPlayerSlots(cPlayer & a_Player)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// cSlotAreaHorse:
|
||||||
|
|
||||||
|
cSlotAreaHorse::cSlotAreaHorse(cHorse & a_Horse, cWindow & a_ParentWindow) :
|
||||||
|
cSlotArea(2, a_ParentWindow),
|
||||||
|
m_Horse(a_Horse)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cSlotAreaHorse::Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem)
|
||||||
|
{
|
||||||
|
cItem & DraggingItem = a_Player.GetDraggingItem();
|
||||||
|
|
||||||
|
switch (a_ClickAction)
|
||||||
|
{
|
||||||
|
case caLeftClick:
|
||||||
|
case caRightClick:
|
||||||
|
case caDblClick:
|
||||||
|
{
|
||||||
|
// Check for invalid item types
|
||||||
|
if (DraggingItem.IsEmpty())
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (a_SlotNum)
|
||||||
|
{
|
||||||
|
case SaddleSlot:
|
||||||
|
{
|
||||||
|
if (DraggingItem.m_ItemType != E_ITEM_SADDLE)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case ArmorSlot:
|
||||||
|
{
|
||||||
|
if (!ItemCategory::IsHorseArmor(DraggingItem.m_ItemType))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
cSlotArea::Clicked(a_Player, a_SlotNum, a_ClickAction, a_ClickedItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const cItem * cSlotAreaHorse::GetSlot(int a_SlotNum, cPlayer & a_Player) const
|
||||||
|
{
|
||||||
|
static const cItem InvalidItem;
|
||||||
|
switch (a_SlotNum)
|
||||||
|
{
|
||||||
|
case SaddleSlot: return &m_Horse.GetHorseSaddle();
|
||||||
|
case ArmorSlot: return &m_Horse.GetHorseArmorItem();
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
LOGWARN("cSlotAreaHorse::GetSlot: Invalid slot number %d", a_SlotNum);
|
||||||
|
return &InvalidItem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cSlotAreaHorse::SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem & a_Item)
|
||||||
|
{
|
||||||
|
switch (a_SlotNum)
|
||||||
|
{
|
||||||
|
case SaddleSlot: m_Horse.SetHorseSaddle(a_Item); break;
|
||||||
|
case ArmorSlot: m_Horse.SetHorseArmor(a_Item); break;
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
LOGWARN("cSlotAreaHorse::SetSlot: Invalid slot number %d", a_SlotNum);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cSlotAreaHorse::DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots, bool a_BackFill)
|
||||||
|
{
|
||||||
|
if (ItemCategory::IsHorseArmor(a_ItemStack.m_ItemType) && m_Horse.GetHorseArmorItem().IsEmpty())
|
||||||
|
{
|
||||||
|
if (a_ShouldApply)
|
||||||
|
{
|
||||||
|
m_Horse.SetHorseArmor(a_ItemStack.CopyOne());
|
||||||
|
}
|
||||||
|
--a_ItemStack.m_ItemCount;
|
||||||
|
}
|
||||||
|
else if ((a_ItemStack.m_ItemType == E_ITEM_SADDLE) && !m_Horse.IsSaddled())
|
||||||
|
{
|
||||||
|
if (a_ShouldApply)
|
||||||
|
{
|
||||||
|
m_Horse.SetHorseSaddle(a_ItemStack.CopyOne());
|
||||||
|
}
|
||||||
|
--a_ItemStack.m_ItemCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class cHorse;
|
||||||
class cWindow;
|
class cWindow;
|
||||||
class cPlayer;
|
class cPlayer;
|
||||||
class cBeaconEntity;
|
class cBeaconEntity;
|
||||||
@ -520,3 +521,27 @@ protected:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** Slot area holding horse saddle and armor. */
|
||||||
|
class cSlotAreaHorse:
|
||||||
|
public cSlotArea
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
SaddleSlot,
|
||||||
|
ArmorSlot
|
||||||
|
};
|
||||||
|
|
||||||
|
cSlotAreaHorse(cHorse & a_Horse, cWindow & a_ParentWindow);
|
||||||
|
virtual void Clicked(cPlayer & a_Player, int a_SlotNum, eClickAction a_ClickAction, const cItem & a_ClickedItem) override;
|
||||||
|
virtual const cItem * GetSlot(int a_SlotNum, cPlayer & a_Player) const override;
|
||||||
|
virtual void SetSlot(int a_SlotNum, cPlayer & a_Player, const cItem & a_Item) override;
|
||||||
|
virtual void DistributeStack(cItem & a_ItemStack, cPlayer & a_Player, bool a_ShouldApply, bool a_KeepEmptySlots, bool a_BackFill) override;
|
||||||
|
private:
|
||||||
|
cHorse & m_Horse;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user