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  m_SpawnCount = src.m_SpawnCount;
37  m_SpawnRange = src.m_SpawnRange;
38  m_MinSpawnDelay = src.m_MinSpawnDelay;
39  m_MaxSpawnDelay = src.m_MaxSpawnDelay;
40  m_MaxNearbyEntities = src.m_MaxNearbyEntities;
41  m_RequiredPlayerRange = src.m_RequiredPlayerRange;
42 }
43 
44 
45 
46 
47 
49 {
50  a_Client.SendUpdateBlockEntity(*this);
51 }
52 
53 
54 
55 
56 
58 {
59  if (a_Player->GetEquippedItem().m_ItemType == E_ITEM_SPAWN_EGG)
60  {
62  if (MonsterType == eMonsterType::mtInvalidType)
63  {
64  return false;
65  }
66 
67  m_Entity = MonsterType;
68  ResetTimer();
69  if (!a_Player->IsGameModeCreative())
70  {
71  a_Player->GetInventory().RemoveOneEquippedItem();
72  }
74  FLOGD("Changed monster spawner at {0} to type {1}.", GetPos(), cMonster::MobTypeToString(MonsterType));
75  return true;
76  }
77  return false;
78 }
79 
80 
81 
82 
83 
85 {
87 }
88 
89 
90 
91 
92 
93 bool cMobSpawnerEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
94 {
95  using namespace std::chrono_literals;
96 
97  // Update the active flag every 5 seconds:
98  if ((m_World->GetWorldTickAge() % 5s) == 0s)
99  {
101  }
102 
103  if (!m_IsActive)
104  {
105  return false;
106  }
107 
108  if (m_SpawnDelay <= 0)
109  {
110  SpawnEntity();
112  return true;
113  }
114  else
115  {
116  m_SpawnDelay--;
117  }
118  return false;
119 }
120 
121 
122 
123 
124 
126 {
128 }
129 
130 
131 
132 
133 
135 {
136  auto NearbyEntities = GetNearbyMonsterNum(m_Entity);
137  if (NearbyEntities >= m_MaxNearbyEntities)
138  {
139  ResetTimer();
140  return;
141  }
142 
143  bool EntitiesSpawned = m_World->DoWithChunk(GetChunkX(), GetChunkZ(), [this, NearbyEntities](cChunk & a_Chunk)
144  {
145  auto & Random = GetRandomProvider();
146  auto EntitySpawnTally = NearbyEntities;
147 
148  bool HaveSpawnedEntity = false;
149  for (short I = 0; I < m_SpawnCount; I++)
150  {
151  if (EntitySpawnTally >= m_MaxNearbyEntities)
152  {
153  break;
154  }
155 
156  auto SpawnRelPos(GetRelPos());
157  SpawnRelPos += Vector3i(
158  static_cast<int>((Random.RandReal<double>() - Random.RandReal<double>()) * static_cast<double>(m_SpawnRange)),
159  Random.RandInt(-1, 1),
160  static_cast<int>((Random.RandReal<double>() - Random.RandReal<double>()) * static_cast<double>(m_SpawnRange))
161  );
162 
163  auto Chunk = a_Chunk.GetRelNeighborChunkAdjustCoords(SpawnRelPos);
164  if ((Chunk == nullptr) || !Chunk->IsValid())
165  {
166  continue;
167  }
168  EMCSBiome Biome = Chunk->GetBiomeAt(SpawnRelPos.x, SpawnRelPos.z);
169 
170  if (cMobSpawner::CanSpawnHere(Chunk, SpawnRelPos, m_Entity, Biome, true))
171  {
172  auto AbsPos = Chunk->RelativeToAbsolute(SpawnRelPos);
173  auto Monster = cMonster::NewMonsterFromType(m_Entity);
174  if (Monster == nullptr)
175  {
176  continue;
177  }
178  Monster->SetPosition(AbsPos);
179  Monster->SetYaw(Random.RandReal(360.0f));
180  if (Chunk->GetWorld()->SpawnMobFinalize(std::move(Monster)) != cEntity::INVALID_ID)
181  {
182  HaveSpawnedEntity = true;
184  EntitySpawnTally++;
185  }
186  }
187  }
188  return HaveSpawnedEntity;
189  }
190  );
191 
192  if (EntitiesSpawned)
193  {
194  ResetTimer();
195  }
196 }
197 
198 
199 
200 
201 
203 {
204  int NumPlayers = 0;
205 
206  auto Callback = [this, &NumPlayers](cEntity & a_Entity)
207  {
208  if (!a_Entity.IsPlayer())
209  {
210  return false;
211  }
212  if ((m_Pos - a_Entity.GetPosition()).Length() <= m_RequiredPlayerRange)
213  {
214  NumPlayers++;
215  }
216  return false;
217  };
218 
220  m_World->ForEachEntityInBox(PlayerBoundingBox, Callback);
221 
222  return NumPlayers;
223 }
224 
225 
226 
227 
228 
230 {
231  int NumEntities = 0;
232 
233  auto Callback = [this, &NumEntities](cEntity & a_Entity)
234  {
235  if (!a_Entity.IsMob())
236  {
237  return false;
238  }
239 
240  auto & Mob = static_cast<cMonster &>(a_Entity);
241  if (Mob.GetMobType() == m_Entity)
242  {
243  NumEntities++;
244  }
245  return false;
246  };
247 
248  const cBoundingBox EntityBoundingBox(Vector3d(m_Pos.x, m_Pos.y - 4, m_Pos.z), m_SpawnRange, 8);
249  m_World->ForEachEntityInBox(EntityBoundingBox, Callback);
250 
251  return NumEntities;
252 }
EMCSBiome
Biome IDs The first batch corresponds to the clientside biomes, used by MineCraft.
Definition: BiomeDef.h:18
@ E_BLOCK_MOB_SPAWNER
Definition: BlockType.h:62
@ E_ITEM_SPAWN_EGG
Definition: BlockType.h:429
unsigned char NIBBLETYPE
The datatype used by nibbledata (meta, light, skylight)
Definition: ChunkDef.h:44
unsigned char BLOCKTYPE
The datatype used by blockdata.
Definition: ChunkDef.h:41
@ PARTICLE_MOBSPAWN
MTRand & GetRandomProvider()
Returns the current thread's random number source.
Definition: FastRandom.cpp:12
#define ASSERT(x)
Definition: Globals.h:276
#define FLOGD
Definition: LoggerSimple.h:91
eMonsterType
Identifies individual monster type.
Definition: MonsterTypes.h:11
@ mtPig
Definition: MonsterTypes.h:47
@ mtInvalidType
Definition: MonsterTypes.h:12
Vector3< double > Vector3d
Definition: Vector3.h:485
Vector3< int > Vector3i
Definition: Vector3.h:487
int GetChunkX() const
Definition: BlockEntity.h:101
int GetChunkZ() const
Definition: BlockEntity.h:102
Vector3i GetPos() const
Definition: BlockEntity.h:90
Vector3i GetRelPos() const
Definition: BlockEntity.h:95
Vector3i m_Pos
Position in absolute block coordinates.
Definition: BlockEntity.h:113
virtual void CopyFrom(const cBlockEntity &a_Src)
Copies all properties of a_Src into this entity, except for its m_World and location.
Definition: BlockEntity.cpp:66
cWorld * m_World
Definition: BlockEntity.h:126
virtual bool UsedBy(cPlayer *a_Player) override
Called when a player uses this entity; should open the UI window.
short m_SpawnDelay
Time in ticks until the next entity spawns.
void UpdateActiveState(void)
Update the active flag from the mob spawner.
short m_SpawnRange
Diameter of the square the new monsters are spawned in.
virtual void SendTo(cClientHandle &a_Client) override
Sends the packet defining the block entity to the client specified.
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.
void ResetTimer(void)
Sets the spawn delay to a new random value.
virtual void CopyFrom(const cBlockEntity &a_Src) override
Copies all properties of a_Src into this entity, except for its m_World and location.
eMonsterType m_Entity
The entity to spawn.
short m_SpawnCount
Number of entities the spawner tries to spawn each activation.
short m_MaxNearbyEntities
Maximum amount of the same entity type in proximity.
cMobSpawnerEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld *a_World)
void SpawnEntity(void)
Spawns the entity.
int GetNearbyMonsterNum(eMonsterType a_EntityType)
short m_RequiredPlayerRange
Maximum distance to player for activation.
Represents two sets of coords, minimum and maximum for each direction.
Definition: BoundingBox.h:24
Definition: Chunk.h:36
EMCSBiome GetBiomeAt(int a_RelX, int a_RelZ) const
Definition: Chunk.h:191
cChunk * GetRelNeighborChunkAdjustCoords(Vector3i &a_RelPos) const
Returns the chunk into which the relatively-specified block belongs.
Definition: Chunk.cpp:1885
void SendUpdateBlockEntity(cBlockEntity &a_BlockEntity)
Definition: Entity.h:76
static const UInt32 INVALID_ID
Special ID that is considered an "invalid value", signifying no entity.
Definition: Entity.h:128
Definition: Player.h:29
const cItem & GetEquippedItem(void) const
Definition: Player.h:162
bool IsGameModeCreative(void) const
Returns true if the player is in Creative mode, either explicitly, or by inheriting from current worl...
Definition: Player.cpp:1025
cInventory & GetInventory(void)
Definition: Player.h:156
IntType RandInt(IntType a_Min, IntType a_Max)
Return a random IntType in the range [a_Min, a_Max].
Definition: FastRandom.h:78
bool RemoveOneEquippedItem(void)
Removes one item out of the currently equipped item stack, returns true if successful,...
Definition: Inventory.cpp:232
short m_ItemType
Definition: Item.h:163
short m_ItemDamage
Definition: Item.h:165
static eMonsterType ItemDamageToMonsterType(short a_ItemDamage)
Converts the Spawn egg item damage to the monster type to spawn.
Definition: ItemSpawnEgg.h:64
static std::unique_ptr< cMonster > NewMonsterFromType(eMonsterType a_MobType)
Creates a new object of the specified mob.
Definition: Monster.cpp:1252
static AString MobTypeToString(eMonsterType a_MobType)
Translates MobType enum to a string, empty string if unknown.
Definition: Monster.cpp:1006
static bool CanSpawnHere(cChunk *a_Chunk, Vector3i a_RelPos, eMonsterType a_MobType, EMCSBiome a_Biome, bool a_DisableSolidBelowCheck=false)
Returns true if specified type of mob can spawn on specified block.
Definition: MobSpawner.cpp:75
T x
Definition: Vector3.h:17
T y
Definition: Vector3.h:17
T z
Definition: Vector3.h:17
Definition: World.h:53
bool DoWithChunk(int a_ChunkX, int a_ChunkZ, cChunkCallback a_Callback)
Calls the callback for the chunk specified, with ChunkMapCS locked.
Definition: World.cpp:1451
virtual bool ForEachEntityInBox(const cBoundingBox &a_Box, cEntityCallback a_Callback) override
Calls the callback for each entity that has a nonempty intersection with the specified boundingbox.
Definition: World.cpp:2445
virtual void BroadcastSoundParticleEffect(const EffectID a_EffectID, Vector3i a_SrcPos, int a_Data, const cClientHandle *a_Exclude=nullptr) override
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.
cTickTimeLong GetWorldTickAge() const
Definition: World.cpp:509