summaryrefslogtreecommitdiffstats
path: root/src/BlockEntities
diff options
context:
space:
mode:
Diffstat (limited to 'src/BlockEntities')
-rw-r--r--src/BlockEntities/BeaconEntity.h10
-rw-r--r--src/BlockEntities/BlockEntity.cpp6
-rw-r--r--src/BlockEntities/BlockEntity.h7
-rw-r--r--src/BlockEntities/CMakeLists.txt2
-rw-r--r--src/BlockEntities/ChestEntity.h5
-rw-r--r--src/BlockEntities/CommandBlockEntity.h8
-rw-r--r--src/BlockEntities/DropSpenserEntity.h4
-rw-r--r--src/BlockEntities/FlowerPotEntity.h10
-rw-r--r--src/BlockEntities/FurnaceEntity.h5
-rw-r--r--src/BlockEntities/JukeboxEntity.h9
-rw-r--r--src/BlockEntities/MobHeadEntity.h20
-rw-r--r--src/BlockEntities/MobSpawnerEntity.cpp290
-rw-r--r--src/BlockEntities/MobSpawnerEntity.h71
-rw-r--r--src/BlockEntities/NoteEntity.h6
-rw-r--r--src/BlockEntities/SignEntity.h9
15 files changed, 375 insertions, 87 deletions
diff --git a/src/BlockEntities/BeaconEntity.h b/src/BlockEntities/BeaconEntity.h
index 0417e0464..bc27e92b0 100644
--- a/src/BlockEntities/BeaconEntity.h
+++ b/src/BlockEntities/BeaconEntity.h
@@ -1,3 +1,4 @@
+
// BeaconEntity.h
// Declares the cBeaconEntity class representing a single beacon in the world
@@ -14,15 +15,6 @@
-namespace Json
-{
- class Value;
-}
-
-
-
-
-
// tolua_begin
class cBeaconEntity :
public cBlockEntityWithItems
diff --git a/src/BlockEntities/BlockEntity.cpp b/src/BlockEntities/BlockEntity.cpp
index 3d96e891e..346970cd2 100644
--- a/src/BlockEntities/BlockEntity.cpp
+++ b/src/BlockEntities/BlockEntity.cpp
@@ -14,10 +14,11 @@
#include "FlowerPotEntity.h"
#include "FurnaceEntity.h"
#include "HopperEntity.h"
+#include "MobHeadEntity.h"
+#include "MobSpawnerEntity.h"
#include "JukeboxEntity.h"
#include "NoteEntity.h"
#include "SignEntity.h"
-#include "MobHeadEntity.h"
@@ -35,8 +36,9 @@ cBlockEntity * cBlockEntity::CreateByBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE
case E_BLOCK_ENDER_CHEST: return new cEnderChestEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
case E_BLOCK_FLOWER_POT: return new cFlowerPotEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
case E_BLOCK_FURNACE: return new cFurnaceEntity (a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, a_World);
- case E_BLOCK_HEAD: return new cMobHeadEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
case E_BLOCK_HOPPER: return new cHopperEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
+ case E_BLOCK_HEAD: return new cMobHeadEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
+ case E_BLOCK_MOB_SPAWNER: return new cMobSpawnerEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
case E_BLOCK_JUKEBOX: return new cJukeboxEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
case E_BLOCK_LIT_FURNACE: return new cFurnaceEntity (a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, a_World);
case E_BLOCK_SIGN_POST: return new cSignEntity (a_BlockType, a_BlockX, a_BlockY, a_BlockZ, a_World);
diff --git a/src/BlockEntities/BlockEntity.h b/src/BlockEntities/BlockEntity.h
index ffd6ee856..056a88721 100644
--- a/src/BlockEntities/BlockEntity.h
+++ b/src/BlockEntities/BlockEntity.h
@@ -28,11 +28,6 @@
-namespace Json
-{
- class Value;
-};
-
class cChunk;
class cPlayer;
class cWorld;
@@ -115,7 +110,7 @@ public:
virtual void SendTo(cClientHandle & a_Client) = 0;
/// Ticks the entity; returns true if the chunk should be marked as dirty as a result of this ticking. By default does nothing.
- virtual bool Tick(float a_Dt, cChunk & /* a_Chunk */)
+ virtual bool Tick(float a_Dt, cChunk & a_Chunk)
{
UNUSED(a_Dt);
return false;
diff --git a/src/BlockEntities/CMakeLists.txt b/src/BlockEntities/CMakeLists.txt
index d87594b0d..5f4af288d 100644
--- a/src/BlockEntities/CMakeLists.txt
+++ b/src/BlockEntities/CMakeLists.txt
@@ -18,6 +18,7 @@ SET (SRCS
HopperEntity.cpp
JukeboxEntity.cpp
MobHeadEntity.cpp
+ MobSpawnerEntity.cpp
NoteEntity.cpp
SignEntity.cpp)
@@ -36,6 +37,7 @@ SET (HDRS
HopperEntity.h
JukeboxEntity.h
MobHeadEntity.h
+ MobSpawnerEntity.h
NoteEntity.h
SignEntity.h)
diff --git a/src/BlockEntities/ChestEntity.h b/src/BlockEntities/ChestEntity.h
index 5ab0a4800..645dbf4bc 100644
--- a/src/BlockEntities/ChestEntity.h
+++ b/src/BlockEntities/ChestEntity.h
@@ -7,11 +7,6 @@
-namespace Json
-{
- class Value;
-};
-
class cClientHandle;
diff --git a/src/BlockEntities/CommandBlockEntity.h b/src/BlockEntities/CommandBlockEntity.h
index 8deff6964..d8ac054f0 100644
--- a/src/BlockEntities/CommandBlockEntity.h
+++ b/src/BlockEntities/CommandBlockEntity.h
@@ -15,14 +15,6 @@
-namespace Json
-{
- class Value;
-}
-
-
-
-
// tolua_begin
diff --git a/src/BlockEntities/DropSpenserEntity.h b/src/BlockEntities/DropSpenserEntity.h
index 9092bc077..6c23a402f 100644
--- a/src/BlockEntities/DropSpenserEntity.h
+++ b/src/BlockEntities/DropSpenserEntity.h
@@ -16,10 +16,6 @@
-namespace Json
-{
- class Value;
-}
class cClientHandle;
diff --git a/src/BlockEntities/FlowerPotEntity.h b/src/BlockEntities/FlowerPotEntity.h
index 005a3841a..a4246bb7d 100644
--- a/src/BlockEntities/FlowerPotEntity.h
+++ b/src/BlockEntities/FlowerPotEntity.h
@@ -15,16 +15,6 @@
-
-namespace Json
-{
- class Value;
-}
-
-
-
-
-
// tolua_begin
class cFlowerPotEntity :
diff --git a/src/BlockEntities/FurnaceEntity.h b/src/BlockEntities/FurnaceEntity.h
index 1ad812d8b..fbe9d6c75 100644
--- a/src/BlockEntities/FurnaceEntity.h
+++ b/src/BlockEntities/FurnaceEntity.h
@@ -8,11 +8,6 @@
-namespace Json
-{
- class Value;
-}
-
class cClientHandle;
diff --git a/src/BlockEntities/JukeboxEntity.h b/src/BlockEntities/JukeboxEntity.h
index 301d018d1..000f7d87e 100644
--- a/src/BlockEntities/JukeboxEntity.h
+++ b/src/BlockEntities/JukeboxEntity.h
@@ -7,15 +7,6 @@
-namespace Json
-{
- class Value;
-}
-
-
-
-
-
// tolua_begin
class cJukeboxEntity :
diff --git a/src/BlockEntities/MobHeadEntity.h b/src/BlockEntities/MobHeadEntity.h
index de033fd16..7f08c5ab2 100644
--- a/src/BlockEntities/MobHeadEntity.h
+++ b/src/BlockEntities/MobHeadEntity.h
@@ -14,14 +14,6 @@
-namespace Json
-{
- class Value;
-}
-
-
-
-
// tolua_begin
@@ -41,22 +33,22 @@ public:
// tolua_begin
- /** Set the Type */
+ /** Set the type of the mob head */
void SetType(const eMobHeadType & a_SkullType);
- /** Set the Rotation */
+ /** Set the rotation of the mob head */
void SetRotation(eMobHeadRotation a_Rotation);
- /** Set the Player Name for Mobheads with Player type */
+ /** Set the player name for mob heads with player type */
void SetOwner(const AString & a_Owner);
- /** Get the Type */
+ /** Returns the type of the mob head */
eMobHeadType GetType(void) const { return m_Type; }
- /** Get the Rotation */
+ /** Returns the rotation of the mob head */
eMobHeadRotation GetRotation(void) const { return m_Rotation; }
- /** Get the setted Player Name */
+ /** Returns the player name of the mob head */
AString GetOwner(void) const { return m_Owner; }
// tolua_end
diff --git a/src/BlockEntities/MobSpawnerEntity.cpp b/src/BlockEntities/MobSpawnerEntity.cpp
new file mode 100644
index 000000000..26499972d
--- /dev/null
+++ b/src/BlockEntities/MobSpawnerEntity.cpp
@@ -0,0 +1,290 @@
+
+#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
+
+#include "MobSpawnerEntity.h"
+
+#include "../World.h"
+#include "../FastRandom.h"
+#include "../MobSpawner.h"
+#include "../Items/ItemSpawnEgg.h"
+
+
+
+
+
+cMobSpawnerEntity::cMobSpawnerEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World)
+ : super(E_BLOCK_MOB_SPAWNER, a_BlockX, a_BlockY, a_BlockZ, a_World)
+ , m_Entity(mtPig)
+ , m_SpawnDelay(100)
+ , m_IsActive(false)
+{
+}
+
+
+
+
+
+void cMobSpawnerEntity::SendTo(cClientHandle & a_Client)
+{
+ a_Client.SendUpdateBlockEntity(*this);
+}
+
+
+
+
+
+void cMobSpawnerEntity::UsedBy(cPlayer * a_Player)
+{
+ if (a_Player->GetEquippedItem().m_ItemType == E_ITEM_SPAWN_EGG)
+ {
+ eMonsterType MonsterType = cItemSpawnEggHandler::ItemDamageToMonsterType(a_Player->GetEquippedItem().m_ItemDamage);
+ if (MonsterType == eMonsterType::mtInvalidType)
+ {
+ return;
+ }
+
+ m_Entity = MonsterType;
+ ResetTimer();
+ if (!a_Player->IsGameModeCreative())
+ {
+ a_Player->GetInventory().RemoveOneEquippedItem();
+ }
+ LOGD("Changed monster spawner at {%d, %d, %d} to type %s.", GetPosX(), GetPosY(), GetPosZ(), cMonster::MobTypeToString(MonsterType).c_str());
+ }
+}
+
+
+
+
+
+void cMobSpawnerEntity::UpdateActiveState(void)
+{
+ if (GetNearbyPlayersNum() > 0)
+ {
+ m_IsActive = true;
+ }
+ else
+ {
+ m_IsActive = false;
+ }
+}
+
+
+
+
+
+bool cMobSpawnerEntity::Tick(float a_Dt, cChunk & a_Chunk)
+{
+ // Update the active flag every 5 seconds
+ if ((m_World->GetWorldAge() % 100) == 0)
+ {
+ UpdateActiveState();
+ }
+
+ if (!m_IsActive)
+ {
+ return false;
+ }
+
+ if (m_SpawnDelay <= 0)
+ {
+ SpawnEntity();
+ return true;
+ }
+ else
+ {
+ m_SpawnDelay--;
+ }
+ return false;
+}
+
+
+
+
+
+void cMobSpawnerEntity::ResetTimer(void)
+{
+ m_SpawnDelay = (short) (200 + m_World->GetTickRandomNumber(600));
+ m_World->BroadcastBlockEntity(m_PosX, m_PosY, m_PosZ);
+}
+
+
+
+
+
+void cMobSpawnerEntity::SpawnEntity(void)
+{
+ int NearbyEntities = GetNearbyMonsterNum(m_Entity);
+ if (NearbyEntities >= 6)
+ {
+ ResetTimer();
+ return;
+ }
+
+ 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)
+ {
+ cFastRandom Random;
+
+ bool EntitiesSpawned = false;
+ for (size_t i = 0; i < 4; i++)
+ {
+ if (m_NearbyEntitiesNum >= 6)
+ {
+ break;
+ }
+
+ int RelX = (int) (m_RelX + (double)(Random.NextFloat() - Random.NextFloat()) * 4.0);
+ int RelY = m_RelY + Random.NextInt(3) - 1;
+ int RelZ = (int) (m_RelZ + (double)(Random.NextFloat() - Random.NextFloat()) * 4.0);
+
+ cChunk * Chunk = a_Chunk->GetRelNeighborChunkAdjustCoords(RelX, RelZ);
+ if ((Chunk == NULL) || !Chunk->IsValid())
+ {
+ continue;
+ }
+ EMCSBiome Biome = Chunk->GetBiomeAt(RelX, RelZ);
+
+ if (cMobSpawner::CanSpawnHere(Chunk, RelX, RelY, RelZ, m_MobType, Biome))
+ {
+ double PosX = Chunk->GetPosX() * cChunkDef::Width + RelX;
+ double PosZ = Chunk->GetPosZ() * cChunkDef::Width + RelZ;
+
+ cMonster * Monster = cMonster::NewMonsterFromType(m_MobType);
+ if (Monster == NULL)
+ {
+ continue;
+ }
+
+ Monster->SetPosition(PosX, RelY, PosZ);
+ Monster->SetYaw(Random.NextFloat() * 360.0f);
+ if (Chunk->GetWorld()->SpawnMobFinalize(Monster) != mtInvalidType)
+ {
+ EntitiesSpawned = true;
+ Chunk->BroadcastSoundParticleEffect(2004, (int)(PosX * 8.0), (int)(RelY * 8.0), (int)(PosZ * 8.0), 0);
+ 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 (m_World->DoWithChunk(GetChunkX(), GetChunkZ(), Callback))
+ {
+ ResetTimer();
+ }
+}
+
+
+
+
+
+int cMobSpawnerEntity::GetNearbyPlayersNum(void)
+{
+ Vector3d SpawnerPos(m_PosX + 0.5, m_PosY + 0.5, m_PosZ + 0.5);
+ int NumPlayers = 0;
+
+ class cCallback : public cChunkDataCallback
+ {
+ public:
+ cCallback(Vector3d a_SpawnerPos, int & a_NumPlayers) :
+ m_SpawnerPos(a_SpawnerPos),
+ m_NumPlayers(a_NumPlayers)
+ {
+ }
+
+ virtual void Entity(cEntity * a_Entity) override
+ {
+ if (!a_Entity->IsPlayer())
+ {
+ return;
+ }
+
+ if ((m_SpawnerPos - a_Entity->GetPosition()).Length() <= 16)
+ {
+ m_NumPlayers++;
+ }
+ }
+
+ protected:
+ Vector3d m_SpawnerPos;
+ int & m_NumPlayers;
+ } Callback(SpawnerPos, NumPlayers);
+
+ int ChunkX = GetChunkX();
+ int ChunkZ = GetChunkZ();
+ m_World->ForEachChunkInRect(ChunkX - 1, ChunkX + 1, ChunkZ - 1, ChunkZ + 1, Callback);
+
+ return NumPlayers;
+}
+
+
+
+
+
+int cMobSpawnerEntity::GetNearbyMonsterNum(eMonsterType a_EntityType)
+{
+ Vector3d SpawnerPos(m_PosX + 0.5, m_PosY + 0.5, m_PosZ + 0.5);
+ int NumEntities = 0;
+
+ class cCallback : public cChunkDataCallback
+ {
+ public:
+ cCallback(Vector3d a_SpawnerPos, eMonsterType a_EntityType, int & a_NumEntities) :
+ m_SpawnerPos(a_SpawnerPos),
+ m_EntityType(a_EntityType),
+ m_NumEntities(a_NumEntities)
+ {
+ }
+
+ virtual void Entity(cEntity * a_Entity) override
+ {
+ if (!a_Entity->IsMob())
+ {
+ return;
+ }
+
+ cMonster * Mob = (cMonster *)a_Entity;
+ if (Mob->GetMobType() != m_EntityType)
+ {
+ return;
+ }
+
+ if (((m_SpawnerPos - a_Entity->GetPosition()).Length() <= 8) && (Diff(m_SpawnerPos.y, a_Entity->GetPosY()) <= 4.0))
+ {
+ m_NumEntities++;
+ }
+ }
+
+ protected:
+ Vector3d m_SpawnerPos;
+ eMonsterType m_EntityType;
+ int & m_NumEntities;
+ } Callback(SpawnerPos, a_EntityType, NumEntities);
+
+ int ChunkX = GetChunkX();
+ int ChunkZ = GetChunkZ();
+ m_World->ForEachChunkInRect(ChunkX - 1, ChunkX + 1, ChunkZ - 1, ChunkZ + 1, Callback);
+
+ return NumEntities;
+}
+
+
+
+
diff --git a/src/BlockEntities/MobSpawnerEntity.h b/src/BlockEntities/MobSpawnerEntity.h
new file mode 100644
index 000000000..0a3367c97
--- /dev/null
+++ b/src/BlockEntities/MobSpawnerEntity.h
@@ -0,0 +1,71 @@
+
+#pragma once
+
+#include "BlockEntity.h"
+#include "../Entities/Player.h"
+
+
+
+
+
+// tolua_begin
+
+class cMobSpawnerEntity :
+ public cBlockEntity
+{
+ typedef cBlockEntity super;
+public:
+
+ // tolua_end
+
+ cMobSpawnerEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World);
+
+ virtual void SendTo(cClientHandle & a_Client) override;
+ virtual void UsedBy(cPlayer * a_Player) override;
+ virtual bool Tick(float a_Dt, cChunk & a_Chunk) override;
+
+ // tolua_begin
+
+ /** Upate the active flag from the mob spawner. This function will called every 5 seconds from the Tick() function. */
+ void UpdateActiveState(void);
+
+ /** Sets the spawn delay to a new random value. */
+ void ResetTimer(void);
+
+ /** Spawns the entity. This function automaticly change the spawn delay! */
+ void SpawnEntity(void);
+
+ /** Returns the entity type that will be spawn by this mob spawner. */
+ eMonsterType GetEntity(void) const { return m_Entity; }
+
+ /** Sets the entity type who will be spawn by this mob spawner. */
+ void SetEntity(eMonsterType a_EntityType) { m_Entity = a_EntityType; }
+
+ /** Returns the spawn delay. This is the tick delay that is needed to spawn new monsters. */
+ short GetSpawnDelay(void) const { return m_SpawnDelay; }
+
+ /** Sets the spawn delay. */
+ void SetSpawnDelay(short a_Delay) { m_SpawnDelay = a_Delay; }
+
+ /** Returns the amount of the nearby players in a 16-block radius. */
+ int GetNearbyPlayersNum(void);
+
+ /** Returns the amount of this monster type in a 8-block radius (Y: 4-block radius). */
+ int GetNearbyMonsterNum(eMonsterType a_EntityType);
+
+ // tolua_end
+
+ static const char * GetClassStatic(void) { return "cMobSpawnerEntity"; }
+
+private:
+ /** The entity to spawn. */
+ eMonsterType m_Entity;
+
+ short m_SpawnDelay;
+
+ bool m_IsActive;
+} ; // tolua_end
+
+
+
+
diff --git a/src/BlockEntities/NoteEntity.h b/src/BlockEntities/NoteEntity.h
index d63ff56b6..d3f85e9d2 100644
--- a/src/BlockEntities/NoteEntity.h
+++ b/src/BlockEntities/NoteEntity.h
@@ -5,12 +5,6 @@
#include "RedstonePoweredEntity.h"
-namespace Json
-{
- class Value;
-}
-
-
diff --git a/src/BlockEntities/SignEntity.h b/src/BlockEntities/SignEntity.h
index 347689d0a..9480537ed 100644
--- a/src/BlockEntities/SignEntity.h
+++ b/src/BlockEntities/SignEntity.h
@@ -14,15 +14,6 @@
-namespace Json
-{
- class Value;
-}
-
-
-
-
-
// tolua_begin
class cSignEntity :