Cuberite
A lightweight, fast and extensible game server for Minecraft
MobSpawnerEntity.cpp
Go to the documentation of this file.
1 
2 #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
3 
4 #include "MobSpawnerEntity.h"
5 
6 #include "../World.h"
7 #include "../FastRandom.h"
8 #include "../MobSpawner.h"
9 #include "../ClientHandle.h"
10 #include "../Items/ItemSpawnEgg.h"
11 
12 
13 
14 
15 
16 cMobSpawnerEntity::cMobSpawnerEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World):
17  super(a_BlockType, a_BlockMeta, a_Pos, a_World),
18  m_Entity(mtPig),
19  m_SpawnDelay(100),
20  m_IsActive(false)
21 {
22  ASSERT(a_BlockType == E_BLOCK_MOB_SPAWNER);
23 }
24 
25 
26 
27 
28 
30 {
31  super::CopyFrom(a_Src);
32  auto & src = static_cast<const cMobSpawnerEntity &>(a_Src);
33  m_Entity = src.m_Entity;
34  m_IsActive = src.m_IsActive;
35  m_SpawnDelay = src.m_SpawnDelay;
36 }
37 
38 
39 
40 
41 
43 {
44  a_Client.SendUpdateBlockEntity(*this);
45 }
46 
47 
48 
49 
50 
52 {
53  if (a_Player->GetEquippedItem().m_ItemType == E_ITEM_SPAWN_EGG)
54  {
56  if (MonsterType == eMonsterType::mtInvalidType)
57  {
58  return false;
59  }
60 
61  m_Entity = MonsterType;
62  ResetTimer();
63  if (!a_Player->IsGameModeCreative())
64  {
65  a_Player->GetInventory().RemoveOneEquippedItem();
66  }
67  FLOGD("Changed monster spawner at {0} to type {1}.", GetPos(), cMonster::MobTypeToString(MonsterType));
68  return true;
69  }
70  return false;
71 }
72 
73 
74 
75 
76 
78 {
79  if (GetNearbyPlayersNum() > 0)
80  {
81  m_IsActive = true;
82  }
83  else
84  {
85  m_IsActive = false;
86  }
87 }
88 
89 
90 
91 
92 
93 bool cMobSpawnerEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
94 {
95  // Update the active flag every 5 seconds
96  if ((m_World->GetWorldAge() % 100) == 0)
97  {
99  }
100 
101  if (!m_IsActive)
102  {
103  return false;
104  }
105 
106  if (m_SpawnDelay <= 0)
107  {
108  SpawnEntity();
109  return true;
110  }
111  else
112  {
113  m_SpawnDelay--;
114  }
115  return false;
116 }
117 
118 
119 
120 
121 
123 {
124  m_SpawnDelay = GetRandomProvider().RandInt<short>(200, 800);
126 }
127 
128 
129 
130 
131 
133 {
134  int NearbyEntities = GetNearbyMonsterNum(m_Entity);
135  if (NearbyEntities >= 6)
136  {
137  ResetTimer();
138  return;
139  }
140 
141  auto MobType = m_Entity;
142  bool EntitiesSpawned = m_World->DoWithChunk(GetChunkX(), GetChunkZ(), [&](cChunk & a_Chunk)
143  {
144  auto & Random = GetRandomProvider();
145 
146  bool HaveSpawnedEntity = false;
147  for (size_t i = 0; i < 4; i++)
148  {
149  if (NearbyEntities >= 6)
150  {
151  break;
152  }
153 
154  Vector3i spawnRelPos(GetRelPos());
155  spawnRelPos += Vector3i(
156  static_cast<int>((Random.RandReal<double>() - Random.RandReal<double>()) * 4.0),
157  Random.RandInt(-1, 1),
158  static_cast<int>((Random.RandReal<double>() - Random.RandReal<double>()) * 4.0)
159  );
160 
161  auto chunk = a_Chunk.GetRelNeighborChunkAdjustCoords(spawnRelPos);
162  if ((chunk == nullptr) || !chunk->IsValid())
163  {
164  continue;
165  }
166  EMCSBiome Biome = chunk->GetBiomeAt(spawnRelPos.x, spawnRelPos.z);
167 
168  if (cMobSpawner::CanSpawnHere(chunk, spawnRelPos, MobType, Biome))
169  {
170  auto absPos = chunk->RelativeToAbsolute(spawnRelPos);
171  auto monster = cMonster::NewMonsterFromType(MobType);
172  if (monster == nullptr)
173  {
174  continue;
175  }
176  monster->SetPosition(absPos);
177  monster->SetYaw(Random.RandReal(360.0f));
178  if (chunk->GetWorld()->SpawnMobFinalize(std::move(monster)) != cEntity::INVALID_ID)
179  {
180  HaveSpawnedEntity = true;
183  absPos,
184  0
185  );
186  NearbyEntities++;
187  }
188  }
189  }
190  return HaveSpawnedEntity;
191  }
192  );
193 
194  if (EntitiesSpawned)
195  {
196  ResetTimer();
197  }
198 }
199 
200 
201 
202 
203 
205 {
206  auto SpawnerPos = Vector3d(0.5, 0.5, 0.5) + m_Pos;
207  int NumPlayers = 0;
208 
209  class cCallback : public cChunkDataCallback
210  {
211  public:
212  cCallback(Vector3d a_SpawnerPos, int & a_NumPlayers) :
213  m_SpawnerPos(a_SpawnerPos),
214  m_NumPlayers(a_NumPlayers)
215  {
216  }
217 
218  virtual void Entity(cEntity * a_Entity) override
219  {
220  if (!a_Entity->IsPlayer())
221  {
222  return;
223  }
224 
225  if ((m_SpawnerPos - a_Entity->GetPosition()).Length() <= 16)
226  {
227  m_NumPlayers++;
228  }
229  }
230 
231  protected:
232  Vector3d m_SpawnerPos;
233  int & m_NumPlayers;
234  } Callback(SpawnerPos, NumPlayers);
235 
236  int ChunkX = GetChunkX();
237  int ChunkZ = GetChunkZ();
238  m_World->ForEachChunkInRect(ChunkX - 1, ChunkX + 1, ChunkZ - 1, ChunkZ + 1, Callback);
239 
240  return NumPlayers;
241 }
242 
243 
244 
245 
246 
248 {
249  auto SpawnerPos = Vector3d(0.5, 0.5, 0.5) + m_Pos;
250  int NumEntities = 0;
251 
252  class cCallback : public cChunkDataCallback
253  {
254  public:
255  cCallback(Vector3d a_SpawnerPos, eMonsterType a_CallbackEntityType, int & a_NumEntities) :
256  m_SpawnerPos(a_SpawnerPos),
257  m_EntityType(a_CallbackEntityType),
258  m_NumEntities(a_NumEntities)
259  {
260  }
261 
262  virtual void Entity(cEntity * a_Entity) override
263  {
264  if (!a_Entity->IsMob())
265  {
266  return;
267  }
268 
269  cMonster * Mob = static_cast<cMonster *>(a_Entity);
270  if (Mob->GetMobType() != m_EntityType)
271  {
272  return;
273  }
274 
275  if ((Diff(m_SpawnerPos.x, a_Entity->GetPosX()) <= 8.0) && (Diff(m_SpawnerPos.y, a_Entity->GetPosY()) <= 4.0) && (Diff(m_SpawnerPos.z, a_Entity->GetPosZ()) <= 8.0))
276  {
277  m_NumEntities++;
278  }
279  }
280 
281  protected:
282  Vector3d m_SpawnerPos;
283  eMonsterType m_EntityType;
284  int & m_NumEntities;
285  } Callback(SpawnerPos, a_EntityType, NumEntities);
286 
287  int ChunkX = GetChunkX();
288  int ChunkZ = GetChunkZ();
289  m_World->ForEachChunkInRect(ChunkX - 1, ChunkX + 1, ChunkZ - 1, ChunkZ + 1, Callback);
290 
291  return NumEntities;
292 }
293 
294 
295 
296 
double GetPosY(void) const
Definition: Entity.h:207
void ResetTimer(void)
Sets the spawn delay to a new random value.
double GetPosX(void) const
Definition: Entity.h:206
T x
Definition: Vector3.h:17
int GetNearbyPlayersNum(void)
Returns the amount of the nearby players in a 16-block radius.
eMonsterType GetMobType(void) const
Definition: Monster.h:68
int GetChunkZ() const
Definition: BlockEntity.h:116
cChunk * GetRelNeighborChunkAdjustCoords(Vector3i &a_RelPos) const
Returns the chunk into which the relatively-specified block belongs.
Definition: Chunk.cpp:2358
static std::unique_ptr< cMonster > NewMonsterFromType(eMonsterType a_MobType)
Creates a new object of the specified mob.
Definition: Monster.cpp:1129
short m_ItemDamage
Definition: Item.h:211
virtual void SendTo(cClientHandle &a_Client) override
Sends the packet defining the block entity to the client specified.
unsigned char BLOCKTYPE
The datatype used by blockdata.
Definition: ChunkDef.h:42
bool RemoveOneEquippedItem(void)
Removes one item out of the currently equipped item stack, returns true if successful, false if empty-handed.
Definition: Inventory.cpp:207
MTRand & GetRandomProvider()
Returns the current thread&#39;s random number source.
Definition: FastRandom.cpp:20
const cItem & GetEquippedItem(void) const
Definition: Player.h:142
Definition: Player.h:27
bool IsMob(void) const
Definition: Entity.h:173
bool DoWithChunk(int a_ChunkX, int a_ChunkZ, cChunkCallback a_Callback)
Calls the callback for the chunk specified, with ChunkMapCS locked.
Definition: World.cpp:1558
static bool CanSpawnHere(cChunk *a_Chunk, Vector3i a_RelPos, eMonsterType a_MobType, EMCSBiome a_Biome)
Returns true if specified type of mob can spawn on specified block.
Definition: MobSpawner.cpp:74
unsigned char NIBBLETYPE
The datatype used by nibbledata (meta, light, skylight)
Definition: ChunkDef.h:45
EMCSBiome
Biome IDs The first batch corresponds to the clientside biomes, used by MineCraft.
Definition: BiomeDef.h:21
Definition: Chunk.h:49
eMonsterType
Identifies individual monster type, as well as their network type-ID.
Definition: MonsterTypes.h:10
virtual void CopyFrom(const cBlockEntity &a_Src) override
Copies all properties of a_Src into this entity, except for its m_World and location.
cWorld * m_World
Definition: BlockEntity.h:155
static eMonsterType ItemDamageToMonsterType(short a_ItemDamage)
Converts the Spawn egg item damage to the monster type to spawn.
Definition: ItemSpawnEgg.h:59
T z
Definition: Vector3.h:17
cMobSpawnerEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld *a_World)
virtual bool Tick(std::chrono::milliseconds a_Dt, cChunk &a_Chunk) override
Ticks the entity; returns true if the chunk should be marked as dirty as a result of this ticking...
int GetChunkX() const
Definition: BlockEntity.h:115
virtual void BroadcastBlockEntity(Vector3i a_BlockPos, const cClientHandle *a_Exclude=nullptr) override
If there is a block entity at the specified coods, sends it to all clients except a_Exclude...
IntType RandInt(IntType a_Min, IntType a_Max)
Return a random IntType in the range [a_Min, a_Max].
Definition: FastRandom.h:78
Vector3i GetPos() const
Definition: BlockEntity.h:104
Vector3i GetRelPos() const
Definition: BlockEntity.h:109
virtual void BroadcastSoundParticleEffect(const EffectID a_EffectID, Vector3i a_SrcPos, int a_Data, const cClientHandle *a_Exclude=nullptr) override
Definition: World.h:65
virtual bool ForEachChunkInRect(int a_MinChunkX, int a_MaxChunkX, int a_MinChunkZ, int a_MaxChunkZ, cChunkDataCallback &a_Callback) override
Calls the callback for each chunk in the coords specified (all cords are inclusive).
Definition: World.cpp:2970
Vector3< double > Vector3d
Definition: Vector3.h:445
virtual Int64 GetWorldAge(void) const override
Definition: World.h:109
#define ASSERT(x)
Definition: Globals.h:335
void SendUpdateBlockEntity(cBlockEntity &a_BlockEntity)
Vector3i m_Pos
Position in absolute block coordinates.
Definition: BlockEntity.h:142
virtual void CopyFrom(const cBlockEntity &a_Src)
Copies all properties of a_Src into this entity, except for its m_World and location.
void UpdateActiveState(void)
Upate the active flag from the mob spawner.
static AString MobTypeToString(eMonsterType a_MobType)
Translates MobType enum to a string, empty string if unknown.
Definition: Monster.cpp:913
#define FLOGD(...)
Definition: LoggerSimple.h:48
bool IsPlayer(void) const
Definition: Entity.h:171
eMonsterType m_Entity
The entity to spawn.
virtual bool UsedBy(cPlayer *a_Player) override
Called when a player uses this entity; should open the UI window.
void SpawnEntity(void)
Spawns the entity.
Definition: Entity.h:73
const Vector3d & GetPosition(void) const
Exported in ManualBindings.
Definition: Entity.h:307
Vector3< int > Vector3i
Definition: Vector3.h:447
double GetPosZ(void) const
Definition: Entity.h:208
bool IsGameModeCreative(void) const
Returns true if the player is in Creative mode, either explicitly, or by inheriting from current worl...
Definition: Player.cpp:1260
short m_ItemType
Definition: Item.h:209
cInventory & GetInventory(void)
Definition: Player.h:136
static const UInt32 INVALID_ID
Special ID that is considered an "invalid value", signifying no entity.
Definition: Entity.h:156
T Diff(T a_Val1, T a_Val2)
Definition: Defines.h:965
int GetNearbyMonsterNum(eMonsterType a_EntityType)
Returns the amount of this monster type in a 8-block radius (Y: 4-block radius).