From 4fe7801cfccbfa6f5a42ac2eb919287ef98ea611 Mon Sep 17 00:00:00 2001 From: "madmaxoft@gmail.com" Date: Tue, 25 Jun 2013 06:36:59 +0000 Subject: [PATCH] Unified the way mobs are spawned (egg vs natural). Fixed deadlocks in mob moving. Fixed mob destroying code. Should fix FS #400 and partially fix FS #381 git-svn-id: http://mc-server.googlecode.com/svn/trunk@1626 0a769ca7-a7f5-676a-18bf-c427514a06d6 --- source/Chunk.cpp | 2 +- source/Entity.cpp | 8 +++-- source/Entity.h | 3 +- source/FallingBlock.cpp | 6 ++-- source/Mobs/Monster.cpp | 9 ++++-- source/Pickup.cpp | 8 ++--- source/TNTEntity.cpp | 2 +- source/World.cpp | 72 ++++++++++++++++++----------------------- 8 files changed, 55 insertions(+), 55 deletions(-) diff --git a/source/Chunk.cpp b/source/Chunk.cpp index 7816f2adc..049a4944d 100644 --- a/source/Chunk.cpp +++ b/source/Chunk.cpp @@ -123,7 +123,7 @@ cChunk::~cChunk() { if (!(*itr)->IsPlayer()) { - (*itr)->Destroy(); + (*itr)->Destroy(false); delete *itr; } } diff --git a/source/Entity.cpp b/source/Entity.cpp index 082e1e925..bc68ec3b2 100644 --- a/source/Entity.cpp +++ b/source/Entity.cpp @@ -173,13 +173,17 @@ void cEntity::WrapSpeed(void) -void cEntity::Destroy(void) +void cEntity::Destroy(bool a_ShouldBroadcast) { if (!m_IsInitialized) { return; } - m_World->BroadcastDestroyEntity(*this); + + if (a_ShouldBroadcast) + { + m_World->BroadcastDestroyEntity(*this); + } m_IsInitialized = false; diff --git a/source/Entity.h b/source/Entity.h index 49a7a5b0d..a756d064b 100644 --- a/source/Entity.h +++ b/source/Entity.h @@ -161,7 +161,8 @@ public: inline int GetUniqueID(void) const { return m_UniqueID; } inline bool IsDestroyed(void) const { return !m_IsInitialized; } - void Destroy(void); + /// Schedules the entity for destroying; if a_ShouldBroadcast is set to true, broadcasts the DestroyEntity packet + void Destroy(bool a_ShouldBroadcast = true); // tolua_end diff --git a/source/FallingBlock.cpp b/source/FallingBlock.cpp index f20abe3ba..0da00e29f 100644 --- a/source/FallingBlock.cpp +++ b/source/FallingBlock.cpp @@ -58,7 +58,7 @@ void cFallingBlock::Tick(float a_Dt, cChunk & a_Chunk) // Fallen out of this world, just continue falling until out of sight, then destroy: if (BlockY < 100) { - Destroy(); + Destroy(true); } return; } @@ -77,7 +77,7 @@ void cFallingBlock::Tick(float a_Dt, cChunk & a_Chunk) // Fallen onto a block that breaks this into pickups (e. g. half-slab) // Must finish the fall with coords one below the block: cSandSimulator::FinishFalling(m_World, BlockX, BlockY, BlockZ, m_BlockType, m_BlockMeta); - Destroy(); + Destroy(true); return; } else if (!cSandSimulator::CanContinueFallThrough(BlockBelow)) @@ -93,7 +93,7 @@ void cFallingBlock::Tick(float a_Dt, cChunk & a_Chunk) */ cSandSimulator::FinishFalling(m_World, BlockX, BlockY + 1, BlockZ, m_BlockType, m_BlockMeta); - Destroy(); + Destroy(true); return; } } diff --git a/source/Mobs/Monster.cpp b/source/Mobs/Monster.cpp index 232143579..0176175e9 100644 --- a/source/Mobs/Monster.cpp +++ b/source/Mobs/Monster.cpp @@ -95,7 +95,7 @@ void cMonster::Tick(float a_Dt, cChunk & a_Chunk) m_DestroyTimer += a_Dt / 1000; if (m_DestroyTimer > 1) { - Destroy(); + Destroy(true); } return; } @@ -134,7 +134,12 @@ void cMonster::Tick(float a_Dt, cChunk & a_Chunk) { Vector3f NormSpeed = Vector3f(GetSpeed()).NormalizeCopy(); Vector3f NextBlock = Vector3f( GetPosition() ) + NormSpeed; - double NextHeight = (double)GetWorld()->GetHeight( (int)NextBlock.x, (int)NextBlock.z ); + int NextHeight; + if (!m_World->TryGetHeight((int)NextBlock.x, (int)NextBlock.z, NextHeight)) + { + // The chunk at NextBlock is not loaded + return; + } if( NextHeight > (GetPosY() - 1.0) && (NextHeight - GetPosY()) < 2.5 ) { m_bOnGround = false; diff --git a/source/Pickup.cpp b/source/Pickup.cpp index 19959efa3..6d0f0aa0e 100644 --- a/source/Pickup.cpp +++ b/source/Pickup.cpp @@ -93,7 +93,7 @@ void cPickup::Tick(float a_Dt, cChunk & a_Chunk) m_Timer += a_Dt; // In case we have to destroy the pickup in the same tick. if (m_Timer > 500.f) { - Destroy(); + Destroy(true); return; } } @@ -104,20 +104,20 @@ void cPickup::Tick(float a_Dt, cChunk & a_Chunk) { if (m_Timer > 500.f) // 0.5 second { - Destroy(); + Destroy(true); return; } } if (m_Timer > 1000 * 60 * 5) // 5 minutes { - Destroy(); + Destroy(true); return; } if (GetPosY() < -8) // Out of this world and no more visible! { - Destroy(); + Destroy(true); return; } } diff --git a/source/TNTEntity.cpp b/source/TNTEntity.cpp index 32850e246..53981eee7 100644 --- a/source/TNTEntity.cpp +++ b/source/TNTEntity.cpp @@ -60,7 +60,7 @@ void cTNTEntity::Tick(float a_Dt, cChunk & a_Chunk) m_Counter += delta_time; if (m_Counter > m_MaxFuseTime) // Check if we go KABOOOM { - Destroy(); + Destroy(true); LOGD("BOOM at {%f,%f,%f}", GetPosX(), GetPosY(), GetPosZ()); m_World->DoExplosiontAt(4.0, (int)floor(GetPosX()), (int)floor(GetPosY()), (int)floor(GetPosZ())); return; diff --git a/source/World.cpp b/source/World.cpp index 39dd17c17..569e2e4f9 100644 --- a/source/World.cpp +++ b/source/World.cpp @@ -621,65 +621,55 @@ void cWorld::TickSpawnMobs(float a_Dt) SpawnPos = (*itr)->GetPosition(); } - cMonster * Monster = NULL; - int dayRand = m_TickRand.randInt() % 6; - int nightRand = m_TickRand.randInt() % 10; + int dayRand = (m_TickRand.randInt() / 7) % 6; + int nightRand = (m_TickRand.randInt() / 11) % 10; SpawnPos += Vector3d((double)(m_TickRand.randInt() % 64) - 32, (double)(m_TickRand.randInt() % 64) - 32, (double)(m_TickRand.randInt() % 64) - 32); int Height = GetHeight((int)SpawnPos.x, (int)SpawnPos.z); + int MobType = -1; if (m_TimeOfDay >= 12000 + 1000) { if (GetBiomeAt((int)SpawnPos.x, (int)SpawnPos.z) == biHell) // Spawn nether mobs { - if (nightRand == 1) - Monster = new cZombie(); - else if (nightRand == 5) - Monster = new cGhast(); - else if (nightRand == 6) - Monster = new cZombiepigman(); + switch (nightRand) + { + case 1: MobType = E_ENTITY_TYPE_ZOMBIE; break; // _X 2013_06_25: Really? Zombies in the Nether? + case 5: MobType = E_ENTITY_TYPE_GHAST; break; + case 6: MobType = E_ENTITY_TYPE_ZOMBIE_PIGMAN; break; + } } else { - if (nightRand == 0) //random percent to spawn for night - Monster = new cSpider(); - else if (nightRand == 2) - Monster = new cEnderman(); - else if (nightRand == 3) - Monster = new cCreeper(); - else if (nightRand == 4) - Monster = new cCavespider(); - else if (nightRand == 7) - Monster = new cSlime(); - else if (nightRand == 8) - Monster = new cSilverfish(); - else if (nightRand == 9) - Monster = new cSkeleton(); + switch (nightRand) + { + case 0: MobType = E_ENTITY_TYPE_SPIDER; break; + case 2: MobType = E_ENTITY_TYPE_ENDERMAN; break; + case 3: MobType = E_ENTITY_TYPE_CREEPER; break; + case 4: MobType = E_ENTITY_TYPE_CAVE_SPIDER; break; + case 7: MobType = E_ENTITY_TYPE_SLIME; break; + case 8: MobType = E_ENTITY_TYPE_SILVERFISH; break; + case 9: MobType = E_ENTITY_TYPE_SKELETON; break; + } } - //end random percent to spawn for night } else { - if (dayRand == 0) //random percent to spawn for day - Monster = new cChicken(); - else if (dayRand == 1) - Monster = new cCow(); - else if (dayRand == 2) - Monster = new cPig(); - else if (dayRand == 3) - Monster = new cSheep(); - else if (dayRand == 4) - Monster = new cSquid(); - else if (dayRand == 5) - Monster = new cWolf(); - //end random percent to spawn for day + switch (dayRand) + { + case 0: MobType = E_ENTITY_TYPE_CHICKEN; break; + case 1: MobType = E_ENTITY_TYPE_COW; break; + case 2: MobType = E_ENTITY_TYPE_PIG; break; + case 3: MobType = E_ENTITY_TYPE_SHEEP; break; + case 4: MobType = E_ENTITY_TYPE_SQUID; break; + case 5: MobType = E_ENTITY_TYPE_WOLF; break; + } } - if (Monster) + if (MobType >= 0) { - Monster->Initialize(this); - Monster->TeleportTo(SpawnPos.x, (double)(Height) + 2, SpawnPos.z); - BroadcastSpawn(*Monster); + // A proper mob type was selected, now spawn the mob: + SpawnMob(SpawnPos.x, SpawnPos.y, SpawnPos.z, MobType); } }