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 "../BlockArea.h"
6 #include "../Entities/Player.h"
7 #include "../UI/BeaconWindow.h"
8 #include "../ClientHandle.h"
9 
10 
11 
12 
13 
14 cBeaconEntity::cBeaconEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World):
15  super(a_BlockType, a_BlockMeta, a_Pos, 1, 1, a_World),
16  m_IsActive(false),
17  m_BeaconLevel(0),
18  m_PrimaryEffect(cEntityEffect::effNoEffect),
19  m_SecondaryEffect(cEntityEffect::effNoEffect)
20 {
21  ASSERT(a_BlockType == E_BLOCK_BEACON);
22  if (m_World != nullptr)
23  {
24  UpdateBeacon();
25  }
26 }
27 
28 
29 
30 
31 
33 {
34  cBlockArea Area;
35  int MinY = std::max(GetPosY() - 4, 0);
36  int MaxY = std::max(GetPosY() - 1, 0);
37 
38  Area.Read(
39  *m_World,
40  GetPosX() - 4, GetPosX() + 4,
41  MinY, MaxY,
42  GetPosZ() - 4, GetPosZ() + 4,
44  );
45 
46  int Layer = 1;
47  int MiddleXZ = 4;
48 
49  for (int Y = (Area.GetSizeY() - 1); Y >= 0; Y--)
50  {
51  for (int X = MiddleXZ - Layer; X <= (MiddleXZ + Layer); X++)
52  {
53  for (int Z = MiddleXZ - Layer; Z <= (MiddleXZ + Layer); Z++)
54  {
55  if (!IsMineralBlock(Area.GetRelBlockType(X, Y, Z)))
56  {
57  return static_cast<char>(Layer - 1);
58  }
59  }
60  }
61  Layer++;
62  }
63 
64  return static_cast<char>(Layer - 1);
65 }
66 
67 
68 
69 
70 
71 bool cBeaconEntity::IsValidEffect(cEntityEffect::eType a_Effect, char a_BeaconLevel)
72 {
73  switch (a_Effect)
74  {
75  case cEntityEffect::effRegeneration: return (a_BeaconLevel >= 4);
76  case cEntityEffect::effStrength: return (a_BeaconLevel >= 3);
77  case cEntityEffect::effResistance: return (a_BeaconLevel >= 2);
78  case cEntityEffect::effJumpBoost: return (a_BeaconLevel >= 2);
79  case cEntityEffect::effSpeed: return (a_BeaconLevel >= 1);
80  case cEntityEffect::effHaste: return (a_BeaconLevel >= 1);
81  case cEntityEffect::effNoEffect: return true;
82 
83  default:
84  {
85  LOGD("%s: Invalid beacon effect: %d", __FUNCTION__, static_cast<int>(a_Effect));
86  return false;
87  }
88  }
89 }
90 
91 
92 
93 
94 
96 {
97  if (!IsValidEffect(a_Effect, m_BeaconLevel))
98  {
100  return false;
101  }
102 
103  m_PrimaryEffect = a_Effect;
104 
105  // Send window update:
106  if (GetWindow() != nullptr)
107  {
109  }
110  return true;
111 }
112 
113 
114 
115 
116 
118 {
119  if (!IsValidEffect(a_Effect, m_BeaconLevel))
120  {
122  return false;
123  }
124 
125  m_SecondaryEffect = a_Effect;
126 
127  // Send window update:
128  if (GetWindow() != nullptr)
129  {
131  }
132  return true;
133 }
134 
135 
136 
137 
138 
140 {
141  for (int Y = m_Pos.y; Y < cChunkDef::Height; ++Y)
142  {
143  BLOCKTYPE Block = m_World->GetBlock({m_Pos.x, Y, m_Pos.z});
144  if (!cBlockInfo::IsTransparent(Block))
145  {
146  return true;
147  }
148  }
149  return false;
150 }
151 
152 
153 
154 
155 
157 {
158  switch (a_BlockType)
159  {
161  case E_BLOCK_GOLD_BLOCK:
162  case E_BLOCK_IRON_BLOCK:
164  {
165  return true;
166  }
167  }
168  return false;
169 }
170 
171 
172 
173 
174 
176 {
177  int OldBeaconLevel = m_BeaconLevel;
178 
179  if (IsBeaconBlocked())
180  {
181  m_IsActive = false;
182  m_BeaconLevel = 0;
183  }
184  else
185  {
187  m_IsActive = (m_BeaconLevel > 0);
188  }
189 
190  if ((m_BeaconLevel != OldBeaconLevel) && (m_BeaconLevel == 4))
191  {
192  // Send window update:
193  if (GetWindow() != nullptr)
194  {
196  }
197 
198  Vector3d BeaconPosition(m_Pos);
199  GetWorld()->ForEachPlayer([=](cPlayer & a_Player)
200  {
201  Vector3d Distance = BeaconPosition - a_Player.GetPosition();
202  if (
203  (std::abs(Distance.y) <= 14) &&
204  (std::abs(Distance.x) <= 20) &&
205  (std::abs(Distance.z) <= 20)
206  )
207  {
209  }
210  return false;
211  }
212  );
213  }
214 }
215 
216 
217 
218 
219 
221 {
222  if (!m_IsActive || (m_BeaconLevel < 0))
223  {
224  return;
225  }
226 
227  int Radius = m_BeaconLevel * 10 + 10;
228  short EffectLevel = 0;
230  {
231  EffectLevel = 1;
232  }
233 
234  bool HasSecondaryEffect = (m_BeaconLevel >= 4) && (m_PrimaryEffect != m_SecondaryEffect) && (m_SecondaryEffect > 0);
235 
236  Vector3d BeaconPosition(m_Pos);
237  GetWorld()->ForEachPlayer([=](cPlayer & a_Player)
238  {
239  auto PlayerPosition = a_Player.GetPosition();
240  if (PlayerPosition.y > BeaconPosition.y)
241  {
242  PlayerPosition.y = BeaconPosition.y;
243  }
244 
245  // TODO: Vanilla minecraft uses an AABB check instead of a radius one
246  if ((PlayerPosition - BeaconPosition).Length() <= Radius)
247  {
248  a_Player.AddEntityEffect(m_PrimaryEffect, 180, EffectLevel);
249 
250  if (HasSecondaryEffect)
251  {
252  a_Player.AddEntityEffect(m_SecondaryEffect, 180, 0);
253  }
254  }
255  return false;
256  }
257  );
258 }
259 
260 
261 
262 
263 
265 {
266  super::CopyFrom(a_Src);
267  auto & src = static_cast<const cBeaconEntity &>(a_Src);
268  m_BeaconLevel = src.m_BeaconLevel;
269  m_Contents.CopyFrom(src.m_Contents);
270  m_IsActive = src.m_IsActive;
271  m_PrimaryEffect = src.m_PrimaryEffect;
272  m_SecondaryEffect = src.m_SecondaryEffect;
273 }
274 
275 
276 
277 
278 
280 {
281  a_Client.SendUpdateBlockEntity(*this);
282 }
283 
284 
285 
286 
287 
288 bool cBeaconEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
289 {
290  // Update the beacon every 4 seconds
291  if ((GetWorld()->GetWorldAge() % 80) == 0)
292  {
293  UpdateBeacon();
294  GiveEffects();
295  }
296  return false;
297 }
298 
299 
300 
301 
302 
304 {
305  cWindow * Window = GetWindow();
306  if (Window == nullptr)
307  {
308  OpenWindow(new cBeaconWindow(this));
309  Window = GetWindow();
310  }
311 
312  if (Window != nullptr)
313  {
314  // if (a_Player->GetWindow() != Window)
315  // -> Because mojang doesn't send a 'close window' packet when you click the cancel button in the beacon inventory ...
316  {
317  a_Player->OpenWindow(*Window);
318  }
319  }
320  return true;
321 }
322 
323 
324 
325 
bool IsBeaconBlocked(void)
Is the beacon blocked by non-transparent blocks that are higher than the beacon?
eType
All types of entity effects (numbers correspond to protocol / storage types)
Definition: EntityEffect.h:11
cBeaconEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld *a_World)
BLOCKTYPE GetBlock(Vector3i a_BlockPos)
Returns the block type at the specified position.
Definition: World.h:416
T x
Definition: Vector3.h:17
char m_BeaconLevel
Definition: BeaconEntity.h:81
cWorld * GetWorld() const
Definition: BlockEntity.h:113
void CopyFrom(const cItemGrid &a_Src)
Copies all items from a_Src to this grid.
Definition: ItemGrid.cpp:83
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 GetPosY() const
Definition: BlockEntity.h:106
unsigned int AwardAchievement(const eStatistic a_Ach)
Awards the player an achievement.
Definition: Player.cpp:1605
void GiveEffects(void)
Give the near-players the effects.
unsigned char BLOCKTYPE
The datatype used by blockdata.
Definition: ChunkDef.h:42
cEntityEffect::eType m_SecondaryEffect
Definition: BeaconEntity.h:83
Definition: Player.h:27
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 IsMineralBlock(BLOCKTYPE a_BlockType)
Returns true if the block is a diamond block, a golden block, an iron block or an emerald block...
cEntityEffect::eType m_PrimaryEffect
Definition: BeaconEntity.h:83
void OpenWindow(cWindow *a_Window)
Definition: WindowOwner.h:34
char CalculatePyramidLevel(void)
Calculate the amount of layers the pyramid below the beacon has.
int GetPosX() const
Definition: BlockEntity.h:105
virtual void CopyFrom(const cBlockEntity &a_Src) override
Copies all properties of a_Src into this entity, except for its m_World and location.
int GetPosZ() const
Definition: BlockEntity.h:107
unsigned char NIBBLETYPE
The datatype used by nibbledata (meta, light, skylight)
Definition: ChunkDef.h:45
void UpdateBeacon(void)
Update the beacon.
virtual bool UsedBy(cPlayer *a_Player) override
Called when a player uses this entity; should open the UI window.
Definition: Chunk.h:49
T y
Definition: Vector3.h:17
cWorld * m_World
Definition: BlockEntity.h:155
T z
Definition: Vector3.h:17
static const int Height
Definition: ChunkDef.h:135
cWindow * GetWindow(void) const
Definition: WindowOwner.h:40
Definition: World.h:65
void AddEntityEffect(cEntityEffect::eType a_EffectType, int a_EffectDurationTicks, short a_EffectIntensity, double a_DistanceModifier=1)
Applies an entity effect.
Definition: Pawn.cpp:172
BLOCKTYPE GetRelBlockType(int a_RelX, int a_RelY, int a_RelZ) const
Definition: BlockArea.cpp:1722
static bool IsValidEffect(cEntityEffect::eType a_Effect, char a_BeaconLevel)
Returns true if the effect can be used.
#define ASSERT(x)
Definition: Globals.h:335
void SendUpdateBlockEntity(cBlockEntity &a_BlockEntity)
#define LOGD(...)
Definition: LoggerSimple.h:40
Vector3i m_Pos
Position in absolute block coordinates.
Definition: BlockEntity.h:142
int GetSizeY(void) const
Definition: BlockArea.h:345
virtual void SetProperty(short a_Property, short a_Value)
Updates a numerical property associated with the window.
Definition: Window.cpp:751
static bool IsTransparent(BLOCKTYPE a_Type)
Definition: BlockInfo.h:32
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:443
virtual void SendTo(cClientHandle &a_Client) override
Sends the packet defining the block entity to the client specified.
const Vector3d & GetPosition(void) const
Exported in ManualBindings.
Definition: Entity.h:307
Represents a UI window.
Definition: Window.h:53
bool SetSecondaryEffect(cEntityEffect::eType a_Effect)
Sets the secondary effect.
bool SetPrimaryEffect(cEntityEffect::eType a_Effect)
Sets the primary effect.
void OpenWindow(cWindow &a_Window)
Opens the specified window; closes the current one first using CloseWindow()
Definition: Player.cpp:1349
virtual bool ForEachPlayer(cPlayerListCallback a_Callback) override
Calls the callback for each player in the list; returns true if all players processed, false if the callback aborted by returning true.
Definition: World.cpp:2549