diff options
Diffstat (limited to 'src/Entities')
-rw-r--r-- | src/Entities/Entity.h | 4 | ||||
-rw-r--r-- | src/Entities/ExpOrb.cpp | 7 | ||||
-rw-r--r-- | src/Entities/ItemFrame.cpp | 124 | ||||
-rw-r--r-- | src/Entities/ItemFrame.h | 42 | ||||
-rw-r--r-- | src/Entities/Painting.cpp | 43 | ||||
-rw-r--r-- | src/Entities/Painting.h | 42 | ||||
-rw-r--r-- | src/Entities/Player.cpp | 17 | ||||
-rw-r--r-- | src/Entities/Player.h | 4 | ||||
-rw-r--r-- | src/Entities/ProjectileEntity.cpp | 1 |
9 files changed, 279 insertions, 5 deletions
diff --git a/src/Entities/Entity.h b/src/Entities/Entity.h index b2edfc2b4..b3b1cef83 100644 --- a/src/Entities/Entity.h +++ b/src/Entities/Entity.h @@ -81,6 +81,8 @@ public: etProjectile, etExpOrb, etFloater, + etItemFrame, + etPainting, // Common variations etMob = etMonster, // DEPRECATED, use etMonster instead! @@ -139,6 +141,8 @@ public: bool IsProjectile (void) const { return (m_EntityType == etProjectile); } bool IsExpOrb (void) const { return (m_EntityType == etExpOrb); } bool IsFloater (void) const { return (m_EntityType == etFloater); } + bool IsItemFrame (void) const { return (m_EntityType == etItemFrame); } + bool IsPainting (void) const { return (m_EntityType == etPainting); } /// Returns true if the entity is of the specified class or a subclass (cPawn's IsA("cEntity") returns true) virtual bool IsA(const char * a_ClassName) const; diff --git a/src/Entities/ExpOrb.cpp b/src/Entities/ExpOrb.cpp index 04ee85823..3398f1c7b 100644 --- a/src/Entities/ExpOrb.cpp +++ b/src/Entities/ExpOrb.cpp @@ -51,7 +51,10 @@ void cExpOrb::Tick(float a_Dt, cChunk & a_Chunk) { LOGD("Player %s picked up an ExpOrb. His reward is %i", a_ClosestPlayer->GetName().c_str(), m_Reward); a_ClosestPlayer->DeltaExperience(m_Reward); - Destroy(true); + + m_World->BroadcastSoundEffect("random.orb", (int)GetPosX() * 8, (int)GetPosY() * 8, (int)GetPosZ() * 8, 0.5f, (float)(0.75 + ((float)((GetUniqueID() * 23) % 32)) / 64)); + + Destroy(); } a_Distance.Normalize(); a_Distance *= ((float) (5.5 - Distance)); @@ -61,4 +64,4 @@ void cExpOrb::Tick(float a_Dt, cChunk & a_Chunk) BroadcastMovementUpdate(); } HandlePhysics(a_Dt, a_Chunk); -}
\ No newline at end of file +} diff --git a/src/Entities/ItemFrame.cpp b/src/Entities/ItemFrame.cpp new file mode 100644 index 000000000..8cfa5e18d --- /dev/null +++ b/src/Entities/ItemFrame.cpp @@ -0,0 +1,124 @@ + +#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules + +#include "ItemFrame.h" +#include "ClientHandle.h" +#include "Player.h" + + + + + +cItemFrame::cItemFrame(eBlockFace a_BlockFace, double a_X, double a_Y, double a_Z) + : cEntity(etItemFrame, a_X, a_Y, a_Z, 0.8, 0.8), + m_BlockFace(a_BlockFace), + m_Item(E_BLOCK_AIR), + m_Rotation(0) +{ + SetMaxHealth(1); + SetHealth(1); +} + + + + + +void cItemFrame::SpawnOn(cClientHandle & a_ClientHandle) +{ + int Dir = 0; + + // The client uses different values for item frame directions and block faces. Our constants are for the block faces, so we convert them here to item frame faces + switch (m_BlockFace) + { + case BLOCK_FACE_ZP: break; // Initialised to zero + case BLOCK_FACE_ZM: Dir = 2; break; + case BLOCK_FACE_XM: Dir = 1; break; + case BLOCK_FACE_XP: Dir = 3; break; + default: ASSERT(!"Unhandled block face when trying to spawn item frame!"); return; + } + + if ((Dir == 0) || (Dir == 2)) // Probably a client bug, but two directions are flipped and contrary to the norm, so we do -180 + { + SetYaw((Dir * 90) - 180); + } + else + { + SetYaw(Dir * 90); + } + + a_ClientHandle.SendSpawnObject(*this, 71, Dir, (Byte)GetYaw(), (Byte)GetPitch()); +} + + + + + +void cItemFrame::OnRightClicked(cPlayer & a_Player) +{ + if (!m_Item.IsEmpty()) + { + // Item not empty, rotate, clipping values to zero to three inclusive + m_Rotation++; + if (m_Rotation >= 4) + { + m_Rotation = 0; + } + } + else if (!a_Player.GetEquippedItem().IsEmpty()) + { + // Item empty, and player held item not empty - add this item to self + m_Item = a_Player.GetEquippedItem(); + m_Item.m_ItemCount = 1; + + if (!a_Player.IsGameModeCreative()) + { + a_Player.GetInventory().RemoveOneEquippedItem(); + } + } + + GetWorld()->BroadcastEntityMetadata(*this); // Update clients +} + + + + + + +void cItemFrame::KilledBy(cEntity * a_Killer) +{ + if (m_Item.IsEmpty()) + { + super::KilledBy(a_Killer); + Destroy(); + return; + } + + if ((a_Killer != NULL) && a_Killer->IsPlayer() && !((cPlayer *)a_Killer)->IsGameModeCreative()) + { + cItems Item; + Item.push_back(m_Item); + + GetWorld()->SpawnItemPickups(Item, GetPosX(), GetPosY(), GetPosZ()); + } + + SetHealth(GetMaxHealth()); + m_Item.Clear(); + m_Rotation = 0; + GetWorld()->BroadcastEntityMetadata(*this); +} + + + + + +void cItemFrame::GetDrops(cItems & a_Items, cEntity * a_Killer) +{ + if ((a_Killer != NULL) && a_Killer->IsPlayer() && !((cPlayer *)a_Killer)->IsGameModeCreative()) + { + a_Items.push_back(cItem(E_ITEM_ITEM_FRAME)); + } +} + + + + diff --git a/src/Entities/ItemFrame.h b/src/Entities/ItemFrame.h new file mode 100644 index 000000000..43915e3f9 --- /dev/null +++ b/src/Entities/ItemFrame.h @@ -0,0 +1,42 @@ + +#pragma once + +#include "Entity.h" + + + + + +// tolua_begin +class cItemFrame : + public cEntity +{ + // tolua_end + typedef cEntity super; + +public: + + CLASS_PROTODEF(cItemFrame); + + cItemFrame(eBlockFace a_BlockFace, double a_X, double a_Y, double a_Z); + + const cItem & GetItem(void) { return m_Item; } + Byte GetRotation(void) const { return m_Rotation; } + +private: + + virtual void SpawnOn(cClientHandle & a_ClientHandle) override; + virtual void OnRightClicked(cPlayer & a_Player) override; + virtual void Tick(float a_Dt, cChunk & a_Chunk) override {}; + virtual void KilledBy(cEntity * a_Killer) override; + virtual void GetDrops(cItems & a_Items, cEntity * a_Killer) override; + + eBlockFace m_BlockFace; + cItem m_Item; + Byte m_Rotation; + +}; // tolua_export + + + + diff --git a/src/Entities/Painting.cpp b/src/Entities/Painting.cpp new file mode 100644 index 000000000..b98c1e67a --- /dev/null +++ b/src/Entities/Painting.cpp @@ -0,0 +1,43 @@ + +#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules + +#include "Painting.h" +#include "ClientHandle.h" +#include "Player.h" + + + + + +cPainting::cPainting(const AString & a_Name, int a_Direction, double a_X, double a_Y, double a_Z) + : cEntity(etPainting, a_X, a_Y, a_Z, 1, 1), + m_Name(a_Name), + m_Direction(a_Direction) +{ +} + + + + + + +void cPainting::SpawnOn(cClientHandle & a_Client) +{ + a_Client.SendPaintingSpawn(*this); +} + + + + + +void cPainting::GetDrops(cItems & a_Items, cEntity * a_Killer) +{ + if ((a_Killer != NULL) && a_Killer->IsPlayer() && !((cPlayer *)a_Killer)->IsGameModeCreative()) + { + a_Items.push_back(cItem(E_ITEM_PAINTING)); + } +} + + + + diff --git a/src/Entities/Painting.h b/src/Entities/Painting.h new file mode 100644 index 000000000..95afbed1e --- /dev/null +++ b/src/Entities/Painting.h @@ -0,0 +1,42 @@ + +#pragma once + +#include "Entity.h" + + + + + +// tolua_begin +class cPainting : + public cEntity +{ + // tolua_end + typedef cEntity super; + +public: + CLASS_PROTODEF(cPainting); + + cPainting(const AString & a_Name, int a_Direction, double a_X, double a_Y, double a_Z); + const AString & GetName(void) const { return m_Name; } // tolua_export + int GetDirection(void) const { return m_Direction; } // tolua_export + +private: + + virtual void SpawnOn(cClientHandle & a_Client) override; + virtual void Tick(float a_Dt, cChunk & a_Chunk) override {}; + virtual void GetDrops(cItems & a_Items, cEntity * a_Killer) override; + virtual void KilledBy(cEntity * a_Killer) override + { + super::KilledBy(a_Killer); + Destroy(); + } + + AString m_Name; + int m_Direction; + +}; // tolua_export + + + + diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index fdf8d4303..0152bfc5b 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -842,6 +842,12 @@ void cPlayer::KilledBy(cEntity * a_Killer) cItems Pickups; m_Inventory.CopyToItems(Pickups); m_Inventory.Clear(); + + if (GetName() == "Notch") + { + Pickups.Add(cItem(E_ITEM_RED_APPLE)); + } + m_World->SpawnItemPickups(Pickups, GetPosX(), GetPosY(), GetPosZ(), 10); SaveToDisk(); // Save it, yeah the world is a tough place ! @@ -1125,8 +1131,9 @@ void cPlayer::SetIP(const AString & a_IP) void cPlayer::TeleportToCoords(double a_PosX, double a_PosY, double a_PosZ) { - SetPosition( a_PosX, a_PosY, a_PosZ ); + SetPosition(a_PosX, a_PosY, a_PosZ); m_LastGroundHeight = (float)a_PosY; + m_LastJumpHeight = (float)a_PosY; m_World->BroadcastTeleportEntity(*this, GetClientHandle()); m_ClientHandle->SendPlayerMoveLook(); @@ -1760,6 +1767,12 @@ void cPlayer::HandleFood(void) { // Ref.: http://www.minecraftwiki.net/wiki/Hunger + if (IsGameModeCreative()) + { + // Hunger is disabled for Creative + return; + } + // Remember the food level before processing, for later comparison int LastFoodLevel = m_FoodLevel; @@ -1777,7 +1790,7 @@ void cPlayer::HandleFood(void) Heal(1); m_FoodExhaustionLevel += 3; } - else if (m_FoodLevel <= 0) + else if ((m_FoodLevel <= 0) && (m_Health > 1)) { // Damage from starving TakeDamage(dtStarving, NULL, 1, 1, 0); diff --git a/src/Entities/Player.h b/src/Entities/Player.h index 7db9544cb..a795bb9eb 100644 --- a/src/Entities/Player.h +++ b/src/Entities/Player.h @@ -203,6 +203,7 @@ public: void SendMessageWarning (const AString & a_Message) { m_ClientHandle->SendChat(a_Message, mtWarning); } void SendMessageFatal (const AString & a_Message) { m_ClientHandle->SendChat(a_Message, mtFailure); } void SendMessagePrivateMsg(const AString & a_Message, const AString & a_Sender) { m_ClientHandle->SendChat(a_Message, mtPrivateMessage, a_Sender); } + void SendMessage (const cCompositeChat & a_Message) { m_ClientHandle->SendChat(a_Message); } const AString & GetName(void) const { return m_PlayerName; } void SetName(const AString & a_Name) { m_PlayerName = a_Name; } @@ -225,7 +226,8 @@ public: // tolua_begin - /// Returns the full color code to use for this player, based on their primary group or set in m_Color + /** Returns the full color code to use for this player, based on their primary group or set in m_Color. + The returned value includes the cChatColor::Delimiter. */ AString GetColor(void) const; /** tosses the item in the selected hotbar slot */ diff --git a/src/Entities/ProjectileEntity.cpp b/src/Entities/ProjectileEntity.cpp index a3fa9d557..ef82c6e94 100644 --- a/src/Entities/ProjectileEntity.cpp +++ b/src/Entities/ProjectileEntity.cpp @@ -680,6 +680,7 @@ super(pkExpBottle, a_Creator, a_X, a_Y, a_Z, 0.25, 0.25) void cExpBottleEntity::OnHitSolidBlock(const Vector3d & a_HitPos, eBlockFace a_HitFace) { // Spawn an experience orb with a reward between 3 and 11. + m_World->BroadcastSoundParticleEffect(2002, POSX_TOINT, POSY_TOINT, POSZ_TOINT, 0); m_World->SpawnExperienceOrb(GetPosX(), GetPosY(), GetPosZ(), 3 + m_World->GetTickRandomNumber(8)); Destroy(); |