diff options
Diffstat (limited to 'src/BlockEntities')
-rw-r--r-- | src/BlockEntities/BeaconEntity.cpp | 60 | ||||
-rw-r--r-- | src/BlockEntities/ChestEntity.cpp | 28 | ||||
-rw-r--r-- | src/BlockEntities/HopperEntity.cpp | 21 | ||||
-rw-r--r-- | src/BlockEntities/MobSpawnerEntity.cpp | 41 |
4 files changed, 107 insertions, 43 deletions
diff --git a/src/BlockEntities/BeaconEntity.cpp b/src/BlockEntities/BeaconEntity.cpp index 1d088a56f..a98547ba7 100644 --- a/src/BlockEntities/BeaconEntity.cpp +++ b/src/BlockEntities/BeaconEntity.cpp @@ -1,4 +1,4 @@ - + #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "BeaconEntity.h" @@ -195,21 +195,33 @@ void cBeaconEntity::UpdateBeacon(void) GetWindow()->SetProperty(0, m_BeaconLevel); } - Vector3d BeaconPosition(m_PosX, m_PosY, m_PosZ); - GetWorld()->ForEachPlayer([=](cPlayer & a_Player) + class cPlayerCallback : + public cPlayerListCallback + { + public: + cPlayerCallback(Vector3d a_Position): + m_Position(a_Position) { - Vector3d Distance = BeaconPosition - a_Player.GetPosition(); + } + + virtual bool Item(cPlayer * a_Player) + { + Vector3d Distance = m_Position - a_Player->GetPosition(); if ( (std::abs(Distance.y) <= 14) && (std::abs(Distance.x) <= 20) && (std::abs(Distance.z) <= 20) ) { - a_Player.AwardAchievement(eStatistic::achFullBeacon); + a_Player->AwardAchievement(eStatistic::achFullBeacon); } return false; } - ); + + private: + Vector3d m_Position; + } PlayerCallback(Vector3d(m_PosX, m_PosY, m_PosZ)); + GetWorld()->ForEachPlayer(PlayerCallback); } } @@ -237,28 +249,46 @@ void cBeaconEntity::GiveEffects(void) SecondaryEffect = m_SecondaryEffect; } - Vector3d BeaconPosition(m_PosX, m_PosY, m_PosZ); - GetWorld()->ForEachPlayer([=](cPlayer & a_Player) + class cPlayerCallback : public cPlayerListCallback + { + int m_Radius; + Vector3d m_Position; + cEntityEffect::eType m_PrimaryEffect, m_SecondaryEffect; + short m_EffectLevel; + + virtual bool Item(cPlayer * a_Player) { - auto PlayerPosition = a_Player.GetPosition(); - if (PlayerPosition.y > BeaconPosition.y) + Vector3d PlayerPosition = Vector3d(a_Player->GetPosition()); + if (PlayerPosition.y > m_Position.y) { - PlayerPosition.y = BeaconPosition.y; + PlayerPosition.y = m_Position.y; } // TODO: Vanilla minecraft uses an AABB check instead of a radius one - if ((PlayerPosition - BeaconPosition).Length() <= Radius) + if ((PlayerPosition - m_Position).Length() <= m_Radius) { - a_Player.AddEntityEffect(m_PrimaryEffect, 180, EffectLevel); + a_Player->AddEntityEffect(m_PrimaryEffect, 180, m_EffectLevel); if (m_SecondaryEffect != cEntityEffect::effNoEffect) { - a_Player.AddEntityEffect(m_SecondaryEffect, 180, 0); + a_Player->AddEntityEffect(m_SecondaryEffect, 180, 0); } } return false; } - ); + + public: + cPlayerCallback(int a_Radius, Vector3d a_Position, cEntityEffect::eType a_PrimaryEffect, cEntityEffect::eType a_SecondaryEffect, short a_EffectLevel): + m_Radius(a_Radius), + m_Position(a_Position), + m_PrimaryEffect(a_PrimaryEffect), + m_SecondaryEffect(a_SecondaryEffect), + m_EffectLevel(a_EffectLevel) + { + } + + } PlayerCallback(Radius, Vector3d(m_PosX, m_PosY, m_PosZ), m_PrimaryEffect, SecondaryEffect, EffectLevel); + GetWorld()->ForEachPlayer(PlayerCallback); } diff --git a/src/BlockEntities/ChestEntity.cpp b/src/BlockEntities/ChestEntity.cpp index 5e8b29a45..a8f5b7242 100644 --- a/src/BlockEntities/ChestEntity.cpp +++ b/src/BlockEntities/ChestEntity.cpp @@ -138,18 +138,33 @@ bool cChestEntity::UsedBy(cPlayer * a_Player) void cChestEntity::ScanNeighbours() { // Callback for finding neighbouring chest: - auto FindNeighbour = [this](cChestEntity & a_Chest) + class cFindNeighbour : + public cChestCallback { - if (a_Chest.GetBlockType() != m_BlockType) + public: + cChestEntity * m_Neighbour; + BLOCKTYPE m_ChestType; + + cFindNeighbour(BLOCKTYPE a_ChestType) : + m_Neighbour(nullptr), + m_ChestType(a_ChestType) { - // Neighboring block is not the same type of chest - return true; } - m_Neighbour = &a_Chest; - return false; + + virtual bool Item(cChestEntity * a_Chest) override + { + if (a_Chest->GetBlockType() != m_ChestType) + { + // Neighboring block is not the same type of chest + return true; + } + m_Neighbour = a_Chest; + return false; + } }; // Scan horizontally adjacent blocks for any neighbouring chest of the same type: + cFindNeighbour FindNeighbour(m_BlockType); if ( m_World->DoWithChestAt(m_PosX - 1, m_PosY, m_PosZ, FindNeighbour) || m_World->DoWithChestAt(m_PosX + 1, m_PosY, m_PosZ, FindNeighbour) || @@ -157,6 +172,7 @@ void cChestEntity::ScanNeighbours() m_World->DoWithChestAt(m_PosX, m_PosY, m_PosZ + 1, FindNeighbour) ) { + m_Neighbour = FindNeighbour.m_Neighbour; m_Neighbour->m_Neighbour = this; // Force neighbour's window shut. Does Mojang server do this or should a double window open? m_Neighbour->DestroyWindow(); diff --git a/src/BlockEntities/HopperEntity.cpp b/src/BlockEntities/HopperEntity.cpp index 2fac188b1..0467685af 100644 --- a/src/BlockEntities/HopperEntity.cpp +++ b/src/BlockEntities/HopperEntity.cpp @@ -193,7 +193,8 @@ bool cHopperEntity::MovePickupsIn(cChunk & a_Chunk, Int64 a_CurrentTick) { UNUSED(a_CurrentTick); - class cHopperPickupSearchCallback + class cHopperPickupSearchCallback : + public cEntityCallback { public: cHopperPickupSearchCallback(const Vector3i & a_Pos, cItemGrid & a_Contents) : @@ -203,20 +204,22 @@ bool cHopperEntity::MovePickupsIn(cChunk & a_Chunk, Int64 a_CurrentTick) { } - bool operator () (cEntity & a_Entity) + virtual bool Item(cEntity * a_Entity) override { - if (!a_Entity.IsPickup()) + ASSERT(a_Entity != nullptr); + + if (!a_Entity->IsPickup()) { return false; } - Vector3f EntityPos = a_Entity.GetPosition(); + Vector3f EntityPos = a_Entity->GetPosition(); Vector3f BlockPos(m_Pos.x + 0.5f, static_cast<float>(m_Pos.y) + 1, m_Pos.z + 0.5f); // One block above hopper, and search from center outwards double Distance = (EntityPos - BlockPos).Length(); if (Distance < 0.5) { - if (TrySuckPickupIn(static_cast<cPickup &>(a_Entity))) + if (TrySuckPickupIn(static_cast<cPickup *>(a_Entity))) { return false; } @@ -225,9 +228,9 @@ bool cHopperEntity::MovePickupsIn(cChunk & a_Chunk, Int64 a_CurrentTick) return false; } - bool TrySuckPickupIn(cPickup & a_Pickup) + bool TrySuckPickupIn(cPickup * a_Pickup) { - cItem & Item = a_Pickup.GetItem(); + cItem & Item = a_Pickup->GetItem(); for (int i = 0; i < ContentsWidth * ContentsHeight; i++) { @@ -235,7 +238,7 @@ bool cHopperEntity::MovePickupsIn(cChunk & a_Chunk, Int64 a_CurrentTick) { m_bFoundPickupsAbove = true; m_Contents.SetSlot(i, Item); - a_Pickup.Destroy(); // Kill pickup + a_Pickup->Destroy(); // Kill pickup return true; } @@ -249,7 +252,7 @@ bool cHopperEntity::MovePickupsIn(cChunk & a_Chunk, Int64 a_CurrentTick) if (Item.IsEmpty()) { - a_Pickup.Destroy(); // Kill pickup if all items were added + a_Pickup->Destroy(); // Kill pickup if all items were added } return true; } diff --git a/src/BlockEntities/MobSpawnerEntity.cpp b/src/BlockEntities/MobSpawnerEntity.cpp index 8a4cc4d38..5246ae6ca 100644 --- a/src/BlockEntities/MobSpawnerEntity.cpp +++ b/src/BlockEntities/MobSpawnerEntity.cpp @@ -1,4 +1,4 @@ - + #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "MobSpawnerEntity.h" @@ -138,36 +138,47 @@ void cMobSpawnerEntity::SpawnEntity(void) return; } - auto MobType = m_Entity; - bool EntitiesSpawned = m_World->DoWithChunk(GetChunkX(), GetChunkZ(), [&](cChunk & a_Chunk) + class cCallback : public cChunkCallback + { + public: + cCallback(int a_RelX, int a_RelY, int a_RelZ, eMonsterType a_MobType, int a_NearbyEntitiesNum) : + m_RelX(a_RelX), + m_RelY(a_RelY), + m_RelZ(a_RelZ), + m_MobType(a_MobType), + m_NearbyEntitiesNum(a_NearbyEntitiesNum) + { + } + + virtual bool Item(cChunk * a_Chunk) { auto & Random = GetRandomProvider(); - bool HaveSpawnedEntity = false; + bool EntitiesSpawned = false; for (size_t i = 0; i < 4; i++) { - if (NearbyEntities >= 6) + if (m_NearbyEntitiesNum >= 6) { break; } int RelX = m_RelX + static_cast<int>((Random.RandReal<double>() - Random.RandReal<double>()) * 4.0); - int RelY = m_PosY + Random.RandInt(-1, 1); + int RelY = m_RelY + Random.RandInt(-1, 1); int RelZ = m_RelZ + static_cast<int>((Random.RandReal<double>() - Random.RandReal<double>()) * 4.0); - cChunk * Chunk = a_Chunk.GetRelNeighborChunkAdjustCoords(RelX, RelZ); + cChunk * Chunk = a_Chunk->GetRelNeighborChunkAdjustCoords(RelX, RelZ); if ((Chunk == nullptr) || !Chunk->IsValid()) { continue; } EMCSBiome Biome = Chunk->GetBiomeAt(RelX, RelZ); - if (cMobSpawner::CanSpawnHere(Chunk, RelX, RelY, RelZ, MobType, Biome)) + if (cMobSpawner::CanSpawnHere(Chunk, RelX, RelY, RelZ, m_MobType, Biome)) { double PosX = Chunk->GetPosX() * cChunkDef::Width + RelX; double PosZ = Chunk->GetPosZ() * cChunkDef::Width + RelZ; - auto Monster = cMonster::NewMonsterFromType(MobType); + auto Monster = cMonster::NewMonsterFromType(m_MobType); if (Monster == nullptr) { continue; @@ -177,7 +188,7 @@ void cMobSpawnerEntity::SpawnEntity(void) Monster->SetYaw(Random.RandReal(360.0f)); if (Chunk->GetWorld()->SpawnMobFinalize(std::move(Monster)) != cEntity::INVALID_ID) { - HaveSpawnedEntity = true; + EntitiesSpawned = true; Chunk->BroadcastSoundParticleEffect( EffectID::PARTICLE_MOBSPAWN, static_cast<int>(PosX * 8.0), @@ -185,15 +196,19 @@ void cMobSpawnerEntity::SpawnEntity(void) static_cast<int>(PosZ * 8.0), 0 ); - NearbyEntities++; + m_NearbyEntitiesNum++; } } } return EntitiesSpawned; } - ); + protected: + int m_RelX, m_RelY, m_RelZ; + eMonsterType m_MobType; + int m_NearbyEntitiesNum; + } Callback(m_RelX, m_PosY, m_RelZ, m_Entity, NearbyEntities); - if (EntitiesSpawned) + if (m_World->DoWithChunk(GetChunkX(), GetChunkZ(), Callback)) { ResetTimer(); } |