From 0fe1e50ffc744d861744e4aa4905e1b4b15e10fd Mon Sep 17 00:00:00 2001 From: andrew Date: Tue, 25 Mar 2014 10:32:58 +0200 Subject: Protocol: Wither metadata --- src/Blocks/BlockMobHead.h | 82 ++++++++++++++++++++++++++++++++++++++++++-- src/Mobs/Wither.cpp | 16 +++++++++ src/Mobs/Wither.h | 3 ++ src/Protocol/Protocol125.cpp | 8 +++++ src/Protocol/Protocol17x.cpp | 10 ++++++ 5 files changed, 116 insertions(+), 3 deletions(-) diff --git a/src/Blocks/BlockMobHead.h b/src/Blocks/BlockMobHead.h index 6aa01f986..9935c2496 100644 --- a/src/Blocks/BlockMobHead.h +++ b/src/Blocks/BlockMobHead.h @@ -22,14 +22,90 @@ public: a_Pickups.push_back(cItem(E_ITEM_HEAD, 1, 0)); } - bool TrySpawnWither(cChunkInterface & a_ChunkInterface, int a_BlockX, int a_BlockY, int a_BlockZ) + bool TrySpawnWither(cChunkInterface & a_ChunkInterface, cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ) { if (a_BlockY < 2) { return false; } + + class cCallback : public cMobHeadCallback + { + bool m_IsWither; + + virtual bool Item (cMobHeadEntity * a_MobHeadEntity) + { + m_IsWither = (a_MobHeadEntity->GetType() == SKULL_TYPE_WITHER); + + return false; + } + + public: + cCallback () : m_IsWither(false) {} + + bool IsWither(void) const { return m_IsWither; } + + void Reset(void) { m_IsWither = false; } + } CallbackA, CallbackB; + + BLOCKTYPE BlockY1 = a_ChunkInterface.GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ); + BLOCKTYPE BlockY2 = a_ChunkInterface.GetBlock(a_BlockX, a_BlockY - 2, a_BlockZ); + + if ((BlockY1 != E_BLOCK_SOULSAND) || (BlockY2 != E_BLOCK_SOULSAND)) + { + return false; + } - // TODO 2014-03-24 xdot + a_World->DoWithMobHeadAt(a_BlockX - 1, a_BlockY, a_BlockZ, CallbackA); + a_World->DoWithMobHeadAt(a_BlockX + 1, a_BlockY, a_BlockZ, CallbackB); + + BLOCKTYPE Block1 = a_ChunkInterface.GetBlock(a_BlockX - 1, a_BlockY - 1, a_BlockZ); + BLOCKTYPE Block2 = a_ChunkInterface.GetBlock(a_BlockX + 1, a_BlockY - 1, a_BlockZ); + + if ((Block1 == E_BLOCK_SOULSAND) && (Block2 == E_BLOCK_SOULSAND) && CallbackA.IsWither() && CallbackB.IsWither()) + { + a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY - 1, a_BlockZ, E_BLOCK_AIR, 0); + a_ChunkInterface.FastSetBlock(a_BlockX + 1, a_BlockY - 1, a_BlockZ, E_BLOCK_AIR, 0); + a_ChunkInterface.FastSetBlock(a_BlockX - 1, a_BlockY - 1, a_BlockZ, E_BLOCK_AIR, 0); + a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY - 2, a_BlockZ, E_BLOCK_AIR, 0); + + // Block entities + a_World->SetBlock(a_BlockX + 1, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0); + a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0); + a_World->SetBlock(a_BlockX - 1, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0); + + // Spawn the wither: + a_World->SpawnMob(a_BlockX + 0.5, a_BlockY - 2, a_BlockZ + 0.5, cMonster::mtWither); + + return true; + } + + CallbackA.Reset(); + CallbackB.Reset(); + + a_World->DoWithMobHeadAt(a_BlockX, a_BlockY, a_BlockZ - 1, CallbackA); + a_World->DoWithMobHeadAt(a_BlockX, a_BlockY, a_BlockZ + 1, CallbackB); + + Block1 = a_ChunkInterface.GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ - 1); + Block2 = a_ChunkInterface.GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ + 1); + + if ((Block1 == E_BLOCK_SOULSAND) && (Block2 == E_BLOCK_SOULSAND) && CallbackA.IsWither() && CallbackB.IsWither()) + { + a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY - 1, a_BlockZ, E_BLOCK_AIR, 0); + a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY - 1, a_BlockZ + 1, E_BLOCK_AIR, 0); + a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY - 1, a_BlockZ - 1, E_BLOCK_AIR, 0); + a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY - 2, a_BlockZ, E_BLOCK_AIR, 0); + + // Block entities + a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ + 1, E_BLOCK_AIR, 0); + a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0); + a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ - 1, E_BLOCK_AIR, 0); + + // Spawn the wither: + a_World->SpawnMob(a_BlockX + 0.5, a_BlockY - 2, a_BlockZ + 0.5, cMonster::mtWither); + + return true; + } return false; } @@ -75,7 +151,7 @@ public: World->DoWithMobHeadAt(a_BlockX, a_BlockY, a_BlockZ, Callback); a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, a_BlockMeta); - TrySpawnWither(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ); + TrySpawnWither(a_ChunkInterface, World, a_BlockX, a_BlockY, a_BlockZ); } } ; diff --git a/src/Mobs/Wither.cpp b/src/Mobs/Wither.cpp index 0e42194ac..790f127f2 100644 --- a/src/Mobs/Wither.cpp +++ b/src/Mobs/Wither.cpp @@ -21,6 +21,15 @@ cWither::cWither(void) : +bool cWither::IsArmored(void) const +{ + return GetHealth() <= (GetMaxHealth() / 2); +} + + + + + void cWither::DoTakeDamage(TakeDamageInfo & a_TDI) { if (a_TDI.DamageType == dtDrowning) @@ -33,6 +42,11 @@ void cWither::DoTakeDamage(TakeDamageInfo & a_TDI) return; } + if (IsArmored() && (a_TDI.DamageType == dtRangedAttack)) + { + return; + } + super::DoTakeDamage(a_TDI); } @@ -60,6 +74,8 @@ void cWither::Tick(float a_Dt, cChunk & a_Chunk) Heal(10); } } + + m_World->BroadcastEntityMetadata(*this); } diff --git a/src/Mobs/Wither.h b/src/Mobs/Wither.h index d09e3607a..52666a190 100644 --- a/src/Mobs/Wither.h +++ b/src/Mobs/Wither.h @@ -20,6 +20,9 @@ public: unsigned int GetNumInvulnerableTicks(void) const { return m_InvulnerableTicks; } void SetNumInvulnerableTicks(unsigned int a_Ticks) { m_InvulnerableTicks = a_Ticks; } + + /** Returns whether the wither is invulnerable to arrows. */ + bool IsArmored(void) const; // cEntity overrides virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; diff --git a/src/Protocol/Protocol125.cpp b/src/Protocol/Protocol125.cpp index 69f4934d8..d8b340350 100644 --- a/src/Protocol/Protocol125.cpp +++ b/src/Protocol/Protocol125.cpp @@ -1972,6 +1972,14 @@ void cProtocol125::WriteMobMetadata(const cMonster & a_Mob) WriteByte(((const cWitch &)a_Mob).IsAngry() ? 1 : 0); // Aggravated? Doesn't seem to do anything break; } + case cMonster::mtWither: + { + WriteByte(0x54); // Int at index 20 + WriteInt(((const cWither &)a_Mob).GetNumInvulnerableTicks()); + WriteByte(0x66); // Float at index 6 + WriteFloat((float)(a_Mob.GetHealth())); + break; + } case cMonster::mtSlime: case cMonster::mtMagmaCube: { diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp index 721ed349e..c678fc9a0 100644 --- a/src/Protocol/Protocol17x.cpp +++ b/src/Protocol/Protocol17x.cpp @@ -2535,6 +2535,7 @@ void cProtocol172::cPacketizer::WriteEntityMetadata(const cEntity & a_Entity) WriteByte(Frame.GetRotation()); break; } + default: break; } } @@ -2659,6 +2660,15 @@ void cProtocol172::cPacketizer::WriteMobMetadata(const cMonster & a_Mob) WriteByte(((const cWitch &)a_Mob).IsAngry() ? 1 : 0); break; } + + case cMonster::mtWither: + { + WriteByte(0x54); // Int at index 20 + WriteInt(((const cWither &)a_Mob).GetNumInvulnerableTicks()); + WriteByte(0x66); // Float at index 6 + WriteFloat((float)(a_Mob.GetHealth())); + break; + } case cMonster::mtSlime: { -- cgit v1.2.3 From ba4216641120ec2f49464ed0b136af3198d48f89 Mon Sep 17 00:00:00 2001 From: andrew Date: Tue, 25 Mar 2014 11:13:27 +0200 Subject: Fixed wither summoning --- src/Blocks/BlockMobHead.h | 25 ++++++++++++++++++++++++- src/Mobs/Wither.cpp | 14 ++++++++++++-- src/Mobs/Wither.h | 1 + 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/src/Blocks/BlockMobHead.h b/src/Blocks/BlockMobHead.h index 9935c2496..693240898 100644 --- a/src/Blocks/BlockMobHead.h +++ b/src/Blocks/BlockMobHead.h @@ -47,6 +47,15 @@ public: void Reset(void) { m_IsWither = false; } } CallbackA, CallbackB; + + a_World->DoWithMobHeadAt(a_BlockX, a_BlockY, a_BlockZ, CallbackA); + + if (!CallbackA.IsWither()) + { + return false; + } + + CallbackA.Reset(); BLOCKTYPE BlockY1 = a_ChunkInterface.GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ); BLOCKTYPE BlockY2 = a_ChunkInterface.GetBlock(a_BlockX, a_BlockY - 2, a_BlockZ); @@ -151,7 +160,21 @@ public: World->DoWithMobHeadAt(a_BlockX, a_BlockY, a_BlockZ, Callback); a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, a_BlockMeta); - TrySpawnWither(a_ChunkInterface, World, a_BlockX, a_BlockY, a_BlockZ); + static const Vector3i Coords[] = + { + Vector3i( 0, 0, 0), + Vector3i( 1, 0, 0), + Vector3i(-1, 0, 0), + Vector3i( 0, 0, 1), + Vector3i( 0, 0, -1), + }; + for (size_t i = 0; i < ARRAYCOUNT(Coords); ++i) + { + if (TrySpawnWither(a_ChunkInterface, World, a_BlockX + Coords[i].x, a_BlockY, a_BlockZ + Coords[i].z)) + { + break; + } + } // for i - Coords[] } } ; diff --git a/src/Mobs/Wither.cpp b/src/Mobs/Wither.cpp index 790f127f2..39dc6aab9 100644 --- a/src/Mobs/Wither.cpp +++ b/src/Mobs/Wither.cpp @@ -13,8 +13,6 @@ cWither::cWither(void) : m_InvulnerableTicks(220) { SetMaxHealth(300); - - SetHealth(GetMaxHealth() / 3); } @@ -30,6 +28,18 @@ bool cWither::IsArmored(void) const +bool cWither::Initialize(cWorld * a_World) override +{ + // Set health before BroadcastSpawnEntity() + SetHealth(GetMaxHealth() / 3); + + return super::Initialize(a_World); +} + + + + + void cWither::DoTakeDamage(TakeDamageInfo & a_TDI) { if (a_TDI.DamageType == dtDrowning) diff --git a/src/Mobs/Wither.h b/src/Mobs/Wither.h index 52666a190..bc78bfaad 100644 --- a/src/Mobs/Wither.h +++ b/src/Mobs/Wither.h @@ -25,6 +25,7 @@ public: bool IsArmored(void) const; // cEntity overrides + virtual bool Initialize(cWorld * a_World) override; virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; virtual void DoTakeDamage(TakeDamageInfo & a_TDI) override; virtual void Tick(float a_Dt, cChunk & a_Chunk) override; -- cgit v1.2.3 From c8445cd93479d4729a180b21df1783449ce01b7e Mon Sep 17 00:00:00 2001 From: andrew Date: Tue, 25 Mar 2014 11:40:54 +0200 Subject: Fixed clang compilation --- src/Blocks/BlockMobHead.h | 29 ++++++++++++++++------------- src/Mobs/Wither.cpp | 2 +- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/Blocks/BlockMobHead.h b/src/Blocks/BlockMobHead.h index 693240898..e172cee69 100644 --- a/src/Blocks/BlockMobHead.h +++ b/src/Blocks/BlockMobHead.h @@ -160,21 +160,24 @@ public: World->DoWithMobHeadAt(a_BlockX, a_BlockY, a_BlockZ, Callback); a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, a_BlockMeta); - static const Vector3i Coords[] = + if (a_BlockMeta == SKULL_TYPE_WITHER) { - Vector3i( 0, 0, 0), - Vector3i( 1, 0, 0), - Vector3i(-1, 0, 0), - Vector3i( 0, 0, 1), - Vector3i( 0, 0, -1), - }; - for (size_t i = 0; i < ARRAYCOUNT(Coords); ++i) - { - if (TrySpawnWither(a_ChunkInterface, World, a_BlockX + Coords[i].x, a_BlockY, a_BlockZ + Coords[i].z)) + static const Vector3i Coords[] = { - break; - } - } // for i - Coords[] + Vector3i( 0, 0, 0), + Vector3i( 1, 0, 0), + Vector3i(-1, 0, 0), + Vector3i( 0, 0, 1), + Vector3i( 0, 0, -1), + }; + for (size_t i = 0; i < ARRAYCOUNT(Coords); ++i) + { + if (TrySpawnWither(a_ChunkInterface, World, a_BlockX + Coords[i].x, a_BlockY, a_BlockZ + Coords[i].z)) + { + break; + } + } // for i - Coords[] + } } } ; diff --git a/src/Mobs/Wither.cpp b/src/Mobs/Wither.cpp index 39dc6aab9..8f5d28b68 100644 --- a/src/Mobs/Wither.cpp +++ b/src/Mobs/Wither.cpp @@ -28,7 +28,7 @@ bool cWither::IsArmored(void) const -bool cWither::Initialize(cWorld * a_World) override +bool cWither::Initialize(cWorld * a_World) { // Set health before BroadcastSpawnEntity() SetHealth(GetMaxHealth() / 3); -- cgit v1.2.3