Cuberite
A lightweight, fast and extensible game server for Minecraft
Pawn.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 "Pawn.h"
5 #include "Player.h"
6 #include "../BlockInfo.h"
7 #include "../World.h"
8 #include "../Bindings/PluginManager.h"
9 #include "../BoundingBox.h"
10 #include "../Blocks/BlockHandler.h"
11 #include "../Blocks/BlockFarmland.h"
12 #include "../EffectID.h"
13 #include "../Mobs/Monster.h"
14 
15 
16 
17 
18 cPawn::cPawn(eEntityType a_EntityType, float a_Width, float a_Height) :
19  Super(a_EntityType, Vector3d(), a_Width, a_Height),
20  m_EntityEffects(tEffectMap()),
21  m_LastGroundHeight(0),
22  m_bTouchGround(false)
23 {
24  SetGravity(-32.0f);
25  SetAirDrag(0.02f);
26 }
27 
28 
29 
30 
31 
32 void cPawn::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
33 {
34  std::vector<cEntityEffect *> EffectsToTick;
35 
36  // Iterate through this entity's applied effects
37  for (tEffectMap::iterator iter = m_EntityEffects.begin(); iter != m_EntityEffects.end();)
38  {
39  // Copies values to prevent pesky wrong accesses and erasures
40  cEntityEffect::eType EffectType = iter->first;
41  cEntityEffect * Effect = iter->second.get();
42 
43  // Iterates (must be called before any possible erasure)
44  ++iter;
45 
46  // Remove effect if duration has elapsed
47  if (Effect->GetDuration() - Effect->GetTicks() <= 0)
48  {
49  RemoveEntityEffect(EffectType);
50  }
51  // Call OnTick later to make sure the iterator won't be invalid
52  else
53  {
54  EffectsToTick.push_back(Effect);
55  }
56 
57  // TODO: Check for discrepancies between client and server effect values
58  }
59 
60 
61  for (auto * Effect : EffectsToTick)
62  {
63  Effect->OnTick(*this);
64  }
65 
66  // Spectators cannot push entities around
67  if ((!IsPlayer()) || (!static_cast<cPlayer *>(this)->IsGameModeSpectator()))
68  {
70  {
71  if (a_Entity.GetUniqueID() == GetUniqueID())
72  {
73  return false;
74  }
75 
76  // we only push other mobs, boats and minecarts
77  if ((a_Entity.GetEntityType() != etMonster) && (a_Entity.GetEntityType() != etMinecart) && (a_Entity.GetEntityType() != etBoat))
78  {
79  return false;
80  }
81 
82  // do not push a boat / minecart you're sitting in
83  if (IsAttachedTo(&a_Entity))
84  {
85  return false;
86  }
87 
88  Vector3d v3Delta = a_Entity.GetPosition() - GetPosition();
89  v3Delta.y = 0.0; // we only push sideways
90  v3Delta *= 1.0 / (v3Delta.Length() + 0.01); // we push harder if we're close
91  // QUESTION: is there an additional multiplier for this? current shoving seems a bit weak
92 
93  a_Entity.AddSpeed(v3Delta);
94  return false;
95  }
96  );
97  }
98 
99  Super::Tick(a_Dt, a_Chunk);
100  if (!IsTicking())
101  {
102  // The base class tick destroyed us
103  return;
104  }
105  HandleFalling();
106 
107  // Handle item pickup
108  if (m_Health > 0)
109  {
110  if (IsPlayer())
111  {
113  }
114  else if (IsMob())
115  {
116  cMonster & Mob = static_cast<cMonster &>(*this);
117  if (Mob.CanPickUpLoot())
118  {
120  }
121  }
122  }
123 }
124 
125 
126 
127 
128 
130 {
132 
133  // Is death eligible for totem reanimation?
134  if (DeductTotem(a_TDI.DamageType))
135  {
137 
141 
142  m_Health = 1;
143  return;
144  }
145 
146  Super::KilledBy(a_TDI);
147 }
148 
149 
150 
151 
152 
153 bool cPawn::IsFireproof(void) const
154 {
156 }
157 
158 
159 
160 
161 
162 bool cPawn::IsInvisible() const
163 {
165 }
166 
167 
168 
169 
170 
172 {
174  {
175  // Prevent the oxygen from decreasing
176  return;
177  }
178 
180 }
181 
182 
183 
184 
185 
186 void cPawn::AddEntityEffect(cEntityEffect::eType a_EffectType, int a_Duration, short a_Intensity, double a_DistanceModifier)
187 {
188  // Check if the plugins allow the addition:
189  if (cPluginManager::Get()->CallHookEntityAddEffect(*this, a_EffectType, a_Duration, a_Intensity, a_DistanceModifier))
190  {
191  // A plugin disallows the addition, bail out.
192  return;
193  }
194 
195  // No need to add empty effects:
196  if (a_EffectType == cEntityEffect::effNoEffect)
197  {
198  return;
199  }
200  a_Duration = static_cast<int>(a_Duration * a_DistanceModifier);
201 
202  // If we already have the effect, we have to deactivate it or else it will act cumulatively
203  auto ExistingEffect = m_EntityEffects.find(a_EffectType);
204  if (ExistingEffect != m_EntityEffects.end())
205  {
206  ExistingEffect->second->OnDeactivate(*this);
207  }
208 
209  auto Res = m_EntityEffects.emplace(a_EffectType, cEntityEffect::CreateEntityEffect(a_EffectType, a_Duration, a_Intensity, a_DistanceModifier));
210  m_World->BroadcastEntityEffect(*this, a_EffectType, a_Intensity, a_Duration);
211  cEntityEffect * Effect = Res.first->second.get();
212  Effect->OnActivate(*this);
213 }
214 
215 
216 
217 
218 
220 {
221  m_World->BroadcastRemoveEntityEffect(*this, a_EffectType);
222  auto itr = m_EntityEffects.find(a_EffectType);
223  if (itr != m_EntityEffects.end())
224  {
225  // Erase from effect map before calling OnDeactivate to allow metadata broadcasts (e.g. for invisibility effect)
226  auto Effect = std::move(itr->second);
227  m_EntityEffects.erase(itr);
228  Effect->OnDeactivate(*this);
229  }
230 }
231 
232 
233 
234 
235 
237 {
238  return m_EntityEffects.find(a_EffectType) != m_EntityEffects.end();
239 }
240 
241 
242 
243 
244 
246 {
247  // Iterate through this entity's applied effects
248  for (tEffectMap::iterator iter = m_EntityEffects.begin(); iter != m_EntityEffects.end();)
249  {
250  // Copy values to prevent pesky wrong erasures
251  cEntityEffect::eType EffectType = iter->first;
252 
253  // Iterates (must be called before any possible erasure)
254  ++iter;
255 
256  // Remove effect
257  RemoveEntityEffect(EffectType);
258  }
259 }
260 
261 
262 
263 
264 
266 {
267  ASSERT(IsTicking()); // Our destroy override is supposed to clear all targets before we're destroyed.
268  for (auto i = m_TargetingMe.begin(); i != m_TargetingMe.end(); ++i)
269  {
270  cMonster * Monster = *i;
271  if (Monster == a_Monster)
272  {
273  ASSERT(Monster->GetTarget() != this); // The monster is notifying us it is no longer targeting us, assert if that's a lie
274  m_TargetingMe.erase(i);
275  return;
276  }
277  }
278  ASSERT(false); // If this happens, something is wrong. Perhaps the monster never called TargetingMe() or called NoLongerTargetingMe() twice.
279 }
280 
281 
282 
283 
284 
285 void cPawn::TargetingMe(cMonster * a_Monster)
286 {
287  ASSERT(IsTicking());
288  ASSERT(m_TargetingMe.size() < 10000);
289  ASSERT(a_Monster->GetTarget() == this);
290  m_TargetingMe.push_back(a_Monster);
291 }
292 
293 
294 
295 
296 
298 {
299  /* Not pretty looking, and is more suited to wherever server-sided collision detection is implemented.
300  The following condition sets on-ground-ness if
301  The player isn't swimming or flying (client hardcoded conditions) and
302  they're on a block (Y is exact) - ensure any they could be standing on (including on the edges) is solid or
303  they're on a slab (Y significand is 0.5) - ditto with slab check
304  they're on a snow layer (Y divisible by 0.125) - ditto with snow layer check
305  */
306 
307  static const auto HalfWidth = GetWidth() / 2;
308  static const auto EPS = 0.0001;
309 
310  /* Since swimming is decided in a tick and is asynchronous to this, we have to check for dampeners ourselves.
311  The behaviour as of 1.8.9 is the following:
312  - Landing in water alleviates all fall damage
313  - Passing through any liquid (water + lava) and cobwebs "slows" the player down,
314  i.e. resets the fall distance to that block, but only after checking for fall damage
315  (this means that plummeting into lava will still kill the player via fall damage, although cobwebs
316  will slow players down enough to have multiple updates that keep them alive)
317  - Slime blocks reverse falling velocity, unless it's a crouching player, in which case they act as standard blocks.
318  They also reset the topmost point of the damage calculation with each bounce,
319  so if the block is removed while the player is bouncing or crouches after a bounce, the last bounce's zenith is considered as fall damage.
320 
321  With this in mind, we first check the block at the player's feet, then the one below that (because fences),
322  and decide which behaviour we want to go with.
323  */
324  const auto BlockAtFoot = (cChunkDef::IsValidHeight(POS_TOINT)) ? GetWorld()->GetBlock(POS_TOINT) : static_cast<BLOCKTYPE>(E_BLOCK_AIR);
325 
326  /* We initialize these with what the foot is really IN, because for sampling we will move down with the epsilon above */
327  bool IsFootInWater = IsBlockWater(BlockAtFoot);
328  bool IsFootOnSlimeBlock = false;
329 
330  /* The "cross" we sample around to account for the player width/girth */
331  static const struct
332  {
333  int x, z;
334  } CrossSampleCoords[] =
335  {
336  { 0, 0 },
337  { 1, 0 },
338  { -1, 0 },
339  { 0, 1 },
340  { 0, -1 },
341  };
342 
343  /* The blocks we're interested in relative to the player to account for larger than 1 blocks.
344  This can be extended to do additional checks in case there are blocks that are represented as one block
345  in memory but have a hitbox larger than 1 (like fences) */
346  static const Vector3i BlockSampleOffsets[] =
347  {
348  { 0, 0, 0 }, // TODO: something went wrong here (offset 0?)
349  { 0, -1, 0 }, // Potentially causes mis-detection (IsFootInWater) when player stands on block diagonal to water (i.e. on side of pool)
350  };
351 
352  /* Here's the rough outline of how this mechanism works:
353  We take the player's pointlike position (sole of feet), and expand it into a crosslike shape.
354  If any of the five points hit a block, we consider the player to be "on" (or "in") the ground. */
355  bool OnGround = false;
356  for (size_t i = 0; i < ARRAYCOUNT(CrossSampleCoords); i++)
357  {
358  /* We calculate from the player's position, one of the cross-offsets above, and we move it down slightly so it's beyond inaccuracy.
359  The added advantage of this method is that if the player is simply standing on the floor,
360  the point will move into the next block, and the floor() will retrieve that instead of air. */
361  Vector3d CrossTestPosition = GetPosition() + Vector3d(CrossSampleCoords[i].x * HalfWidth, -EPS, CrossSampleCoords[i].z * HalfWidth);
362 
363  /* We go through the blocks that we consider "relevant" */
364  for (size_t j = 0; j < ARRAYCOUNT(BlockSampleOffsets); j++)
365  {
366  Vector3i BlockTestPosition = CrossTestPosition.Floor() + BlockSampleOffsets[j];
367 
368  if (!cChunkDef::IsValidHeight(BlockTestPosition))
369  {
370  continue;
371  }
372 
373  BLOCKTYPE BlockType = GetWorld()->GetBlock(BlockTestPosition);
374  NIBBLETYPE BlockMeta = GetWorld()->GetBlockMeta(BlockTestPosition);
375 
376  /* we do the cross-shaped sampling to check for water / liquids, but only on our level because water blocks are never bigger than unit voxels */
377  if (j == 0)
378  {
379  IsFootInWater |= IsBlockWater(BlockType);
380  IsFootOnSlimeBlock |= (BlockType == E_BLOCK_SLIME_BLOCK);
381  }
382 
383  /* If the block is solid, and the blockhandler confirms the block to be inside, we're officially on the ground. */
384  if ((cBlockInfo::IsSolid(BlockType)) && (cBlockHandler::For(BlockType).IsInsideBlock(CrossTestPosition - BlockTestPosition, BlockMeta)))
385  {
386  OnGround = true;
387  }
388  }
389  }
390 
391  /* So here's the use of the rules above: */
392  /* 1. Falling in water absorbs all fall damage */
393  bool FallDamageAbsorbed = IsFootInWater;
394 
395  /* 2. Falling in liquid (lava, water, cobweb) or hitting a slime block resets the "fall zenith".
396  Note: Even though the pawn bounces back with no damage after hitting the slime block,
397  the "fall zenith" will continue to increase back up when flying upwards - which is good */
398  bool ShouldBounceOnSlime = true;
399 
400  if (IsPlayer())
401  {
402  auto Player = static_cast<cPlayer *>(this);
403 
404  /* 3. If the player is flying or climbing, absorb fall damage */
405  FallDamageAbsorbed |= Player->IsFlying() || Player->IsClimbing();
406 
407  /* 4. If the player is about to bounce on a slime block and is not crouching, absorb all fall damage */
408  ShouldBounceOnSlime = !Player->IsCrouched();
409  FallDamageAbsorbed |= (IsFootOnSlimeBlock && ShouldBounceOnSlime);
410  }
411  else
412  {
413  /* 5. Bouncing on a slime block absorbs all fall damage */
414  FallDamageAbsorbed |= IsFootOnSlimeBlock;
415  }
416 
417  /* If the player is not crouching or is not a player, shoot them back up.
418  NOTE: this will only work in some cases; should be done in HandlePhysics() */
419  if (IsFootOnSlimeBlock && ShouldBounceOnSlime)
420  {
421  // TODO: doesn't work too well, causes dissatisfactory experience for players on slime blocks - SetSpeedY(-GetSpeedY());
422  }
423 
424  // TODO: put player speed into GetSpeedY, and use that.
425  // If flying, climbing, swimming, or going up...
426  if (FallDamageAbsorbed || ((GetPosition() - m_LastPosition).y > 0))
427  {
428  // ...update the ground height to have the highest position of the player (i.e. jumping up adds to the eventual fall damage)
430  }
431 
432  if (OnGround)
433  {
434  const auto FallHeight = m_LastGroundHeight - GetPosY();
435  auto Damage = static_cast<int>(FallHeight - 3.0);
436 
437  const auto Below = POS_TOINT.addedY(-1);
438  const auto BlockBelow = (cChunkDef::IsValidHeight(Below)) ? GetWorld()->GetBlock(Below) : static_cast<BLOCKTYPE>(E_BLOCK_AIR);
439 
440  if ((Damage > 0) && !FallDamageAbsorbed)
441  {
442  if (IsElytraFlying())
443  {
444  Damage = static_cast<int>(static_cast<float>(Damage) * 0.33);
445  }
446 
447  if (BlockBelow == E_BLOCK_HAY_BALE)
448  {
449  Damage = std::clamp(static_cast<int>(static_cast<float>(Damage) * 0.2), 1, 20);
450  }
451 
452  // Fall particles
453  // TODO: falling on a partial (e.g. slab) block shouldn't broadcast particles of the block below
455  "blockdust",
456  GetPosition(),
457  { 0, 0, 0 },
458  (Damage - 1.f) * ((0.3f - 0.1f) / (15.f - 1.f)) + 0.1f, // Map damage (1 - 15) to particle speed (0.1 - 0.3)
459  static_cast<int>((Damage - 1.f) * ((50.f - 20.f) / (15.f - 1.f)) + 20.f), // Map damage (1 - 15) to particle quantity (20 - 50)
460  { { BlockBelow, 0 } }
461  );
462 
463  TakeDamage(dtFalling, nullptr, Damage, static_cast<float>(Damage), 0);
464  }
465 
466  m_bTouchGround = true;
468 
469  // Farmland trampling. Mobs smaller than 0.512 cubic blocks won't trample (Java Edition's behavior)
470  // We only have width and height, so we have to calculate Width^2
471  if (GetWorld()->IsFarmlandTramplingEnabled())
472  {
473  HandleFarmlandTrampling(FallHeight, BlockAtFoot, BlockBelow);
474  }
475  }
476  else
477  {
478  m_bTouchGround = false;
479  }
480 
481  /* Note: it is currently possible to fall through lava and still die from fall damage
482  because of the client skipping an update about the lava block. This can only be resolved by
483  somehow integrating these above checks into the tracer in HandlePhysics. */
484 }
485 
486 
487 
488 
489 
490 void cPawn::HandleFarmlandTrampling(const double a_FallHeight, const BLOCKTYPE a_BlockAtFoot, const BLOCKTYPE a_BlockBelow)
491 {
492  // No trampling if FallHeight <= 0.6875
493  if (a_FallHeight <= 0.6875)
494  {
495  return;
496  }
497  // No trampling for mobs smaller than 0.512 cubic blocks
498  if (GetWidth() * GetWidth() * GetHeight() < 0.512)
499  {
500  return;
501  }
502 
503  auto AbsPos = POS_TOINT;
504 
505  // Check if the foot is "inside" a farmland - for 1.10.1 and newer clients
506  // If it isn't, check if the block below is a farmland - for mobs and older clients
507  if (a_BlockAtFoot != E_BLOCK_FARMLAND)
508  {
509  // These are probably the only blocks which:
510  // - can be placed on a farmland and shouldn't destroy it
511  // - will stop the player from falling down further
512  // - are less than 1 block high
513  if ((a_BlockAtFoot == E_BLOCK_HEAD) || (a_BlockAtFoot == E_BLOCK_FLOWER_POT))
514  {
515  return;
516  }
517 
518  // Finally, check whether the block below is farmland
519  if (a_BlockBelow != E_BLOCK_FARMLAND)
520  {
521  return;
522  }
523 
524  // If we haven't returned, decrease the height
525  AbsPos.y -= 1;
526  }
527 
528  bool ShouldTrample = true;
529  auto & Random = GetRandomProvider();
530 
531  // For FallHeight <= 1.5625 we need to get a random bool
532  if (a_FallHeight <= 1.0625)
533  {
534  ShouldTrample = Random.RandBool(0.25);
535  }
536  else if (a_FallHeight <= 1.5625)
537  {
538  ShouldTrample = Random.RandBool(0.66);
539  }
540  // For FallHeight > 1.5625 we always trample - ShouldTrample remains true
541 
542  if (ShouldTrample)
543  {
544  GetWorld()->DoWithChunkAt(AbsPos, [&](cChunk & Chunk)
545  {
546  cBlockFarmlandHandler::TurnToDirt(Chunk, AbsPos);
547  return true;
548  });
549  }
550 }
551 
552 
553 
554 
555 
557 {
559  Super::OnRemoveFromWorld(a_World);
560 }
561 
562 
563 
564 
565 
567 {
568  std::vector<cMonster*>::iterator i = m_TargetingMe.begin();
569  while (i != m_TargetingMe.end())
570  {
571  cMonster * Monster = *i;
572  ASSERT(Monster->GetTarget() == this);
573  Monster->UnsafeUnsetTarget();
574  i = m_TargetingMe.erase(i);
575  }
576  ASSERT(m_TargetingMe.size() == 0);
577 }
578 
579 
580 
581 
582 
583 std::map<cEntityEffect::eType, cEntityEffect *> cPawn::GetEntityEffects() const
584 {
585  std::map<cEntityEffect::eType, cEntityEffect *> Effects;
586  for (auto & Effect : m_EntityEffects)
587  {
588  Effects.insert({ Effect.first, Effect.second.get() });
589  }
590  return Effects;
591 }
592 
593 
594 
595 
596 
598 {
599  auto itr = m_EntityEffects.find(a_EffectType);
600  return (itr != m_EntityEffects.end()) ? itr->second.get() : nullptr;
601 }
602 
603 
604 
605 
606 
607 void cPawn::ResetPosition(Vector3d a_NewPosition)
608 {
609  Super::ResetPosition(a_NewPosition);
611 }
612 
613 
614 
615 
616 
617 bool cPawn::DeductTotem(const eDamageType a_DamageType)
618 {
619  if ((a_DamageType == dtAdmin) || (a_DamageType == dtInVoid))
620  {
621  // Beyond saving:
622  return false;
623  }
624 
625  if (!IsPlayer())
626  {
627  // TODO: implement when mobs will be able to pick up items based on CanPickUpLoot attribute:
628  return false;
629  }
630 
631  // If the player is holding a totem of undying in their off-hand or
632  // main-hand slot and receives otherwise fatal damage, the totem saves the player from death.
633 
634  auto & inv = static_cast<cPlayer *>(this)->GetInventory();
635  if (inv.GetEquippedItem().m_ItemType == E_ITEM_TOTEM_OF_UNDYING)
636  {
637  inv.SetEquippedItem({});
638  return true;
639  }
640  if (inv.GetShieldSlot().m_ItemType == E_ITEM_TOTEM_OF_UNDYING)
641  {
642  inv.SetShieldSlot({});
643  return true;
644  }
645  return false;
646 }
647 
648 
649 
650 
651 
652 bool cPawn::FindTeleportDestination(cWorld & a_World, const int a_HeightRequired, const unsigned int a_NumTries, Vector3d & a_Destination, const Vector3i a_MinBoxCorner, const Vector3i a_MaxBoxCorner)
653 {
654  /*
655  Algorithm:
656  Choose random destination.
657  Seek downwards, regardless of distance until the block is made of movement-blocking material: https://minecraft.wiki/w/Materials
658  Succeeds if no liquid or solid blocks prevents from standing at destination.
659  */
660  auto & Random = GetRandomProvider();
661 
662  for (unsigned int i = 0; i < a_NumTries; i++)
663  {
664  const int DestX = Random.RandInt(a_MinBoxCorner.x, a_MaxBoxCorner.x);
665  int DestY = Random.RandInt(a_MinBoxCorner.y, a_MaxBoxCorner.y);
666  const int DestZ = Random.RandInt(a_MinBoxCorner.z, a_MaxBoxCorner.z);
667 
668  // Seek downwards from initial destination until we find a solid block or go into the void
669  BLOCKTYPE DestBlock = a_World.GetBlock({DestX, DestY, DestZ});
670  while ((DestY >= 0) && !cBlockInfo::IsSolid(DestBlock))
671  {
672  DestBlock = a_World.GetBlock({DestX, DestY, DestZ});
673  DestY--;
674  }
675 
676  // Couldn't find a solid block so move to next attempt
677  if (DestY < 0)
678  {
679  continue;
680  }
681 
682  // Succeed if blocks above destination are empty
683  bool Success = true;
684  for (int j = 1; j <= a_HeightRequired; j++)
685  {
686  BLOCKTYPE TestBlock = a_World.GetBlock({DestX, DestY + j, DestZ});
687  if (cBlockInfo::IsSolid(TestBlock) || IsBlockLiquid(TestBlock))
688  {
689  Success = false;
690  break;
691  }
692  }
693 
694  if (!Success)
695  {
696  continue;
697  }
698 
699  // Offsets for entity to be centred and standing on solid block
700  a_Destination = Vector3d(DestX + 0.5, DestY + 1, DestZ + 0.5);
701  return true;
702  }
703  return false;
704 }
705 
706 
707 
708 
709 
710 bool cPawn::FindTeleportDestination(cWorld & a_World, const int a_HeightRequired, const unsigned int a_NumTries, Vector3d & a_Destination, const cBoundingBox a_BoundingBox)
711 {
712  return FindTeleportDestination(a_World, a_HeightRequired, a_NumTries, a_Destination, a_BoundingBox.GetMin(), a_BoundingBox.GetMax());
713 }
714 
715 
716 
717 
718 
719 bool cPawn::FindTeleportDestination(cWorld & a_World, const int a_HeightRequired, const unsigned int a_NumTries, Vector3d & a_Destination, Vector3i a_Centre, const int a_HalfCubeWidth)
720 {
721  Vector3i MinCorner(a_Centre.x - a_HalfCubeWidth, a_Centre.y - a_HalfCubeWidth, a_Centre.z - a_HalfCubeWidth);
722  Vector3i MaxCorner(a_Centre.x + a_HalfCubeWidth, a_Centre.y + a_HalfCubeWidth, a_Centre.z + a_HalfCubeWidth);
723  return FindTeleportDestination(a_World, a_HeightRequired, a_NumTries, a_Destination, MinCorner, MaxCorner);
724 }
bool IsBlockWater(BLOCKTYPE a_BlockType)
Definition: BlockInfo.cpp:10
bool IsBlockLiquid(BLOCKTYPE a_BlockType)
Definition: BlockInfo.cpp:58
@ E_BLOCK_HEAD
Definition: BlockType.h:159
@ E_BLOCK_SLIME_BLOCK
Definition: BlockType.h:184
@ E_BLOCK_FARMLAND
Definition: BlockType.h:72
@ E_BLOCK_AIR
Definition: BlockType.h:10
@ E_BLOCK_HAY_BALE
Definition: BlockType.h:189
@ E_BLOCK_FLOWER_POT
Definition: BlockType.h:155
@ E_ITEM_TOTEM_OF_UNDYING
Definition: BlockType.h:496
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
eDamageType
Damage type, used in the TakeDamageInfo structure and related functions.
Definition: Defines.h:244
@ dtAdmin
Definition: Defines.h:263
@ dtInVoid
Definition: Defines.h:260
@ dtFalling
Definition: Defines.h:249
#define POS_TOINT
Definition: Entity.h:34
MTRand & GetRandomProvider()
Returns the current thread's random number source.
Definition: FastRandom.cpp:12
#define ARRAYCOUNT(X)
Evaluates to the number of elements in an array (compile-time!)
Definition: Globals.h:231
#define ASSERT(x)
Definition: Globals.h:276
BlockType
Definition: BlockTypes.h:4
Vector3< double > Vector3d
Definition: Vector3.h:485
static cPluginManager * Get(void)
Returns the instance of the Plugin Manager (there is only ever one)
static bool IsSolid(BLOCKTYPE Block)
Is this block solid (player cannot walk through)?
Definition: BlockInfo.cpp:892
static void TurnToDirt(cChunk &a_Chunk, Vector3i a_AbsPos)
Turns farmland into dirt.
Definition: BlockFarmland.h:34
virtual bool IsInsideBlock(const Vector3d a_RelPosition, const NIBBLETYPE a_BlockMeta) const
Tests if a_RelPosition is inside the block, where a_RelPosition is relative to the origin of the bloc...
static const cBlockHandler & For(BLOCKTYPE a_BlockType)
Represents two sets of coords, minimum and maximum for each direction.
Definition: BoundingBox.h:24
Vector3d GetMax(void) const
Definition: BoundingBox.h:101
Vector3d GetMin(void) const
Definition: BoundingBox.h:100
Definition: Chunk.h:36
static bool IsValidHeight(Vector3i a_BlockPosition)
Validates a height-coordinate.
Definition: ChunkDef.h:185
eDamageType DamageType
Definition: Entity.h:61
Definition: Entity.h:76
float m_Health
Definition: Entity.h:584
virtual bool IsElytraFlying(void) const
Definition: Entity.h:487
bool IsPlayer(void) const
Definition: Entity.h:160
Vector3d m_LastPosition
Definition: Entity.h:620
cBoundingBox GetBoundingBox() const
Definition: Entity.h:211
virtual void Tick(std::chrono::milliseconds a_Dt, cChunk &a_Chunk)
Definition: Entity.cpp:909
bool IsAttachedTo(const cEntity *a_Entity) const
Returns true if this entity is attached to the specified entity.
Definition: Entity.cpp:2081
void AddSpeed(double a_AddSpeedX, double a_AddSpeedY, double a_AddSpeedZ)
Definition: Entity.cpp:2194
virtual void HandleAir(void)
Called in each tick to handle air-related processing i.e.
Definition: Entity.cpp:1798
bool IsTicking(void) const
Returns true if the entity is valid and ticking.
Definition: Entity.cpp:2259
void SetGravity(float a_Gravity)
Definition: Entity.h:282
virtual bool IsFireproof(void) const
Definition: Entity.h:412
float GetWidth(void) const
Definition: Entity.h:205
cWorld * m_World
Definition: Entity.h:624
virtual bool IsHeadInWater(void) const
Returns true if any part of the entity is in a water block.
Definition: Entity.h:504
UInt32 GetUniqueID(void) const
Definition: Entity.h:253
eEntityType GetEntityType(void) const
Definition: Entity.h:156
double GetPosY(void) const
Definition: Entity.h:196
void TakeDamage(cEntity &a_Attacker)
Makes this pawn take damage from an attack by a_Attacker.
Definition: Entity.cpp:272
float GetHeight(void) const
Definition: Entity.h:193
void SetAirDrag(float a_AirDrag)
Definition: Entity.h:286
virtual void KilledBy(TakeDamageInfo &a_TDI)
Called when the health drops below zero.
Definition: Entity.cpp:851
virtual void OnRemoveFromWorld(cWorld &a_World)
Called when the entity is removed from a world.
Definition: Entity.cpp:172
const Vector3d & GetPosition(void) const
Exported in ManualBindings.
Definition: Entity.h:297
eEntityType
Definition: Entity.h:89
@ etMinecart
Definition: Entity.h:96
@ etMonster
Definition: Entity.h:94
@ etBoat
Definition: Entity.h:97
cWorld * GetWorld(void) const
Definition: Entity.h:190
virtual void ResetPosition(Vector3d a_NewPos)
Set the entities position and last sent position.
Definition: Entity.cpp:1857
bool IsMob(void) const
Definition: Entity.h:162
eType
All types of entity effects (numbers correspond to protocol / storage types)
Definition: EntityEffect.h:12
int GetDuration(void) const
Returns the duration of the effect.
Definition: EntityEffect.h:90
virtual void OnActivate(cPawn &a_Target)
Called when the effect is first added to an entity.
Definition: EntityEffect.h:108
int GetTicks(void) const
Returns how many ticks this effect has been active for.
Definition: EntityEffect.h:87
static std::unique_ptr< cEntityEffect > CreateEntityEffect(cEntityEffect::eType a_EffectType, int a_Duration, short a_Intensity, double a_DistanceModifier)
Creates a pointer to the proper entity effect from the effect type.
void HandleFarmlandTrampling(double a_FallHeight, BLOCKTYPE a_BlockAtFoot, BLOCKTYPE a_BlockBelow)
Handles farmland trampling when hitting the ground.
Definition: Pawn.cpp:490
void ClearEntityEffects(void)
Removes all currently applied entity effects (used when drinking milk)
Definition: Pawn.cpp:245
bool DeductTotem(eDamageType a_DamageType)
Attempt to activate a Totem of Undying.
Definition: Pawn.cpp:617
tEffectMap m_EntityEffects
Definition: Pawn.h:102
std::map< cEntityEffect::eType, std::unique_ptr< cEntityEffect > > tEffectMap
Definition: Pawn.h:101
virtual bool IsInvisible() const override
Definition: Pawn.cpp:162
cEntityEffect * GetEntityEffect(cEntityEffect::eType a_EffectType) const
Returns the entity effect, if it is currently applied or nullptr if not.
Definition: Pawn.cpp:597
virtual void ResetPosition(Vector3d a_NewPosition) override
Set the entities position and last sent position.
Definition: Pawn.cpp:607
virtual void HandleFalling(void)
Definition: Pawn.cpp:297
void TargetingMe(cMonster *a_Monster)
Add the monster to the list of monsters targeting this pawn.
Definition: Pawn.cpp:285
void StopEveryoneFromTargetingMe()
Tells all pawns which are targeting us to stop targeting us.
Definition: Pawn.cpp:566
std::map< cEntityEffect::eType, cEntityEffect * > GetEntityEffects() const
Returns all entity effects.
Definition: Pawn.cpp:583
std::vector< cMonster * > m_TargetingMe
A list of all monsters that are targeting this pawn.
Definition: Pawn.h:112
bool HasEntityEffect(cEntityEffect::eType a_EffectType) const
Returns true, if the entity effect is currently applied.
Definition: Pawn.cpp:236
virtual void HandleAir(void) override
Called in each tick to handle air-related processing i.e.
Definition: Pawn.cpp:171
void AddEntityEffect(cEntityEffect::eType a_EffectType, int a_EffectDurationTicks, short a_EffectIntensity, double a_DistanceModifier=1)
Applies an entity effect.
Definition: Pawn.cpp:186
double m_LastGroundHeight
Definition: Pawn.h:104
void RemoveEntityEffect(cEntityEffect::eType a_EffectType)
Removes a currently applied entity effect.
Definition: Pawn.cpp:219
static bool FindTeleportDestination(cWorld &a_World, const int a_HeightRequired, const unsigned int a_NumTries, Vector3d &a_Destination, const Vector3i a_MinBoxCorner, const Vector3i a_MaxBoxCorner)
Definition: Pawn.cpp:652
virtual void Tick(std::chrono::milliseconds a_Dt, cChunk &a_Chunk) override
Definition: Pawn.cpp:32
bool m_bTouchGround
Definition: Pawn.h:105
virtual void OnRemoveFromWorld(cWorld &a_World) override
Called when the entity is removed from a world.
Definition: Pawn.cpp:556
cPawn(eEntityType a_EntityType, float a_Width, float a_Height)
Definition: Pawn.cpp:18
virtual bool IsFireproof(void) const override
Definition: Pawn.cpp:153
void NoLongerTargetingMe(cMonster *a_Monster)
Remove the monster from the list of monsters targeting this pawn.
Definition: Pawn.cpp:265
virtual void KilledBy(TakeDamageInfo &a_TDI) override
Called when the health drops below zero.
Definition: Pawn.cpp:129
Definition: Player.h:29
bool IsFlying(void) const
Returns true if the player is currently flying.
Definition: Player.h:377
cPawn * GetTarget()
Returns the current target.
Definition: Monster.cpp:1243
void UnsafeUnsetTarget()
Unset the target without notifying the target entity.
Definition: Monster.cpp:1234
bool CanPickUpLoot()
Definition: Monster.h:136
T x
Definition: Vector3.h:17
Vector3< int > Floor(void) const
Returns a new Vector3i with coords set to std::floor() of this vector's coords.
Definition: Vector3.h:177
T y
Definition: Vector3.h:17
double Length(void) const
Definition: Vector3.h:100
T z
Definition: Vector3.h:17
Definition: World.h:53
bool DoWithChunkAt(Vector3i a_BlockPos, cChunkCallback a_Callback)
Calls the callback for the chunk at the block position specified, with ChunkMapCS locked.
Definition: World.cpp:1460
virtual void BroadcastEntityAnimation(const cEntity &a_Entity, EntityAnimation a_Animation, const cClientHandle *a_Exclude=nullptr) override
BLOCKTYPE GetBlock(Vector3i a_BlockPos) const
Returns the block type at the specified position.
Definition: World.h:363
virtual void BroadcastParticleEffect(const AString &a_ParticleName, Vector3f a_Src, Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, const cClientHandle *a_Exclude=nullptr) override
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
NIBBLETYPE GetBlockMeta(Vector3i a_BlockPos) const
Returns the block meta at the specified position.
Definition: World.h:370
void CollectPickupsByEntity(cEntity &a_Entity)
Definition: World.cpp:2257
virtual void BroadcastEntityEffect(const cEntity &a_Entity, int a_EffectID, int a_Amplifier, int a_Duration, const cClientHandle *a_Exclude=nullptr) override
virtual void BroadcastRemoveEntityEffect(const cEntity &a_Entity, int a_EffectID, const cClientHandle *a_Exclude=nullptr) override