Cuberite
A lightweight, fast and extensible game server for Minecraft
BeaconEntity.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 "BeaconEntity.h"
5 #include "../BlockInfo.h"
6 #include "../BlockArea.h"
7 #include "../Entities/Player.h"
8 #include "../UI/BeaconWindow.h"
9 #include "../ClientHandle.h"
10 
11 
12 
13 
14 
15 cBeaconEntity::cBeaconEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World):
16  Super(a_BlockType, a_BlockMeta, a_Pos, 1, 1, a_World),
17  m_IsActive(false),
18  m_BeaconLevel(0),
19  m_PrimaryEffect(cEntityEffect::effNoEffect),
20  m_SecondaryEffect(cEntityEffect::effNoEffect)
21 {
22  ASSERT(a_BlockType == E_BLOCK_BEACON);
23  if (m_World != nullptr)
24  {
25  UpdateBeacon();
26  }
27 }
28 
29 
30 
31 
32 
34 {
35  cBlockArea Area;
36  int MinY = std::max(GetPosY() - 4, 0);
37  int MaxY = std::max(GetPosY() - 1, 0);
38 
39  Area.Read(
40  *m_World,
41  GetPosX() - 4, GetPosX() + 4,
42  MinY, MaxY,
43  GetPosZ() - 4, GetPosZ() + 4,
45  );
46 
47  int Layer = 1;
48  int MiddleXZ = 4;
49 
50  for (int Y = (Area.GetSizeY() - 1); Y >= 0; Y--)
51  {
52  for (int X = MiddleXZ - Layer; X <= (MiddleXZ + Layer); X++)
53  {
54  for (int Z = MiddleXZ - Layer; Z <= (MiddleXZ + Layer); Z++)
55  {
56  if (!IsMineralBlock(Area.GetRelBlockType(X, Y, Z)))
57  {
58  return static_cast<char>(Layer - 1);
59  }
60  }
61  }
62  Layer++;
63  }
64 
65  return static_cast<char>(Layer - 1);
66 }
67 
68 
69 
70 
71 
72 bool cBeaconEntity::IsValidEffect(cEntityEffect::eType a_Effect, char a_BeaconLevel)
73 {
74  switch (a_Effect)
75  {
76  case cEntityEffect::effRegeneration: return (a_BeaconLevel >= 4);
77  case cEntityEffect::effStrength: return (a_BeaconLevel >= 3);
78  case cEntityEffect::effResistance: return (a_BeaconLevel >= 2);
79  case cEntityEffect::effJumpBoost: return (a_BeaconLevel >= 2);
80  case cEntityEffect::effSpeed: return (a_BeaconLevel >= 1);
81  case cEntityEffect::effHaste: return (a_BeaconLevel >= 1);
82  case cEntityEffect::effNoEffect: return true;
83 
84  default:
85  {
86  LOGD("%s: Invalid beacon effect: %d", __FUNCTION__, static_cast<int>(a_Effect));
87  return false;
88  }
89  }
90 }
91 
92 
93 
94 
95 
97 {
98  if (!IsValidEffect(a_Effect, m_BeaconLevel))
99  {
101  return false;
102  }
103 
104  m_PrimaryEffect = a_Effect;
105 
106  // Send window update:
107  if (GetWindow() != nullptr)
108  {
109  GetWindow()->SetProperty(1, static_cast<short>(m_PrimaryEffect));
110  }
111  return true;
112 }
113 
114 
115 
116 
117 
119 {
120  if (!IsValidEffect(a_Effect, m_BeaconLevel))
121  {
123  return false;
124  }
125 
126  m_SecondaryEffect = a_Effect;
127 
128  // Send window update:
129  if (GetWindow() != nullptr)
130  {
131  GetWindow()->SetProperty(2, static_cast<short>(m_SecondaryEffect));
132  }
133  return true;
134 }
135 
136 
137 
138 
139 
141 {
142  for (int Y = m_Pos.y; Y < cChunkDef::Height; ++Y)
143  {
146  {
147  return true;
148  }
149  }
150  return false;
151 }
152 
153 
154 
155 
156 
158 {
159  switch (a_BlockType)
160  {
162  case E_BLOCK_GOLD_BLOCK:
163  case E_BLOCK_IRON_BLOCK:
165  {
166  return true;
167  }
168  }
169  return false;
170 }
171 
172 
173 
174 
175 
177 {
178  int OldBeaconLevel = m_BeaconLevel;
179 
180  if (IsBeaconBlocked())
181  {
182  m_IsActive = false;
183  m_BeaconLevel = 0;
184  }
185  else
186  {
188  m_IsActive = (m_BeaconLevel > 0);
189  }
190 
191  if ((m_BeaconLevel != OldBeaconLevel) && (m_BeaconLevel == 4))
192  {
193  // Send window update:
194  if (GetWindow() != nullptr)
195  {
197  }
198 
199  Vector3d BeaconPosition(m_Pos);
200  GetWorld()->ForEachPlayer([=](cPlayer & a_Player)
201  {
202  Vector3d Distance = BeaconPosition - a_Player.GetPosition();
203  if (
204  (std::abs(Distance.y) <= 14) &&
205  (std::abs(Distance.x) <= 20) &&
206  (std::abs(Distance.z) <= 20)
207  )
208  {
209  a_Player.AwardAchievement(CustomStatistic::AchFullBeacon);
210  }
211  return false;
212  }
213  );
214  }
215 }
216 
217 
218 
219 
220 
222 {
223  if (!m_IsActive || (m_BeaconLevel < 0))
224  {
225  return;
226  }
227 
228  double Radius = static_cast<double>(m_BeaconLevel) * 10 + 10;
229  short EffectLevel = 0;
231  {
232  EffectLevel = 1;
233  }
234 
235  bool HasSecondaryEffect = (m_BeaconLevel >= 4) && (m_PrimaryEffect != m_SecondaryEffect) && (m_SecondaryEffect > 0);
236 
237  auto Area = cBoundingBox(m_Pos, Radius, Radius + static_cast<double>(cChunkDef::Height), -Radius);
238  GetWorld()->ForEachEntityInBox(Area, [&](cEntity & a_Entity)
239  {
240  if (!a_Entity.IsPlayer())
241  {
242  return false;
243  }
244  auto & Player = static_cast<cPlayer &>(a_Entity);
245  Player.AddEntityEffect(m_PrimaryEffect, 180, EffectLevel);
246 
247  if (HasSecondaryEffect)
248  {
249  Player.AddEntityEffect(m_SecondaryEffect, 180, 0);
250  }
251  return false;
252  });
253 }
254 
255 
256 
257 
258 
260 {
261  Super::CopyFrom(a_Src);
262  auto & src = static_cast<const cBeaconEntity &>(a_Src);
263  m_BeaconLevel = src.m_BeaconLevel;
264  m_Contents.CopyFrom(src.m_Contents);
265  m_IsActive = src.m_IsActive;
266  m_PrimaryEffect = src.m_PrimaryEffect;
267  m_SecondaryEffect = src.m_SecondaryEffect;
268 }
269 
270 
271 
272 
273 
275 {
276  const auto Window = GetWindow();
277  if (Window != nullptr)
278  {
279  // Tell window its owner is destroyed:
280  Window->OwnerDestroyed();
281  }
282 }
283 
284 
285 
286 
287 
289 {
290  a_Client.SendUpdateBlockEntity(*this);
291 }
292 
293 
294 
295 
296 
297 bool cBeaconEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
298 {
299  using namespace std::chrono_literals;
300 
301  // Update the beacon every 4 seconds:
302  if ((GetWorld()->GetWorldTickAge() % 4s) == 0s)
303  {
304  UpdateBeacon();
305  GiveEffects();
306  }
307  return false;
308 }
309 
310 
311 
312 
313 
315 {
317 
318  cWindow * Window = GetWindow();
319  if (Window == nullptr)
320  {
321  OpenWindow(new cBeaconWindow(this));
322  Window = GetWindow();
323  }
324 
325  if (Window != nullptr)
326  {
327  // if (a_Player->GetWindow() != Window)
328  // -> Because mojang doesn't send a 'close window' packet when you click the cancel button in the beacon inventory ...
329  {
330  a_Player->OpenWindow(*Window);
331  }
332  }
333  return true;
334 }
@ E_BLOCK_DIAMOND_BLOCK
Definition: BlockType.h:67
@ E_BLOCK_GOLD_BLOCK
Definition: BlockType.h:51
@ E_BLOCK_BEACON
Definition: BlockType.h:153
@ E_BLOCK_IRON_BLOCK
Definition: BlockType.h:52
@ E_BLOCK_EMERALD_BLOCK
Definition: BlockType.h:148
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
#define ASSERT(x)
Definition: Globals.h:276
#define LOGD
Definition: LoggerSimple.h:83
unsigned char Distance(const BlockState Block)
int GetSizeY(void) const
Definition: BlockArea.h:348
BLOCKTYPE GetRelBlockType(int a_RelX, int a_RelY, int a_RelZ) const
Definition: BlockArea.cpp:1710
bool Read(cForEachChunkProvider &a_ForEachChunkProvider, int a_MinBlockX, int a_MaxBlockX, int a_MinBlockY, int a_MaxBlockY, int a_MinBlockZ, int a_MaxBlockZ, int a_DataTypes=baTypes|baMetas|baBlockEntities)
Reads an area of blocks specified.
Definition: BlockArea.cpp:445
bool SetPrimaryEffect(cEntityEffect::eType a_Effect)
Sets the primary effect.
void UpdateBeacon(void)
Update the beacon.
virtual void OnRemoveFromWorld() override
Called when the block entity object is removed from 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.
static bool IsMineralBlock(BLOCKTYPE a_BlockType)
Returns true if the block is a diamond block, a golden block, an iron block or an emerald block.
virtual void SendTo(cClientHandle &a_Client) override
Sends the packet defining the block entity to the client specified.
cEntityEffect::eType m_PrimaryEffect
Definition: BeaconEntity.h:82
char CalculatePyramidLevel(void)
Calculate the amount of layers the pyramid below the beacon has.
static bool IsValidEffect(cEntityEffect::eType a_Effect, char a_BeaconLevel)
Returns true if the effect can be used.
void GiveEffects(void)
Give the near-players the effects.
virtual void CopyFrom(const cBlockEntity &a_Src) override
Copies all properties of a_Src into this entity, except for its m_World and location.
bool IsBeaconBlocked(void)
Is the beacon blocked by non-transparent blocks that are higher than the beacon?
cEntityEffect::eType m_SecondaryEffect
Definition: BeaconEntity.h:82
char m_BeaconLevel
Definition: BeaconEntity.h:80
virtual bool UsedBy(cPlayer *a_Player) override
Called when a player uses this entity; should open the UI window.
bool SetSecondaryEffect(cEntityEffect::eType a_Effect)
Sets the secondary effect.
cBeaconEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld *a_World)
cWorld * GetWorld() const
Definition: BlockEntity.h:99
int GetPosZ() const
Definition: BlockEntity.h:93
int GetPosY() const
Definition: BlockEntity.h:92
int GetPosX() const
Definition: BlockEntity.h:91
Vector3i m_Pos
Position in absolute block coordinates.
Definition: BlockEntity.h:113
cWorld * m_World
Definition: BlockEntity.h:126
virtual void CopyFrom(const cBlockEntity &a_Src) override
Copies all properties of a_Src into this entity, except for its m_World and location.
static bool IsTransparent(BLOCKTYPE Block)
Is a block transparent? (https://minecraft.wiki/w/Opacity)
Definition: BlockInfo.cpp:961
Represents two sets of coords, minimum and maximum for each direction.
Definition: BoundingBox.h:24
Definition: Chunk.h:36
static const int Height
Definition: ChunkDef.h:125
void SendUpdateBlockEntity(cBlockEntity &a_BlockEntity)
Definition: Entity.h:76
bool IsPlayer(void) const
Definition: Entity.h:160
const Vector3d & GetPosition(void) const
Exported in ManualBindings.
Definition: Entity.h:297
eType
All types of entity effects (numbers correspond to protocol / storage types)
Definition: EntityEffect.h:12
void AddEntityEffect(cEntityEffect::eType a_EffectType, int a_EffectDurationTicks, short a_EffectIntensity, double a_DistanceModifier=1)
Applies an entity effect.
Definition: Pawn.cpp:186
Definition: Player.h:29
StatisticsManager & GetStatistics()
Return the associated statistic and achievement manager.
Definition: Player.h:237
void OpenWindow(cWindow &a_Window)
Opens the specified window; closes the current one first using CloseWindow()
Definition: Player.cpp:1123
void CopyFrom(const cItemGrid &a_Src)
Copies all items from a_Src to this grid.
Definition: ItemGrid.cpp:83
std::unordered_map< CustomStatistic, StatValue > Custom
Represents a UI window.
Definition: Window.h:54
virtual void SetProperty(size_t a_Property, short a_Value)
Updates a numerical property associated with the window.
Definition: Window.cpp:406
cWindow * GetWindow(void) const
Definition: WindowOwner.h:40
void OpenWindow(cWindow *a_Window)
Definition: WindowOwner.h:34
T x
Definition: Vector3.h:17
T y
Definition: Vector3.h:17
T z
Definition: Vector3.h:17
Definition: World.h:53
BLOCKTYPE GetBlock(Vector3i a_BlockPos) const
Returns the block type at the specified position.
Definition: World.h:363
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 bool ForEachPlayer(cPlayerListCallback a_Callback) override
Calls the callback for each player in the list; returns true if all players processed,...
Definition: World.cpp:2266