Cuberite
A lightweight, fast and extensible game server for Minecraft
Player.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 "Player.h"
5 #include "../Mobs/Wolf.h"
6 #include "../Mobs/Horse.h"
7 #include "../BoundingBox.h"
8 #include "../ChatColor.h"
9 #include "../Server.h"
10 #include "../UI/InventoryWindow.h"
11 #include "../UI/WindowOwner.h"
12 #include "../Bindings/PluginManager.h"
13 #include "../BlockEntities/BlockEntity.h"
14 #include "../BlockEntities/EnderChestEntity.h"
15 #include "../Root.h"
16 #include "../Chunk.h"
17 #include "../Items/ItemHandler.h"
18 #include "../FastRandom.h"
19 #include "../ClientHandle.h"
20 
21 #include "../WorldStorage/StatisticsSerializer.h"
22 #include "../CompositeChat.h"
23 
24 #include "../Blocks/BlockHandler.h"
25 #include "../Blocks/BlockSlab.h"
26 #include "../Blocks/ChunkInterface.h"
27 
28 #include "../IniFile.h"
29 #include "../JsonUtils.h"
30 #include "json/json.h"
31 
32 #include "../CraftingRecipes.h"
33 
34 
35 
36 
37 
38 namespace
39 {
40 
43 AString GetUUIDFolderName(const cUUID & a_Uuid)
44 {
45  AString UUID = a_Uuid.ToShortString();
46 
47  AString res("players/");
48  res.append(UUID, 0, 2);
49  res.push_back('/');
50  return res;
51 }
52 
53 } // namespace (anonymous)
54 
55 
56 
57 
58 
59 const int cPlayer::MAX_HEALTH = 20;
60 
61 const int cPlayer::MAX_FOOD_LEVEL = 20;
62 
63 // Number of ticks it takes to eat an item.
64 #define EATING_TICKS 30_tick
65 
66 // 6000 ticks or 5 minutes
67 #define PLAYER_INVENTORY_SAVE_INTERVAL 6000
68 
69 // Food saturation for newly-joined or just-respawned players.
70 #define RESPAWN_FOOD_SATURATION 5
71 
72 #define XP_TO_LEVEL15 255
73 #define XP_PER_LEVEL_TO15 17
74 #define XP_TO_LEVEL30 825
75 
76 
77 
78 
79 
81 {
82  a_Player.SetSize(0.6f, 1.65f);
83 }
84 
85 
86 
87 
88 
90 {
91  a_Player.SetSize(0.2f, 0.2f);
92 }
93 
94 
95 
96 
97 
99 {
100  a_Player.SetSize(0.6f, 1.8f);
101 }
102 
103 
104 
105 
106 
108  TicksElytraFlying(0)
109 {
110  a_Player.SetSize(0.6f, 0.6f);
111 }
112 
113 
114 
115 
116 
117 cPlayer::cPlayer(const std::shared_ptr<cClientHandle> & a_Client) :
118  Super(etPlayer, 0.6f, 1.8f),
120  m_Inventory(*this),
121  m_EnderChestContents(9, 3),
122  m_DefaultWorldPath(cRoot::Get()->GetDefaultWorld()->GetDataPath()),
123  m_ClientHandle(a_Client),
124  m_NormalMaxSpeed(1.0),
125  m_SprintingMaxSpeed(1.3),
126  m_FlyingMaxSpeed(1.0),
127  m_IsChargingBow(false),
128  m_IsFishing(false),
129  m_IsFrozen(false),
130  m_IsLeftHanded(false),
131  m_IsTeleporting(false),
132  m_EatingFinishTick(-1),
133  m_BowCharge(0),
135  m_Team(nullptr),
136  m_Spectating(nullptr),
138  m_SkinParts(0)
139 {
140  ASSERT(GetName().length() <= 16); // Otherwise this player could crash many clients...
141 
142  m_InventoryWindow = new cInventoryWindow(*this);
145 
146  LoadFromDisk();
148  UpdateCapabilities(); // Only required for plugins listening to HOOK_SPAWNING_ENTITY to not read uninitialised variables.
149 }
150 
151 
152 
153 
154 
156 {
157  LOGD("Deleting cPlayer \"%s\" at %p, ID %d", GetName().c_str(), static_cast<void *>(this), GetUniqueID());
158 
159  // "Times ragequit":
161 
162  SaveToDisk();
163 
164  delete m_InventoryWindow;
165 
166  LOGD("Player %p deleted", static_cast<void *>(this));
167 }
168 
169 
170 
171 
172 
174 {
175  m_ClientHandle->SendCameraSetTo(*this);
176  m_ClientHandle->SendPlayerMoveLook();
177  m_Spectating = nullptr;
178 }
179 
180 
181 
182 
183 
184 int cPlayer::CalcLevelFromXp(int a_XpTotal)
185 {
186  // level 0 to 15
187  if (a_XpTotal <= XP_TO_LEVEL15)
188  {
189  return a_XpTotal / XP_PER_LEVEL_TO15;
190  }
191 
192  // level 30+
193  if (a_XpTotal > XP_TO_LEVEL30)
194  {
195  return static_cast<int>((151.5 + sqrt( 22952.25 - (14 * (2220 - a_XpTotal)))) / 7);
196  }
197 
198  // level 16 to 30
199  return static_cast<int>((29.5 + sqrt( 870.25 - (6 * ( 360 - a_XpTotal)))) / 3);
200 }
201 
202 
203 
204 
205 
206 const std::set<UInt32> & cPlayer::GetKnownRecipes() const
207 {
208  return m_KnownRecipes;
209 }
210 
211 
212 
213 
214 
215 int cPlayer::XpForLevel(int a_Level)
216 {
217  // level 0 to 15
218  if (a_Level <= 15)
219  {
220  return a_Level * XP_PER_LEVEL_TO15;
221  }
222 
223  // level 30+
224  if (a_Level >= 31)
225  {
226  return static_cast<int>((3.5 * a_Level * a_Level) - (151.5 * a_Level) + 2220);
227  }
228 
229  // level 16 to 30
230  return static_cast<int>((1.5 * a_Level * a_Level) - (29.5 * a_Level) + 360);
231 }
232 
233 
234 
235 
236 
238 {
240 }
241 
242 
243 
244 
245 
247 {
248  int currentLevel = CalcLevelFromXp(m_CurrentXp);
249  int currentLevel_XpBase = XpForLevel(currentLevel);
250 
251  return static_cast<float>(m_CurrentXp - currentLevel_XpBase) /
252  static_cast<float>(XpForLevel(1 + currentLevel) - currentLevel_XpBase);
253 }
254 
255 
256 
257 
258 
259 bool cPlayer::SetCurrentExperience(int a_CurrentXp)
260 {
261  if (!(a_CurrentXp >= 0) || (a_CurrentXp > (std::numeric_limits<int>::max() - m_LifetimeTotalXp)))
262  {
263  LOGWARNING("Tried to update experiece with an invalid Xp value: %d", a_CurrentXp);
264  return false; // oops, they gave us a dodgey number
265  }
266 
267  m_CurrentXp = a_CurrentXp;
268 
269  // Update experience:
270  m_ClientHandle->SendExperience();
271 
272  return true;
273 }
274 
275 
276 
277 
278 
279 int cPlayer::DeltaExperience(int a_Xp_delta)
280 {
281  if (a_Xp_delta > (std::numeric_limits<int>().max() - m_CurrentXp))
282  {
283  // Value was bad, abort and report
284  LOGWARNING("Attempt was made to increment Xp by %d, which overflowed the int datatype. Ignoring.", a_Xp_delta);
285  return -1; // Should we instead just return the current Xp?
286  }
287 
288  m_CurrentXp += a_Xp_delta;
289 
290  // Make sure they didn't subtract too much
291  m_CurrentXp = std::max(m_CurrentXp, 0);
292 
293 
294  // Update total for score calculation
295  if (a_Xp_delta > 0)
296  {
297  m_LifetimeTotalXp += a_Xp_delta;
298  }
299 
300  LOGD("Player \"%s\" gained / lost %d experience, total is now: %d", GetName().c_str(), a_Xp_delta, m_CurrentXp);
301 
302  // Set experience to be updated:
303  m_ClientHandle->SendExperience();
304 
305  return m_CurrentXp;
306 }
307 
308 
309 
310 
311 
313 {
314  LOGD("Player \"%s\" started charging their bow", GetName().c_str());
315  m_IsChargingBow = true;
316  m_BowCharge = 0;
318 }
319 
320 
321 
322 
323 
325 {
326  LOGD("Player \"%s\" finished charging their bow at a charge of %d", GetName().c_str(), m_BowCharge);
327  int res = m_BowCharge;
328  m_IsChargingBow = false;
329  m_BowCharge = 0;
331 
332  return res;
333 }
334 
335 
336 
337 
338 
340 {
341  LOGD("Player \"%s\" cancelled charging their bow at a charge of %d", GetName().c_str(), m_BowCharge);
342  m_IsChargingBow = false;
343  m_BowCharge = 0;
345 }
346 
347 
348 
349 
350 
351 void cPlayer::SetTouchGround(bool a_bTouchGround)
352 {
353  if (IsGameModeSpectator()) // You can fly through the ground in Spectator
354  {
355  return;
356  }
357 
358  UNUSED(a_bTouchGround);
359  /* Unfortunately whatever the reason, there are still desyncs in on-ground status between the client and server. For example:
360  1. Walking off a ledge (whatever height)
361  2. Initial login
362  Thus, it is too risky to compare their value against ours and kick them for hacking */
363 }
364 
365 
366 
367 
368 
369 void cPlayer::Heal(int a_Health)
370 {
371  Super::Heal(a_Health);
372  m_ClientHandle->SendHealth();
373 }
374 
375 
376 
377 
378 
379 void cPlayer::SetFoodLevel(int a_FoodLevel)
380 {
381  int FoodLevel = Clamp(a_FoodLevel, 0, MAX_FOOD_LEVEL);
382 
383  if (cRoot::Get()->GetPluginManager()->CallHookPlayerFoodLevelChange(*this, FoodLevel))
384  {
385  return;
386  }
387 
388  m_FoodLevel = FoodLevel;
389  m_ClientHandle->SendHealth();
390 }
391 
392 
393 
394 
395 
396 void cPlayer::SetFoodSaturationLevel(double a_FoodSaturationLevel)
397 {
398  m_FoodSaturationLevel = Clamp(a_FoodSaturationLevel, 0.0, static_cast<double>(m_FoodLevel));
399 }
400 
401 
402 
403 
404 
405 void cPlayer::SetFoodTickTimer(int a_FoodTickTimer)
406 {
407  m_FoodTickTimer = a_FoodTickTimer;
408 }
409 
410 
411 
412 
413 
414 void cPlayer::SetFoodExhaustionLevel(double a_FoodExhaustionLevel)
415 {
416  m_FoodExhaustionLevel = Clamp(a_FoodExhaustionLevel, 0.0, 40.0);
417 }
418 
419 
420 
421 
422 
423 bool cPlayer::Feed(int a_Food, double a_Saturation)
424 {
425  if (IsSatiated())
426  {
427  return false;
428  }
429 
431  SetFoodLevel(m_FoodLevel + a_Food);
432  return true;
433 }
434 
435 
436 
437 
438 
439 void cPlayer::AddFoodExhaustion(double a_Exhaustion)
440 {
442  {
443  m_FoodExhaustionLevel = std::min(m_FoodExhaustionLevel + a_Exhaustion, 40.0);
444  }
445 }
446 
447 
448 
449 
450 
451 bool cPlayer::IsInBed(void) const
452 {
453  return std::holds_alternative<BodyStanceSleeping>(m_BodyStance);
454 }
455 
456 
457 
458 
459 
461 {
462  return m_IsLeftHanded;
463 }
464 
465 
466 
467 
468 
470 {
471  return std::holds_alternative<BodyStanceStanding>(m_BodyStance);
472 }
473 
474 
475 
476 
477 
478 void cPlayer::TossItems(const cItems & a_Items)
479 {
480  if (IsGameModeSpectator()) // Players can't toss items in spectator
481  {
482  return;
483  }
484 
486 
487  const auto Speed = (GetLookVector() + Vector3d(0, 0.2, 0)) * 6; // A dash of height and a dollop of speed
488  const auto Position = GetEyePosition() - Vector3d(0, 0.2, 0); // Correct for eye-height weirdness
489  m_World->SpawnItemPickups(a_Items, Position, Speed, true); // 'true' because created by player
490 }
491 
492 
493 
494 
495 
496 void cPlayer::SetIsInBed(const bool a_GoToBed)
497 {
498  if (a_GoToBed && IsStanding())
499  {
502  }
503  else if (!a_GoToBed && IsInBed())
504  {
507  }
508 }
509 
510 
511 
512 
513 
515 {
516  // Set the timer:
518 
519  // Send the packet:
521 }
522 
523 
524 
525 
526 
528 {
529  // Reset the timer:
530  m_EatingFinishTick = -1_tick;
531 
532  // Send the packets:
533  m_ClientHandle->SendEntityAnimation(*this, EntityAnimation::PlayerFinishesEating);
535 
536  // consume the item:
538  Item.m_ItemCount = 1;
539  auto & ItemHandler = Item.GetHandler();
540  if (!ItemHandler.EatItem(this, &Item))
541  {
542  return;
543  }
544  ItemHandler.OnFoodEaten(m_World, this, &Item);
545 }
546 
547 
548 
549 
550 
552 {
553  m_EatingFinishTick = -1_tick;
555 }
556 
557 
558 
559 
560 
562 {
563  // Clear the list of slots that are being inventory-painted. Used by cWindow only
564  m_InventoryPaintSlots.clear();
565 }
566 
567 
568 
569 
570 
572 {
573  // Add a slot to the list for inventory painting. Used by cWindow only
574  m_InventoryPaintSlots.push_back(a_SlotNum);
575 }
576 
577 
578 
579 
580 
582 {
583  // Return the list of slots currently stored for inventory painting. Used by cWindow only
584  return m_InventoryPaintSlots;
585 }
586 
587 
588 
589 
590 
591 double cPlayer::GetMaxSpeed(void) const
592 {
593  if (IsFlying())
594  {
595  return m_FlyingMaxSpeed;
596  }
597  else if (IsSprinting())
598  {
599  return m_SprintingMaxSpeed;
600  }
601  else
602  {
603  return m_NormalMaxSpeed;
604  }
605 }
606 
607 
608 
609 
610 
611 void cPlayer::SetNormalMaxSpeed(double a_Speed)
612 {
613  m_NormalMaxSpeed = a_Speed;
614 
615  if (!m_IsFrozen)
616  {
617  // If we are frozen, we do not send this yet. We send when unfreeze() is called
619  }
620 }
621 
622 
623 
624 
625 
626 void cPlayer::SetSprintingMaxSpeed(double a_Speed)
627 {
628  m_SprintingMaxSpeed = a_Speed;
629 
630  if (!m_IsFrozen)
631  {
632  // If we are frozen, we do not send this yet. We send when unfreeze() is called
634  }
635 }
636 
637 
638 
639 
640 
641 void cPlayer::SetFlyingMaxSpeed(double a_Speed)
642 {
643  m_FlyingMaxSpeed = a_Speed;
644 
645  if (!m_IsFrozen)
646  {
647  // If we are frozen, we do not send this yet. We send when unfreeze() is called
648  m_ClientHandle->SendPlayerAbilities();
649  }
650 }
651 
652 
653 
654 
655 
656 void cPlayer::SetCrouch(const bool a_ShouldCrouch)
657 {
658  if (a_ShouldCrouch && IsStanding())
659  {
661 
662  // Handle spectator mode detach:
663  if (IsGameModeSpectator())
664  {
665  SpectateEntity(nullptr);
666  }
667 
669  }
670  else if (!a_ShouldCrouch && IsCrouched())
671  {
673  }
674 
676 }
677 
678 
679 
680 
681 
682 void cPlayer::SetElytraFlight(const bool a_ShouldElytraFly)
683 {
684  if (a_ShouldElytraFly && IsStanding() && !IsOnGround() && !IsInWater() && !IsRiding() && (GetEquippedChestplate().m_ItemType == E_ITEM_ELYTRA))
685  {
687  }
688  else if (!a_ShouldElytraFly && IsElytraFlying())
689  {
691  }
692 
694 }
695 
696 
697 
698 
699 
700 void cPlayer::SetFlying(const bool a_ShouldFly)
701 {
702  if (a_ShouldFly == m_IsFlying)
703  {
704  return;
705  }
706 
707  m_IsFlying = a_ShouldFly;
708  if (!m_IsFrozen)
709  {
710  // If we are frozen, we do not send this yet. We send when unfreeze() is called
711  m_ClientHandle->SendPlayerAbilities();
712  }
713 }
714 
715 
716 
717 
718 
719 void cPlayer::SetLeftHanded(const bool a_IsLeftHanded)
720 {
721  m_IsLeftHanded = a_IsLeftHanded;
723 }
724 
725 
726 
727 
728 
729 void cPlayer::SetSprint(const bool a_ShouldSprint)
730 {
731  if (a_ShouldSprint && IsStanding())
732  {
734  }
735  else if (!a_ShouldSprint && IsSprinting())
736  {
738  }
739 
742 }
743 
744 
745 
746 
747 
748 void cPlayer::SetCanFly(bool a_CanFly)
749 {
750  if (a_CanFly == m_IsFlightCapable)
751  {
752  return;
753  }
754 
755  m_IsFlightCapable = a_CanFly;
756  m_ClientHandle->SendPlayerAbilities();
757 }
758 
759 
760 
761 
762 
763 void cPlayer::SetCustomName(const AString & a_CustomName)
764 {
765  if (m_CustomName == a_CustomName)
766  {
767  return;
768  }
769 
771 
772  m_CustomName = a_CustomName;
773  if (m_CustomName.length() > 16)
774  {
775  m_CustomName = m_CustomName.substr(0, 16);
776  }
777 
780 }
781 
782 
783 
784 
785 
786 void cPlayer::SetBedPos(const Vector3i a_Position)
787 {
788  SetBedPos(a_Position, *m_World);
789 }
790 
791 
792 
793 
794 
795 void cPlayer::SetBedPos(const Vector3i a_Position, const cWorld & a_World)
796 {
797  m_RespawnPosition = a_Position;
798  m_IsRespawnPointForced = false;
799  m_SpawnWorldName = a_World.GetName();
800 }
801 
802 
803 
804 
805 
806 void cPlayer::SetRespawnPosition(const Vector3i a_Position, const cWorld & a_World)
807 {
808  m_RespawnPosition = a_Position;
809  m_IsRespawnPointForced = true;
810  m_SpawnWorldName = a_World.GetName();
811 }
812 
813 
814 
815 
816 
818 {
819  if (const auto World = cRoot::Get()->GetWorld(m_SpawnWorldName); World != nullptr)
820  {
821  return World;
822  }
823 
824  return cRoot::Get()->GetDefaultWorld();
825 }
826 
827 
828 
829 
830 
831 void cPlayer::NotifyNearbyWolves(cPawn * a_Opponent, bool a_IsPlayerInvolved)
832 {
833  ASSERT(a_Opponent != nullptr);
834 
835  m_World->ForEachEntityInBox(cBoundingBox(GetPosition(), 16), [&] (cEntity & a_Entity)
836  {
837  if (a_Entity.IsMob())
838  {
839  auto & Mob = static_cast<cMonster&>(a_Entity);
840  if (Mob.GetMobType() == mtWolf)
841  {
842  auto & Wolf = static_cast<cWolf&>(Mob);
843  Wolf.ReceiveNearbyFightInfo(GetUUID(), a_Opponent, a_IsPlayerInvolved);
844  }
845  }
846  return false;
847  }
848  );
849 }
850 
851 
852 
853 
854 
856 {
857  Super::KilledBy(a_TDI);
858 
859  if (m_Health > 0)
860  {
861  return; // not dead yet =]
862  }
863 
864  m_IsVisible = false; // So new clients don't see the player
865 
866  // Detach player from object / entity. If the player dies, the server still says
867  // that the player is attached to the entity / object
868  Detach();
869 
870  // Puke out all the items
871  cItems Pickups;
872  m_Inventory.CopyToItems(Pickups);
873  m_Inventory.Clear();
874 
875  if (GetName() == "Notch")
876  {
877  Pickups.Add(cItem(E_ITEM_RED_APPLE));
878  }
880 
881  m_World->SpawnItemPickups(Pickups, GetPosX(), GetPosY(), GetPosZ(), 10);
882  SaveToDisk(); // Save it, yeah the world is a tough place !
883 
884  BroadcastDeathMessage(a_TDI);
885 
888 
890 }
891 
892 
893 
894 
895 
896 void cPlayer::Killed(const cEntity & a_Victim, eDamageType a_DamageType)
897 {
898  cScoreboard & ScoreBoard = m_World->GetScoreBoard();
899 
900  if (a_Victim.IsPlayer())
901  {
903 
905  }
906  else if (a_Victim.IsMob())
907  {
908  const auto & Monster = static_cast<const cMonster &>(a_Victim);
909 
910  if (Monster.GetMobFamily() == cMonster::mfHostile)
911  {
913  }
914 
915  if ((Monster.GetMobType() == eMonsterType::mtSkeleton) && (a_DamageType == eDamageType::dtRangedAttack))
916  {
917  const double DistX = GetPosX() - Monster.GetPosX();
918  const double DistZ = GetPosZ() - Monster.GetPosZ();
919 
920  if ((DistX * DistX + DistZ * DistZ) >= 2500.0)
921  {
923  }
924  }
925 
927  }
928 
930 }
931 
932 
933 
934 
935 
937 {
938  ASSERT(m_World != nullptr);
939 
942 
943  // Reset food level:
947 
948  // Reset Experience
949  m_CurrentXp = 0;
950  m_LifetimeTotalXp = 0;
951  // ToDo: send score to client? How?
952 
953  // Extinguish the fire:
954  StopBurning();
955 
956  // Disable flying:
957  SetFlying(false);
958 
960  {
961  // Check if the bed is still present:
963  {
964  const auto & DefaultWorld = *cRoot::Get()->GetDefaultWorld();
965 
966  // If not, reset spawn to default and inform:
967  SetRespawnPosition(Vector3i(DefaultWorld.GetSpawnX(), DefaultWorld.GetSpawnY(), DefaultWorld.GetSpawnZ()), DefaultWorld);
968  SendAboveActionBarMessage("Your home bed was missing or obstructed");
969  }
970 
971  // TODO: bed obstruction check here
972  }
973 
974 
975  if (const auto RespawnWorld = GetRespawnWorld(); m_World != RespawnWorld)
976  {
977  MoveToWorld(*RespawnWorld, m_RespawnPosition, false, false);
978  }
979  else
980  {
981  m_ClientHandle->SendRespawn(m_World->GetDimension(), true);
983  }
984 
985  SetVisible(true);
986 }
987 
988 
989 
990 
991 
992 double cPlayer::GetEyeHeight(void) const
993 {
994  return GetEyePosition().y - GetPosY();
995 }
996 
997 
998 
999 
1000 
1002 {
1003  if (IsCrouched())
1004  {
1005  return GetPosition().addedY(1.54);
1006  }
1007 
1008  if (IsElytraFlying())
1009  {
1010  return GetPosition().addedY(0.4);
1011  }
1012 
1013  if (IsInBed())
1014  {
1015  return GetPosition().addedY(0.2);
1016  }
1017 
1018  return GetPosition().addedY(1.6);
1019 }
1020 
1021 
1022 
1023 
1024 
1026 {
1027  return (GetEffectiveGameMode() == gmCreative);
1028 }
1029 
1030 
1031 
1032 
1033 
1035 {
1036  return (GetEffectiveGameMode() == gmSurvival);
1037 }
1038 
1039 
1040 
1041 
1042 
1044 {
1045  return (GetEffectiveGameMode() == gmAdventure);
1046 }
1047 
1048 
1049 
1050 
1051 
1053 {
1054  return (GetEffectiveGameMode() == gmSpectator);
1055 }
1056 
1057 
1058 
1059 
1060 
1061 bool cPlayer::CanMobsTarget(void) const
1062 {
1063  return (IsGameModeSurvival() || IsGameModeAdventure()) && (m_Health > 0);
1064 }
1065 
1066 
1067 
1068 
1069 
1071 {
1072  return m_ClientHandle->GetIPString();
1073 }
1074 
1075 
1076 
1077 
1078 
1079 void cPlayer::SetTeam(cTeam * a_Team)
1080 {
1081  if (m_Team == a_Team)
1082  {
1083  return;
1084  }
1085 
1086  if (m_Team)
1087  {
1089  }
1090 
1091  m_Team = a_Team;
1092 
1093  if (m_Team)
1094  {
1095  m_Team->AddPlayer(GetName());
1096  }
1097 }
1098 
1099 
1100 
1101 
1102 
1104 {
1105  if (m_World == nullptr)
1106  {
1107  SetTeam(nullptr);
1108  }
1109  else
1110  {
1111  cScoreboard & Scoreboard = m_World->GetScoreBoard();
1112 
1113  SetTeam(Scoreboard.QueryPlayerTeam(GetName()));
1114  }
1115 
1116  return m_Team;
1117 }
1118 
1119 
1120 
1121 
1122 
1124 {
1125  if (cRoot::Get()->GetPluginManager()->CallHookPlayerOpeningWindow(*this, a_Window))
1126  {
1127  return;
1128  }
1129 
1130  if (&a_Window != m_CurrentWindow)
1131  {
1132  CloseWindow(false);
1133  }
1134 
1135  a_Window.OpenedByPlayer(*this);
1136  m_CurrentWindow = &a_Window;
1137  a_Window.SendWholeWindow(*GetClientHandle());
1138 }
1139 
1140 
1141 
1142 
1143 
1144 void cPlayer::CloseWindow(bool a_CanRefuse)
1145 {
1146  if (m_CurrentWindow == nullptr)
1147  {
1149  return;
1150  }
1151 
1152  if (m_CurrentWindow->ClosedByPlayer(*this, a_CanRefuse) || !a_CanRefuse)
1153  {
1154  // Close accepted, go back to inventory window (the default):
1156  }
1157  else
1158  {
1159  // Re-open the window
1162  }
1163 }
1164 
1165 
1166 
1167 
1168 
1169 void cPlayer::CloseWindowIfID(char a_WindowID, bool a_CanRefuse)
1170 {
1171  if ((m_CurrentWindow == nullptr) || (m_CurrentWindow->GetWindowID() != a_WindowID))
1172  {
1173  return;
1174  }
1175  CloseWindow();
1176 }
1177 
1178 
1179 
1180 
1181 
1182 void cPlayer::SendMessage(const AString & a_Message)
1183 {
1184  m_ClientHandle->SendChat(a_Message, mtCustom);
1185 }
1186 
1187 
1188 
1189 
1190 
1191 void cPlayer::SendMessageInfo(const AString & a_Message)
1192 {
1193  m_ClientHandle->SendChat(a_Message, mtInformation);
1194 }
1195 
1196 
1197 
1198 
1199 
1200 void cPlayer::SendMessageFailure(const AString & a_Message)
1201 {
1202  m_ClientHandle->SendChat(a_Message, mtFailure);
1203 }
1204 
1205 
1206 
1207 
1208 
1209 void cPlayer::SendMessageSuccess(const AString & a_Message)
1210 {
1211  m_ClientHandle->SendChat(a_Message, mtSuccess);
1212 }
1213 
1214 
1215 
1216 
1217 
1218 void cPlayer::SendMessageWarning(const AString & a_Message)
1219 {
1220  m_ClientHandle->SendChat(a_Message, mtWarning);
1221 }
1222 
1223 
1224 
1225 
1226 
1227 void cPlayer::SendMessageFatal(const AString & a_Message)
1228 {
1229  m_ClientHandle->SendChat(a_Message, mtFailure);
1230 }
1231 
1232 
1233 
1234 
1235 
1236 void cPlayer::SendMessagePrivateMsg(const AString & a_Message, const AString & a_Sender)
1237 {
1238  m_ClientHandle->SendChat(a_Message, mtPrivateMessage, a_Sender);
1239 }
1240 
1241 
1242 
1243 
1244 
1245 void cPlayer::SendMessage(const cCompositeChat & a_Message)
1246 {
1247  m_ClientHandle->SendChat(a_Message);
1248 }
1249 
1250 
1251 
1252 
1253 
1254 void cPlayer::SendMessageRaw(const AString & a_MessageRaw, eChatType a_Type)
1255 {
1256  m_ClientHandle->SendChatRaw(a_MessageRaw, a_Type);
1257 }
1258 
1259 
1260 
1261 
1262 
1263 void cPlayer::SendSystemMessage(const AString & a_Message)
1264 {
1265  m_ClientHandle->SendChatSystem(a_Message, mtCustom);
1266 }
1267 
1268 
1269 
1270 
1271 
1273 {
1274  m_ClientHandle->SendChatAboveActionBar(a_Message, mtCustom);
1275 }
1276 
1277 
1278 
1279 
1280 
1282 {
1283  m_ClientHandle->SendChatSystem(a_Message);
1284 }
1285 
1286 
1287 
1288 
1289 
1291 {
1292  m_ClientHandle->SendChatAboveActionBar(a_Message);
1293 }
1294 
1295 
1296 
1297 
1298 
1299 const AString & cPlayer::GetName(void) const
1300 {
1301  return m_ClientHandle->GetUsername();
1302 }
1303 
1304 
1305 
1306 
1307 
1309 {
1310  if ((a_GameMode < gmMin) || (a_GameMode >= gmMax))
1311  {
1312  LOGWARNING("%s: Setting invalid gamemode: %d", GetName().c_str(), a_GameMode);
1313  return;
1314  }
1315 
1316  if (m_GameMode == a_GameMode)
1317  {
1318  // New gamemode unchanged, we're done:
1319  return;
1320  }
1321 
1322  m_GameMode = a_GameMode;
1324 
1325  if (IsGameModeSpectator())
1326  {
1327  // Spectators cannot ride entities:
1328  Detach();
1329  }
1330  else
1331  {
1332  // Non-spectators may not spectate:
1333  SpectateEntity(nullptr);
1334  }
1335 
1336  m_ClientHandle->SendGameMode(a_GameMode);
1337  m_ClientHandle->SendInventorySlot(-1, -1, m_DraggingItem);
1340 }
1341 
1342 
1343 
1344 
1345 
1347 {
1348  if (IsGameModeCreative())
1349  {
1350  m_IsFlightCapable = true;
1351  m_IsVisible = true;
1352  }
1353  else if (IsGameModeSpectator())
1354  {
1355  m_DraggingItem.Empty(); // Clear the current dragging item of spectators.
1356  m_IsFlightCapable = true;
1357  m_IsFlying = true; // Spectators are always in flight mode.
1358  m_IsVisible = false; // Spectators are invisible.
1359  }
1360  else
1361  {
1362  m_IsFlightCapable = false;
1363  m_IsFlying = false;
1364  m_IsVisible = true;
1365  }
1366 }
1367 
1368 
1369 
1370 
1371 
1373 {
1374  // Check if the prerequisites are met:
1375  if (!m_Stats.SatisfiesPrerequisite(a_Ach))
1376  {
1377  return;
1378  }
1379 
1380  // Increment the statistic and check if we already have it:
1381  if (m_Stats.Custom[a_Ach]++ != 1)
1382  {
1383  return;
1384  }
1385 
1387  {
1388  cCompositeChat Msg;
1390  // TODO: cCompositeChat should not use protocol-specific strings
1391  // Msg.AddShowAchievementPart(GetName(), nameNew);
1392  Msg.AddTextPart("Achievement get!");
1393  m_World->BroadcastChat(Msg);
1394  }
1395 
1396  // Achievement Get!
1397  m_ClientHandle->SendStatistics(m_Stats);
1398 }
1399 
1400 
1401 
1402 
1403 
1404 void cPlayer::TeleportToCoords(double a_PosX, double a_PosY, double a_PosZ)
1405 {
1406  // ask plugins to allow teleport to the new position.
1407  if (!cRoot::Get()->GetPluginManager()->CallHookEntityTeleport(*this, m_LastPosition, Vector3d(a_PosX, a_PosY, a_PosZ)))
1408  {
1409  m_IsTeleporting = true;
1410 
1411  Detach();
1412  SetPosition({a_PosX, a_PosY, a_PosZ});
1413  FreezeInternal(GetPosition(), false);
1414 
1415  m_ClientHandle->SendPlayerMoveLook();
1416  }
1417 }
1418 
1419 
1420 
1421 
1422 
1423 void cPlayer::Freeze(const Vector3d & a_Location)
1424 {
1425  FreezeInternal(a_Location, true);
1426 }
1427 
1428 
1429 
1430 
1431 
1433 {
1434  return m_IsFrozen;
1435 }
1436 
1437 
1438 
1439 
1440 
1442 {
1443  if (IsElytraFlying())
1444  {
1446  }
1447 
1448  m_ClientHandle->SendPlayerAbilities();
1450 
1451  m_IsFrozen = false;
1454 }
1455 
1456 
1457 
1458 
1459 
1460 void cPlayer::SendRotation(double a_YawDegrees, double a_PitchDegrees)
1461 {
1462  SetYaw(a_YawDegrees);
1463  SetPitch(a_PitchDegrees);
1464  m_ClientHandle->SendPlayerMoveLook();
1465 }
1466 
1467 
1468 
1469 
1470 
1472 {
1473  if (a_Target == this)
1474  {
1475  // Canonicalise self-pointers:
1476  a_Target = nullptr;
1477  }
1478 
1479  if (m_Spectating == a_Target)
1480  {
1481  // Already spectating requested target:
1482  return;
1483  }
1484 
1485  if (a_Target == nullptr)
1486  {
1487  m_Spectating->OnLoseSpectator(*this);
1488  OnLoseSpectated();
1489  return;
1490  }
1491 
1492  m_Spectating = a_Target;
1493  a_Target->OnAcquireSpectator(*this);
1494  m_ClientHandle->SendCameraSetTo(*a_Target);
1495 }
1496 
1497 
1498 
1499 
1500 
1502 {
1503  Vector3d res = GetEyePosition();
1504 
1505  // Adjust the position to be just outside the player's bounding box:
1506  res.x += 0.16 * cos(GetPitch());
1507  res.y += -0.1;
1508  res.z += 0.16 * sin(GetPitch());
1509 
1510  return res;
1511 }
1512 
1513 
1514 
1515 
1516 
1517 Vector3d cPlayer::GetThrowSpeed(double a_SpeedCoeff) const
1518 {
1519  Vector3d res = GetLookVector();
1520  res.Normalize();
1521 
1522  // TODO: Add a slight random change (+-0.0075 in each direction)
1523 
1524  return res * a_SpeedCoeff;
1525 }
1526 
1527 
1528 
1529 
1530 
1532 {
1533  return (m_GameMode == gmNotSet) ? m_World->GetGameMode() : m_GameMode;
1534 }
1535 
1536 
1537 
1538 
1539 
1540 void cPlayer::ForceSetSpeed(const Vector3d & a_Speed)
1541 {
1542  SetSpeed(a_Speed);
1543 }
1544 
1545 
1546 
1547 
1548 
1549 void cPlayer::SetVisible(bool a_bVisible)
1550 {
1551  if (a_bVisible && !m_IsVisible)
1552  {
1553  m_IsVisible = true;
1554  }
1555  if (!a_bVisible && m_IsVisible)
1556  {
1557  m_IsVisible = false;
1558  }
1559 
1561 }
1562 
1563 
1564 
1565 
1566 
1568 {
1569  return m_EnchantmentSeed;
1570 }
1571 
1572 
1573 
1574 
1575 
1577 {
1578  // Get a new random integer and save that as the seed:
1579  m_EnchantmentSeed = GetRandomProvider().RandInt<unsigned int>();
1580 }
1581 
1582 
1583 
1584 
1585 
1586 bool cPlayer::HasPermission(const AString & a_Permission) const
1587 {
1588  if (a_Permission.empty())
1589  {
1590  // Empty permission request is always granted
1591  return true;
1592  }
1593 
1594  AStringVector Split = StringSplit(a_Permission, ".");
1595 
1596  // Iterate over all restrictions; if any matches, then return failure:
1597  for (auto & Restriction: m_SplitRestrictions)
1598  {
1599  if (PermissionMatches(Split, Restriction))
1600  {
1601  return false;
1602  }
1603  } // for Restriction - m_SplitRestrictions[]
1604 
1605  // Iterate over all granted permissions; if any matches, then return success:
1606  for (auto & Permission: m_SplitPermissions)
1607  {
1608  if (PermissionMatches(Split, Permission))
1609  {
1610  return true;
1611  }
1612  } // for Permission - m_SplitPermissions[]
1613 
1614  // No granted permission matches
1615  return false;
1616 }
1617 
1618 
1619 
1620 
1621 
1622 bool cPlayer::PermissionMatches(const AStringVector & a_Permission, const AStringVector & a_Template)
1623 {
1624  // Check the sub-items if they are the same or there's a wildcard:
1625  size_t lenP = a_Permission.size();
1626  size_t lenT = a_Template.size();
1627  size_t minLen = std::min(lenP, lenT);
1628  for (size_t i = 0; i < minLen; i++)
1629  {
1630  if (a_Template[i] == "*")
1631  {
1632  // Has matched so far and now there's a wildcard in the template, so the permission matches:
1633  return true;
1634  }
1635  if (a_Permission[i] != a_Template[i])
1636  {
1637  // Found a mismatch
1638  return false;
1639  }
1640  }
1641 
1642  // So far all the sub-items have matched
1643  // If the sub-item count is the same, then the permission matches
1644  return (lenP == lenT);
1645 }
1646 
1647 
1648 
1649 
1650 
1652 {
1653  if (m_MsgNameColorCode.empty() || (m_MsgNameColorCode == "-"))
1654  {
1655  // Color has not been assigned, return an empty string:
1656  return AString();
1657  }
1658 
1659  // Return the color, including the delimiter:
1661 }
1662 
1663 
1664 
1665 
1666 
1668 {
1669  return m_MsgPrefix;
1670 }
1671 
1672 
1673 
1674 
1675 
1677 {
1678  return m_MsgSuffix;
1679 }
1680 
1681 
1682 
1683 
1684 
1686 {
1687  const AString & Color = GetColor();
1688 
1689  if (HasCustomName())
1690  {
1691  return m_CustomName;
1692  }
1693  else if ((GetName().length() <= 14) && !Color.empty())
1694  {
1695  return fmt::format(FMT_STRING("{}{}"), Color, GetName());
1696  }
1697  else
1698  {
1699  return GetName();
1700  }
1701 }
1702 
1703 
1704 
1705 
1706 
1707 void cPlayer::SetDraggingItem(const cItem & a_Item)
1708 {
1709  if (GetWindow() != nullptr)
1710  {
1711  m_DraggingItem = a_Item;
1713  }
1714 }
1715 
1716 
1717 
1718 
1719 
1720 void cPlayer::TossEquippedItem(char a_Amount)
1721 {
1722  cItems Drops;
1723  cItem DroppedItem(GetInventory().GetEquippedItem());
1724  if (!DroppedItem.IsEmpty())
1725  {
1726  char NewAmount = a_Amount;
1727  if (NewAmount > GetInventory().GetEquippedItem().m_ItemCount)
1728  {
1729  NewAmount = GetInventory().GetEquippedItem().m_ItemCount; // Drop only what's there
1730  }
1731 
1732  GetInventory().GetHotbarGrid().ChangeSlotCount(GetInventory().GetEquippedSlotNum() /* Returns hotbar subslot, which HotbarGrid takes */, -a_Amount);
1733 
1734  DroppedItem.m_ItemCount = NewAmount;
1735  Drops.push_back(DroppedItem);
1736  }
1737 
1738  TossItems(Drops);
1739 }
1740 
1741 
1742 
1743 
1744 
1746 {
1747  auto PlacedCount = GetInventory().ReplaceOneEquippedItem(a_Item);
1748  char ItemCountToToss = a_Item.m_ItemCount - static_cast<char>(PlacedCount);
1749 
1750  if (ItemCountToToss == 0)
1751  {
1752  return;
1753  }
1754 
1755  cItem Pickup = a_Item;
1756  Pickup.m_ItemCount = ItemCountToToss;
1757  TossPickup(Pickup);
1758 }
1759 
1760 
1761 
1762 
1763 
1764 void cPlayer::TossHeldItem(char a_Amount)
1765 {
1766  cItems Drops;
1767  cItem & Item = GetDraggingItem();
1768  if (!Item.IsEmpty())
1769  {
1770  char OriginalItemAmount = Item.m_ItemCount;
1771  Item.m_ItemCount = std::min(OriginalItemAmount, a_Amount);
1772  Drops.push_back(Item);
1773 
1774  if (OriginalItemAmount > a_Amount)
1775  {
1776  Item.m_ItemCount = OriginalItemAmount - a_Amount;
1777  }
1778  else
1779  {
1780  Item.Empty();
1781  }
1782  }
1783 
1784  TossItems(Drops);
1785 }
1786 
1787 
1788 
1789 
1790 
1791 void cPlayer::TossPickup(const cItem & a_Item)
1792 {
1793  cItems Drops;
1794  Drops.push_back(a_Item);
1795 
1796  TossItems(Drops);
1797 }
1798 
1799 
1800 
1801 
1802 
1804 {
1805  RefreshRank();
1806 
1807  Json::Value Root;
1808  const auto & UUID = GetUUID();
1809  const auto & FileName = GetUUIDFileName(UUID);
1810 
1811  try
1812  {
1813  // Load the data from the save file and parse:
1814  InputFileStream(FileName) >> Root;
1815 
1816  // Load the player stats.
1817  // We use the default world name (like bukkit) because stats are shared between dimensions / worlds.
1818  StatisticsSerializer::Load(m_Stats, m_DefaultWorldPath, UUID.ToLongString());
1819  }
1820  catch (const InputFileStream::failure &)
1821  {
1822  if (errno != ENOENT)
1823  {
1824  // Save file exists but unreadable:
1825  throw;
1826  }
1827 
1828  // This is a new player whom we haven't seen yet with no save file, let them have the defaults:
1829  LOG("Player \"%s\" (%s) save or statistics file not found, resetting to defaults", GetName().c_str(), UUID.ToShortString().c_str());
1830  }
1831 
1832  m_CurrentWorldName = Root.get("world", cRoot::Get()->GetDefaultWorld()->GetName()).asString();
1834 
1835  if (const auto & PlayerPosition = Root["position"]; PlayerPosition.size() == 3)
1836  {
1837  SetPosition(PlayerPosition[0].asDouble(), PlayerPosition[1].asDouble(), PlayerPosition[2].asDouble());
1838  }
1839  else
1840  {
1842  }
1843 
1844  if (const auto & PlayerRotation = Root["rotation"]; PlayerRotation.size() == 3)
1845  {
1846  SetYaw (PlayerRotation[0].asDouble());
1847  SetPitch(PlayerRotation[1].asDouble());
1848  SetRoll (PlayerRotation[2].asDouble());
1849  }
1850 
1851  m_Health = Root.get("health", MAX_HEALTH).asFloat();
1852  m_AirLevel = Root.get("air", MAX_AIR_LEVEL).asInt();
1853  m_FoodLevel = Root.get("food", MAX_FOOD_LEVEL).asInt();
1854  m_FoodSaturationLevel = Root.get("foodSaturation", RESPAWN_FOOD_SATURATION).asDouble();
1855  m_FoodTickTimer = Root.get("foodTickTimer", 0).asInt();
1856  m_FoodExhaustionLevel = Root.get("foodExhaustion", 0).asDouble();
1857  m_LifetimeTotalXp = Root.get("xpTotal", 0).asInt();
1858  m_CurrentXp = Root.get("xpCurrent", 0).asInt();
1859  m_IsFlying = Root.get("isflying", 0).asBool();
1860  m_EnchantmentSeed = Root.get("enchantmentSeed", GetRandomProvider().RandInt<unsigned int>()).asUInt();
1861 
1862  Json::Value & JSON_KnownItems = Root["knownItems"];
1863  for (UInt32 i = 0; i < JSON_KnownItems.size(); i++)
1864  {
1865  cItem Item;
1866  Item.FromJson(JSON_KnownItems[i]);
1867  m_KnownItems.insert(Item);
1868  }
1869 
1870  const auto & RecipeNameMap = cRoot::Get()->GetCraftingRecipes()->GetRecipeNameMap();
1871 
1872  Json::Value & JSON_KnownRecipes = Root["knownRecipes"];
1873  for (UInt32 i = 0; i < JSON_KnownRecipes.size(); i++)
1874  {
1875  auto RecipeId = RecipeNameMap.find(JSON_KnownRecipes[i].asString());
1876  if (RecipeId != RecipeNameMap.end())
1877  {
1878  m_KnownRecipes.insert(RecipeId->second);
1879  }
1880  }
1881 
1882  m_GameMode = static_cast<eGameMode>(Root.get("gamemode", eGameMode_NotSet).asInt());
1883 
1884  m_Inventory.LoadFromJson(Root["inventory"]);
1885  m_Inventory.SetEquippedSlotNum(Root.get("equippedItemSlot", 0).asInt());
1886 
1887  cEnderChestEntity::LoadFromJson(Root["enderchestinventory"], m_EnderChestContents);
1888 
1889  m_RespawnPosition.x = Root.get("SpawnX", m_World->GetSpawnX()).asInt();
1890  m_RespawnPosition.y = Root.get("SpawnY", m_World->GetSpawnY()).asInt();
1891  m_RespawnPosition.z = Root.get("SpawnZ", m_World->GetSpawnZ()).asInt();
1892  m_IsRespawnPointForced = Root.get("SpawnForced", true).asBool();
1893  m_SpawnWorldName = Root.get("SpawnWorld", m_World->GetName()).asString();
1894 
1895  FLOGD("Player \"{0}\" with save file \"{1}\" is spawning at {2:.2f} in world \"{3}\"",
1896  GetName(), FileName, GetPosition(), m_World->GetName()
1897  );
1898 }
1899 
1900 
1901 
1902 
1903 
1905 {
1906  if (
1907  (m_AttachedTo == nullptr) ||
1908  !m_AttachedTo->IsMob()
1909  )
1910  {
1911  return;
1912  }
1913 
1914  auto & Mob = static_cast<cMonster &>(*m_AttachedTo);
1915 
1916  if (Mob.GetMobType() != mtHorse)
1917  {
1918  return;
1919  }
1920 
1921  auto & Horse = static_cast<cHorse &>(Mob);
1922  // The client sends requests for untame horses as well but shouldn't actually open
1923  if (Horse.IsTame())
1924  {
1925  Horse.PlayerOpenWindow(*this);
1926  }
1927 }
1928 
1929 
1930 
1931 
1932 
1934 {
1935  const auto & UUID = GetUUID();
1936  cFile::CreateFolderRecursive(GetUUIDFolderName(UUID));
1937 
1938  // create the JSON data
1939  Json::Value JSON_PlayerPosition;
1940  JSON_PlayerPosition.append(Json::Value(GetPosX()));
1941  JSON_PlayerPosition.append(Json::Value(GetPosY()));
1942  JSON_PlayerPosition.append(Json::Value(GetPosZ()));
1943 
1944  Json::Value JSON_PlayerRotation;
1945  JSON_PlayerRotation.append(Json::Value(GetYaw()));
1946  JSON_PlayerRotation.append(Json::Value(GetPitch()));
1947  JSON_PlayerRotation.append(Json::Value(GetRoll()));
1948 
1949  Json::Value JSON_Inventory;
1950  m_Inventory.SaveToJson(JSON_Inventory);
1951 
1952  Json::Value JSON_EnderChestInventory;
1953  cEnderChestEntity::SaveToJson(JSON_EnderChestInventory, m_EnderChestContents);
1954 
1955  Json::Value JSON_KnownItems;
1956  for (const auto & KnownItem : m_KnownItems)
1957  {
1958  Json::Value JSON_Item;
1959  KnownItem.GetJson(JSON_Item);
1960  JSON_KnownItems.append(JSON_Item);
1961  }
1962 
1963  Json::Value JSON_KnownRecipes;
1964  for (auto KnownRecipe : m_KnownRecipes)
1965  {
1966  auto Recipe = cRoot::Get()->GetCraftingRecipes()->GetRecipeById(KnownRecipe);
1967  JSON_KnownRecipes.append(Recipe->m_RecipeName);
1968  }
1969 
1970  Json::Value root;
1971  root["position"] = JSON_PlayerPosition;
1972  root["rotation"] = JSON_PlayerRotation;
1973  root["inventory"] = JSON_Inventory;
1974  root["knownItems"] = JSON_KnownItems;
1975  root["knownRecipes"] = JSON_KnownRecipes;
1976  root["equippedItemSlot"] = m_Inventory.GetEquippedSlotNum();
1977  root["enderchestinventory"] = JSON_EnderChestInventory;
1978  root["health"] = m_Health;
1979  root["xpTotal"] = m_LifetimeTotalXp;
1980  root["xpCurrent"] = m_CurrentXp;
1981  root["air"] = m_AirLevel;
1982  root["food"] = m_FoodLevel;
1983  root["foodSaturation"] = m_FoodSaturationLevel;
1984  root["foodTickTimer"] = m_FoodTickTimer;
1985  root["foodExhaustion"] = m_FoodExhaustionLevel;
1986  root["isflying"] = IsFlying();
1987  root["lastknownname"] = GetName();
1988  root["SpawnX"] = GetLastBedPos().x;
1989  root["SpawnY"] = GetLastBedPos().y;
1990  root["SpawnZ"] = GetLastBedPos().z;
1991  root["SpawnForced"] = m_IsRespawnPointForced;
1992  root["SpawnWorld"] = m_SpawnWorldName;
1993  root["enchantmentSeed"] = m_EnchantmentSeed;
1994  root["world"] = m_CurrentWorldName;
1995  root["gamemode"] = static_cast<int>(m_GameMode);
1996 
1997  auto JsonData = JsonUtils::WriteStyledString(root);
1998  AString SourceFile = GetUUIDFileName(UUID);
1999 
2000  cFile f;
2001  if (!f.Open(SourceFile, cFile::fmWrite))
2002  {
2003  LOGWARNING("Error writing player \"%s\" to file \"%s\": cannot open file. Player will lose their progress",
2004  GetName().c_str(), SourceFile.c_str()
2005  );
2006  return;
2007  }
2008  if (f.Write(JsonData.c_str(), JsonData.size()) != static_cast<int>(JsonData.size()))
2009  {
2010  LOGWARNING("Error writing player \"%s\" to file \"%s\": cannot save data. Player will lose their progress",
2011  GetName().c_str(), SourceFile.c_str()
2012  );
2013  return;
2014  }
2015 
2016  try
2017  {
2018  // Save the player stats.
2019  // We use the default world name (like bukkit) because stats are shared between dimensions / worlds.
2020  // TODO: save together with player.dat, not in some other place.
2022  }
2023  catch (...)
2024  {
2025  LOGWARNING("Error writing player \"%s\" statistics to file", GetName().c_str());
2026  }
2027 }
2028 
2029 
2030 
2031 
2032 
2033 void cPlayer::UseEquippedItem(short a_Damage)
2034 {
2035  // No durability loss in creative or spectator modes:
2037  {
2038  return;
2039  }
2040 
2042 }
2043 
2044 
2045 
2046 
2047 
2049 {
2050  // Get item being used:
2052 
2053  // Get base damage for action type:
2054  short Dmg = Item.GetHandler().GetDurabilityLossByAction(a_Action);
2055 
2056  UseEquippedItem(Dmg);
2057 }
2058 
2059 
2060 
2061 
2062 
2063 void cPlayer::UseItem(int a_SlotNumber, short a_Damage)
2064 {
2065  const cItem & Item = m_Inventory.GetSlot(a_SlotNumber);
2066 
2067  if (Item.IsEmpty())
2068  {
2069  return;
2070  }
2071 
2072  // Ref: https://minecraft.wiki/w/Enchanting#Unbreaking
2073  unsigned int UnbreakingLevel = Item.m_Enchantments.GetLevel(cEnchantments::enchUnbreaking);
2074  double chance = ItemCategory::IsArmor(Item.m_ItemType)
2075  ? (0.6 + (0.4 / (UnbreakingLevel + 1))) : (1.0 / (UnbreakingLevel + 1));
2076 
2077  // When durability is reduced by multiple points
2078  // Unbreaking is applied for each point of reduction.
2079  std::binomial_distribution<short> Dist(a_Damage, chance);
2080  short ReducedDamage = Dist(GetRandomProvider().Engine());
2081 
2082  if (m_Inventory.DamageItem(a_SlotNumber, ReducedDamage))
2083  {
2084  // The item broke. Broadcast the correct animation:
2085  if (Item.m_ItemType == E_ITEM_SHIELD)
2086  {
2088  }
2089  else if (a_SlotNumber == (cInventory::invHotbarOffset + m_Inventory.GetEquippedSlotNum()))
2090  {
2092  }
2093  else
2094  {
2095  switch (a_SlotNumber)
2096  {
2102  }
2103  }
2104  }
2105  else if (Item.m_ItemType == E_ITEM_SHIELD)
2106  {
2107  // The item survived. Special case for shield blocking:
2109  }
2110 }
2111 
2112 
2113 
2114 
2115 
2117 {
2118  // Ref.: https://minecraft.wiki/w/Hunger
2119 
2121  {
2122  // Hunger is disabled for Creative and Spectator
2123  return;
2124  }
2125 
2126  // Apply food exhaustion that has accumulated:
2127  if (m_FoodExhaustionLevel > 4.0)
2128  {
2129  m_FoodExhaustionLevel -= 4.0;
2130 
2131  if (m_FoodSaturationLevel > 0.0)
2132  {
2133  m_FoodSaturationLevel = std::max(m_FoodSaturationLevel - 1.0, 0.0);
2134  }
2135  else
2136  {
2138  }
2139  }
2140 
2141  // Heal or damage, based on the food level, using the m_FoodTickTimer:
2142  if ((m_FoodLevel >= 18) || (m_FoodLevel <= 0))
2143  {
2144  m_FoodTickTimer++;
2145  if (m_FoodTickTimer >= 80)
2146  {
2147  m_FoodTickTimer = 0;
2148 
2149  if ((m_FoodLevel >= 18) && (GetHealth() < GetMaxHealth()))
2150  {
2151  // Regenerate health from food, incur 3 pts of food exhaustion:
2152  Heal(1);
2153  AddFoodExhaustion(3.0);
2154  }
2155  else if ((m_FoodLevel <= 0) && (m_Health > 1))
2156  {
2157  // Damage from starving
2158  TakeDamage(dtStarving, nullptr, 1, 1, 0);
2159  }
2160  }
2161  }
2162  else
2163  {
2164  m_FoodTickTimer = 0;
2165  }
2166 }
2167 
2168 
2169 
2170 
2171 
2173 {
2174  if (GetEquippedItem().m_ItemType == E_ITEM_FISHING_ROD)
2175  {
2176  return;
2177  }
2178  m_World->DoWithEntityByID(m_FloaterID, [](cEntity & a_Entity)
2179  {
2180  a_Entity.Destroy();
2181  return true;
2182  }
2183  );
2184  SetIsFishing(false);
2185 }
2186 
2187 
2188 
2189 
2190 
2191 bool cPlayer::IsClimbing(void) const
2192 {
2193  const auto Position = GetPosition().Floor();
2194 
2195  if (!cChunkDef::IsValidHeight(Position))
2196  {
2197  return false;
2198  }
2199 
2200  BLOCKTYPE Block = m_World->GetBlock(Position);
2201  switch (Block)
2202  {
2203  case E_BLOCK_LADDER:
2204  case E_BLOCK_VINES:
2205  {
2206  return true;
2207  }
2208  default: return false;
2209  }
2210 }
2211 
2212 
2213 
2214 
2215 
2216 void cPlayer::UpdateMovementStats(const Vector3d & a_DeltaPos, bool a_PreviousIsOnGround)
2217 {
2218  if (m_IsTeleporting)
2219  {
2220  m_IsTeleporting = false;
2221  return;
2222  }
2223 
2224  const auto Value = FloorC<StatisticsManager::StatValue>(a_DeltaPos.Length() * 100 + 0.5);
2225  if (m_AttachedTo == nullptr)
2226  {
2227  if (IsFlying())
2228  {
2230  // May be flying and doing any of the following:
2231  }
2232 
2233  if (IsClimbing())
2234  {
2235  if (a_DeltaPos.y > 0.0) // Going up
2236  {
2237  m_Stats.Custom[CustomStatistic::ClimbOneCm] += FloorC<StatisticsManager::StatValue>(a_DeltaPos.y * 100 + 0.5);
2238  }
2239  }
2240  else if (IsInWater())
2241  {
2242  if (m_IsHeadInWater)
2243  {
2245  }
2246  else
2247  {
2249  }
2250  AddFoodExhaustion(0.00015 * static_cast<double>(Value));
2251  }
2252  else if (IsOnGround())
2253  {
2254  if (IsCrouched())
2255  {
2257  AddFoodExhaustion(0.0001 * static_cast<double>(Value));
2258  }
2259  if (IsSprinting())
2260  {
2262  AddFoodExhaustion(0.001 * static_cast<double>(Value));
2263  }
2264  else
2265  {
2267  AddFoodExhaustion(0.0001 * static_cast<double>(Value));
2268  }
2269  }
2270  else
2271  {
2272  // If a jump just started, process food exhaustion:
2273  if ((a_DeltaPos.y > 0.0) && a_PreviousIsOnGround)
2274  {
2276  AddFoodExhaustion((IsSprinting() ? 0.008 : 0.002) * static_cast<double>(Value));
2277  }
2278  else if (a_DeltaPos.y < 0.0)
2279  {
2280  // Increment statistic
2281  m_Stats.Custom[CustomStatistic::FallOneCm] += static_cast<StatisticsManager::StatValue>(-a_DeltaPos.y * 100 + 0.5);
2282  }
2283  // TODO: good opportunity to detect illegal flight (check for falling tho)
2284  }
2285  }
2286  else
2287  {
2288  switch (m_AttachedTo->GetEntityType())
2289  {
2292  case cEntity::etMonster:
2293  {
2294  cMonster * Monster = static_cast<cMonster *>(m_AttachedTo);
2295  switch (Monster->GetMobType())
2296  {
2297  case mtPig: m_Stats.Custom[CustomStatistic::PigOneCm] += Value; break;
2298  case mtHorse: m_Stats.Custom[CustomStatistic::HorseOneCm] += Value; break;
2299  default: break;
2300  }
2301  break;
2302  }
2303  default: break;
2304  }
2305  }
2306 }
2307 
2308 
2309 
2310 
2311 
2313 {
2314  // Update our permissions:
2315  RefreshRank();
2316 
2317  // Send a permission level update:
2318  m_ClientHandle->SendPlayerPermissionLevel();
2319 }
2320 
2321 
2322 
2323 
2324 
2325 void cPlayer::SendBlocksAround(Vector3i a_BlockPos, int a_Range)
2326 {
2327  // Collect the coords of all the blocks to send:
2328  sSetBlockVector blks;
2329  for (int y = a_BlockPos.y - a_Range + 1; y < a_BlockPos.y + a_Range; y++)
2330  {
2331  for (int z = a_BlockPos.z - a_Range + 1; z < a_BlockPos.z + a_Range; z++)
2332  {
2333  for (int x = a_BlockPos.x - a_Range + 1; x < a_BlockPos.x + a_Range; x++)
2334  {
2335  blks.emplace_back(x, y, z, E_BLOCK_AIR, static_cast<NIBBLETYPE>(0)); // Use fake blocktype, it will get set later on.
2336  }
2337  }
2338  } // for y
2339 
2340  // Get the values of all the blocks:
2341  if (!m_World->GetBlocks(blks, false))
2342  {
2343  LOGD("%s: Cannot query all blocks, not sending an update", __FUNCTION__);
2344  return;
2345  }
2346 
2347  // Divide the block changes by their respective chunks:
2348  std::unordered_map<cChunkCoords, sSetBlockVector, cChunkCoordsHash> Changes;
2349  for (const auto & blk: blks)
2350  {
2351  Changes[cChunkCoords(blk.m_ChunkX, blk.m_ChunkZ)].push_back(blk);
2352  } // for blk - blks[]
2353  blks.clear();
2354 
2355  // Send the blocks for each affected chunk:
2356  for (auto itr = Changes.cbegin(), end = Changes.cend(); itr != end; ++itr)
2357  {
2358  m_ClientHandle->SendBlockChanges(itr->first.m_ChunkX, itr->first.m_ChunkZ, itr->second);
2359  }
2360 }
2361 
2362 
2363 
2364 
2365 
2366 bool cPlayer::DoesPlacingBlocksIntersectEntity(const std::initializer_list<sSetBlock> a_Blocks) const
2367 {
2368  // Compute the bounding box for each block to be placed
2369  std::vector<cBoundingBox> PlacementBoxes;
2370  cBoundingBox PlacingBounds(0, 0, 0, 0, 0, 0);
2371  bool HasInitializedBounds = false;
2372  for (auto blk: a_Blocks)
2373  {
2374  int x = blk.GetX();
2375  int y = blk.GetY();
2376  int z = blk.GetZ();
2377  cBoundingBox BlockBox = cBlockHandler::For(blk.m_BlockType).GetPlacementCollisionBox(
2378  m_World->GetBlock({ x - 1, y, z }),
2379  m_World->GetBlock({ x + 1, y, z }),
2380  (y == 0) ? static_cast<BLOCKTYPE>(E_BLOCK_AIR) : m_World->GetBlock({ x, y - 1, z }),
2381  (y == cChunkDef::Height - 1) ? static_cast<BLOCKTYPE>(E_BLOCK_AIR) : m_World->GetBlock({ x, y + 1, z }),
2382  m_World->GetBlock({ x, y, z - 1 }),
2383  m_World->GetBlock({ x, y, z + 1 })
2384  );
2385  BlockBox.Move(x, y, z);
2386 
2387  PlacementBoxes.push_back(BlockBox);
2388 
2389  if (HasInitializedBounds)
2390  {
2391  PlacingBounds = PlacingBounds.Union(BlockBox);
2392  }
2393  else
2394  {
2395  PlacingBounds = BlockBox;
2396  HasInitializedBounds = true;
2397  }
2398  }
2399 
2400  cWorld * World = GetWorld();
2401 
2402  // Check to see if any entity intersects any block being placed
2403  return !World->ForEachEntityInBox(PlacingBounds, [&](cEntity & a_Entity)
2404  {
2405  // The distance inside the block the entity can still be.
2406  const double EPSILON = 0.0005;
2407 
2408  if (!a_Entity.DoesPreventBlockPlacement())
2409  {
2410  return false;
2411  }
2412  auto EntBox = a_Entity.GetBoundingBox();
2413  for (auto BlockBox : PlacementBoxes)
2414  {
2415  // Put in a little bit of wiggle room
2416  BlockBox.Expand(-EPSILON, -EPSILON, -EPSILON);
2417  if (EntBox.DoesIntersect(BlockBox))
2418  {
2419  return true;
2420  }
2421  }
2422  return false;
2423  }
2424  );
2425 }
2426 
2427 
2428 
2429 
2430 
2431 const cUUID & cPlayer::GetUUID(void) const
2432 {
2433  return m_ClientHandle->GetUUID();
2434 }
2435 
2436 
2437 
2438 
2439 
2440 bool cPlayer::PlaceBlock(const Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
2441 {
2442  return PlaceBlocks({ { a_Position, a_BlockType, a_BlockMeta } });
2443 }
2444 
2445 
2446 
2447 
2448 
2449 bool cPlayer::PlaceBlocks(const std::initializer_list<sSetBlock> a_Blocks)
2450 {
2451  if (DoesPlacingBlocksIntersectEntity(a_Blocks))
2452  {
2453  // Abort - re-send all the current blocks in the a_Blocks' coords to the client:
2454  for (const auto & ResendBlock : a_Blocks)
2455  {
2456  m_World->SendBlockTo(ResendBlock.GetX(), ResendBlock.GetY(), ResendBlock.GetZ(), *this);
2457  }
2458  return false;
2459  }
2460 
2462 
2463  // Check the blocks CanBeAt, and call the "placing" hooks; if any fail, abort:
2464  for (const auto & Block : a_Blocks)
2465  {
2466  if (
2467  !m_World->DoWithChunkAt(Block.GetAbsolutePos(), [&Block](cChunk & a_Chunk)
2468  {
2469  return cBlockHandler::For(Block.m_BlockType).CanBeAt(a_Chunk, Block.GetRelativePos(), Block.m_BlockMeta);
2470  })
2471  )
2472  {
2473  return false;
2474  }
2475 
2476  if (pm->CallHookPlayerPlacingBlock(*this, Block))
2477  {
2478  // Abort - re-send all the current blocks in the a_Blocks' coords to the client:
2479  for (const auto & ResendBlock : a_Blocks)
2480  {
2481  m_World->SendBlockTo(ResendBlock.GetX(), ResendBlock.GetY(), ResendBlock.GetZ(), *this);
2482  }
2483  return false;
2484  }
2485  }
2486 
2487  cChunkInterface ChunkInterface(m_World->GetChunkMap());
2488  for (const auto & Block : a_Blocks)
2489  {
2490  // Set the blocks:
2491  m_World->PlaceBlock(Block.GetAbsolutePos(), Block.m_BlockType, Block.m_BlockMeta);
2492 
2493  // Call the "placed" hooks:
2494  pm->CallHookPlayerPlacedBlock(*this, Block);
2495  }
2496 
2497  return true;
2498 }
2499 
2500 
2501 
2502 
2503 
2504 void cPlayer::SetSkinParts(int a_Parts)
2505 {
2506  m_SkinParts = a_Parts & spMask;
2508 }
2509 
2510 
2511 
2512 
2513 
2515 {
2516  AString UUID = a_UUID.ToLongString();
2517 
2518  AString res("players/");
2519  res.append(UUID, 0, 2);
2520  res.push_back('/');
2521  res.append(UUID, 2, AString::npos);
2522  res.append(".json");
2523  return res;
2524 }
2525 
2526 
2527 
2528 
2529 
2530 void cPlayer::FreezeInternal(const Vector3d & a_Location, bool a_ManuallyFrozen)
2531 {
2532  SetSpeed(0, 0, 0);
2533  SetPosition(a_Location);
2534  m_IsFrozen = true;
2535  m_IsManuallyFrozen = a_ManuallyFrozen;
2536 
2537  double NormalMaxSpeed = GetNormalMaxSpeed();
2538  double SprintMaxSpeed = GetSprintingMaxSpeed();
2539  double FlyingMaxpeed = GetFlyingMaxSpeed();
2540  bool IsFlying = m_IsFlying;
2541 
2542  // Set the client-side speed to 0
2543  m_NormalMaxSpeed = 0;
2544  m_SprintingMaxSpeed = 0;
2545  m_FlyingMaxSpeed = 0;
2546  m_IsFlying = true;
2547 
2548  // Send the client its fake speed and max speed of 0
2549  m_ClientHandle->SendPlayerMoveLook();
2550  m_ClientHandle->SendPlayerAbilities();
2551  m_ClientHandle->SendEntityVelocity(*this);
2553 
2554  // Keep the server side speed variables as they were in the first place
2555  m_NormalMaxSpeed = NormalMaxSpeed;
2556  m_SprintingMaxSpeed = SprintMaxSpeed;
2557  m_FlyingMaxSpeed = FlyingMaxpeed;
2558  m_IsFlying = IsFlying;
2559 }
2560 
2561 
2562 
2563 
2564 
2566 {
2567  if (a_Meta >= 8)
2568  {
2569  a_Meta = 0;
2570  }
2571  return static_cast<float>(a_Meta + 1) / 9.0f;
2572 }
2573 
2574 
2575 
2576 
2577 
2579 {
2580  const auto EyePos = GetEyePosition().Floor();
2581 
2582  if (!cChunkDef::IsValidHeight(EyePos))
2583  {
2584  // Not in water if in void.
2585  return false;
2586  }
2587 
2588  BLOCKTYPE Block;
2589  NIBBLETYPE Meta;
2590  m_World->GetBlockTypeMeta(EyePos, Block, Meta);
2591 
2593  {
2594  return false;
2595  }
2596 
2597  const auto EyeHeight = GetEyeHeight();
2598  float f = GetLiquidHeightPercent(Meta) - 0.11111111f;
2599  float f1 = static_cast<float>(EyeHeight + 1) - f;
2600  return EyeHeight < f1;
2601 }
2602 
2603 
2604 
2605 
2606 
2608 {
2609  // Based on: https://minecraft.wiki/w/Breaking#Speed
2610 
2611  // Get the base speed multiplier of the equipped tool for the mined block
2612  float MiningSpeed = GetEquippedItem().GetHandler().GetBlockBreakingStrength(a_Block);
2613 
2614  // If we can harvest the block then we can apply material and enchantment bonuses
2615  if (GetEquippedItem().GetHandler().CanHarvestBlock(a_Block))
2616  {
2617  if (MiningSpeed > 1.0f) // If the base multiplier for this block is greater than 1, now we can check enchantments
2618  {
2619  unsigned int EfficiencyModifier = GetEquippedItem().m_Enchantments.GetLevel(cEnchantments::eEnchantment::enchEfficiency);
2620  if (EfficiencyModifier > 0) // If an efficiency enchantment is present, apply formula as on wiki
2621  {
2622  MiningSpeed += (EfficiencyModifier * EfficiencyModifier) + 1;
2623  }
2624  }
2625  }
2626  else // If we can't harvest the block then no bonuses:
2627  {
2628  MiningSpeed = 1;
2629  }
2630 
2631  // Haste increases speed by 20% per level
2633  if (Haste != nullptr)
2634  {
2635  int intensity = Haste->GetIntensity() + 1;
2636  MiningSpeed *= 1.0f + (intensity * 0.2f);
2637  }
2638 
2639  // Mining fatigue decreases speed a lot
2640  auto MiningFatigue = GetEntityEffect(cEntityEffect::effMiningFatigue);
2641  if (MiningFatigue != nullptr)
2642  {
2643  int intensity = MiningFatigue->GetIntensity();
2644  switch (intensity)
2645  {
2646  case 0: MiningSpeed *= 0.3f; break;
2647  case 1: MiningSpeed *= 0.09f; break;
2648  case 2: MiningSpeed *= 0.0027f; break;
2649  default: MiningSpeed *= 0.00081f; break;
2650 
2651  }
2652  }
2653 
2654  // 5x speed loss for being in water
2655  if (IsInsideWater() && !(GetEquippedItem().m_Enchantments.GetLevel(cEnchantments::eEnchantment::enchAquaAffinity) > 0))
2656  {
2657  MiningSpeed /= 5.0f;
2658  }
2659 
2660  // 5x speed loss for not touching ground
2661  if (!IsOnGround())
2662  {
2663  MiningSpeed /= 5.0f;
2664  }
2665 
2666  return MiningSpeed;
2667 }
2668 
2669 
2670 
2671 
2672 
2674 {
2675  // Based on https://minecraft.wiki/w/Breaking#Calculation
2676  // If we know it's instantly breakable then quit here:
2677  if (cBlockInfo::IsOneHitDig(a_Block))
2678  {
2679  return 1;
2680  }
2681 
2682  const bool CanHarvest = GetEquippedItem().GetHandler().CanHarvestBlock(a_Block);
2683  const float BlockHardness = cBlockInfo::GetHardness(a_Block) * (CanHarvest ? 1.5f : 5.0f);
2684  ASSERT(BlockHardness > 0); // Can't divide by 0 or less, IsOneHitDig should have returned true
2685 
2686  // LOGD("Time to mine block = %f", BlockHardness/DigSpeed);
2687  // Number of ticks to mine = (20 * BlockHardness)/DigSpeed;
2688  // Therefore take inverse to get fraction mined per tick:
2689  return GetDigSpeed(a_Block) / (20.0f * BlockHardness);
2690 }
2691 
2692 
2693 
2694 
2695 
2697 {
2698  // Based on: https://minecraft.wiki/w/Breaking#Calculation
2699 
2700  // If the dig speed is greater than 30 times the hardness, then the wiki says we can instantly mine:
2701  return GetDigSpeed(a_Block) > (30 * cBlockInfo::GetHardness(a_Block));
2702 }
2703 
2704 
2705 
2706 
2707 
2708 void cPlayer::AddKnownItem(const cItem & a_Item)
2709 {
2710  if (a_Item.m_ItemType < 0)
2711  {
2712  return;
2713  }
2714 
2715  auto Response = m_KnownItems.insert(a_Item.CopyOne());
2716  if (!Response.second)
2717  {
2718  // The item was already known, bail out:
2719  return;
2720  }
2721 
2722  // Process the recipes that got unlocked by this newly-known item:
2723  auto Recipes = cRoot::Get()->GetCraftingRecipes()->FindNewRecipesForItem(a_Item, m_KnownItems);
2724  for (const auto & RecipeId : Recipes)
2725  {
2726  AddKnownRecipe(RecipeId);
2727  }
2728 }
2729 
2730 
2731 
2732 
2733 
2735 {
2736  auto Response = m_KnownRecipes.insert(a_RecipeId);
2737  if (!Response.second)
2738  {
2739  // The recipe was already known, bail out:
2740  return;
2741  }
2742  m_ClientHandle->SendUnlockRecipe(a_RecipeId);
2743 }
2744 
2745 
2746 
2747 
2748 
2750 {
2751  if (m_IsFrozen)
2752  {
2753  if ((!m_IsManuallyFrozen) && (GetClientHandle()->IsPlayerChunkSent()))
2754  {
2755  // If the player was automatically frozen, unfreeze if the chunk the player is inside is loaded and sent
2756  Unfreeze();
2757 
2758  // Pull the player out of any solids that might have loaded on them.
2760  if (RelSuccess)
2761  {
2762  int NewY = Rel.y;
2763  if (NewY < 0)
2764  {
2765  NewY = 0;
2766  }
2767  while (NewY < cChunkDef::Height - 2)
2768  {
2769  // If we find a position with enough space for the player
2770  if (
2771  !cBlockInfo::IsSolid(Chunk->GetBlock(Rel.x, NewY, Rel.z)) &&
2772  !cBlockInfo::IsSolid(Chunk->GetBlock(Rel.x, NewY + 1, Rel.z))
2773  )
2774  {
2775  // If the found position is not the same as the original
2776  if (NewY != Rel.y)
2777  {
2778  SetPosition(GetPosition().x, NewY, GetPosition().z);
2780  }
2781  break;
2782  }
2783  ++NewY;
2784  }
2785  }
2786  }
2787  else if ((GetWorld()->GetWorldTickAge() % 100_tick) == 0_tick)
2788  {
2789  // Despite the client side freeze, the player may be able to move a little by
2790  // Jumping or canceling flight. Re-freeze every now and then
2792  }
2793  }
2794  else
2795  {
2796  if (!GetClientHandle()->IsPlayerChunkSent() || (!GetParentChunk()->IsValid()))
2797  {
2798  FreezeInternal(GetPosition(), false);
2799  }
2800  }
2801 }
2802 
2803 
2804 
2805 
2806 
2808 {
2809  const auto & UUID = GetUUID();
2810  cRankManager * RankMgr = cRoot::Get()->GetRankManager();
2811 
2812  // Load the values from cRankManager:
2813  m_Rank = RankMgr->GetPlayerRankName(UUID);
2814  if (m_Rank.empty())
2815  {
2816  m_Rank = RankMgr->GetDefaultRank();
2817  }
2818  else
2819  {
2820  // Update the name:
2821  RankMgr->UpdatePlayerName(UUID, GetName());
2822  }
2823  m_Permissions = RankMgr->GetPlayerPermissions(UUID);
2824  m_Restrictions = RankMgr->GetPlayerRestrictions(UUID);
2826 
2827  // Break up the individual permissions on each dot, into m_SplitPermissions:
2828  m_SplitPermissions.clear();
2829  m_SplitPermissions.reserve(m_Permissions.size());
2830  for (auto & Permission : m_Permissions)
2831  {
2832  m_SplitPermissions.push_back(StringSplit(Permission, "."));
2833  }
2834 
2835  // Break up the individual restrictions on each dot, into m_SplitRestrictions:
2836  m_SplitRestrictions.clear();
2837  m_SplitRestrictions.reserve(m_Restrictions.size());
2838  for (auto & Restriction : m_Restrictions)
2839  {
2840  m_SplitRestrictions.push_back(StringSplit(Restriction, "."));
2841  }
2842 }
2843 
2844 
2845 
2846 
2847 
2848 void cPlayer::ApplyArmorDamage(int a_DamageBlocked)
2849 {
2850  short ArmorDamage = static_cast<short>(std::max(a_DamageBlocked / 4, 1));
2851 
2852  for (int i = 0; i < 4; i++)
2853  {
2854  UseItem(cInventory::invArmorOffset + i, ArmorDamage);
2855  }
2856 }
2857 
2858 
2859 
2860 
2861 
2863 {
2864  if (!m_IsFrozen && m_Speed.SqrLength() > 0.001)
2865  {
2866  // If the player is not frozen, has a non-zero speed,
2867  // send the speed to the client so he is forced to move so:
2868  m_ClientHandle->SendEntityVelocity(*this);
2869  }
2870 
2871  // Since we do no physics processing for players, speed will otherwise never decrease:
2872  m_Speed.Set(0, 0, 0);
2873 
2874  Super::BroadcastMovementUpdate(a_Exclude);
2875 }
2876 
2877 
2878 
2879 
2880 
2882 {
2883  // Filters out damage for creative mode / friendly fire.
2884 
2885  if ((a_TDI.DamageType != dtInVoid) && (a_TDI.DamageType != dtPlugin))
2886  {
2888  {
2889  // No damage / health in creative or spectator mode if not void or plugin damage
2890  return false;
2891  }
2892  }
2893 
2894  if ((a_TDI.Attacker != nullptr) && (a_TDI.Attacker->IsPlayer()))
2895  {
2896  cPlayer * Attacker = static_cast<cPlayer *>(a_TDI.Attacker);
2897 
2898  if ((m_Team != nullptr) && (m_Team == Attacker->m_Team))
2899  {
2900  if (!m_Team->AllowsFriendlyFire())
2901  {
2902  // Friendly fire is disabled
2903  return false;
2904  }
2905  }
2906  }
2907 
2908  if (Super::DoTakeDamage(a_TDI))
2909  {
2910  // Any kind of damage adds food exhaustion
2911  AddFoodExhaustion(0.3f);
2912  m_ClientHandle->SendHealth();
2913 
2914  // Tell the wolves
2915  if (a_TDI.Attacker != nullptr)
2916  {
2917  if (a_TDI.Attacker->IsPawn())
2918  {
2919  NotifyNearbyWolves(static_cast<cPawn*>(a_TDI.Attacker), true);
2920  }
2921  }
2922  m_Stats.Custom[CustomStatistic::DamageTaken] += FloorC<StatisticsManager::StatValue>(a_TDI.FinalDamage * 10 + 0.5);
2923  return true;
2924  }
2925  return false;
2926 }
2927 
2928 
2929 
2930 
2931 
2933 {
2934  if (
2935  IsGameModeSpectator() ||
2936  (IsGameModeCreative() && !IsOnGround())
2937  )
2938  {
2939  return 1; // No impact from explosion
2940  }
2941 
2943 }
2944 
2945 
2946 
2947 
2948 
2949 bool cPlayer::IsCrouched(void) const
2950 {
2951  return std::holds_alternative<BodyStanceCrouching>(m_BodyStance);
2952 }
2953 
2954 
2955 
2956 
2957 
2958 bool cPlayer::IsSprinting(void) const
2959 {
2960  return std::holds_alternative<BodyStanceSprinting>(m_BodyStance);
2961 }
2962 
2963 
2964 
2965 
2966 
2967 bool cPlayer::IsElytraFlying(void) const
2968 {
2969  return std::holds_alternative<BodyStanceGliding>(m_BodyStance);
2970 }
2971 
2972 
2973 
2974 
2975 
2977 {
2978  return !m_IsVisible || Super::IsInvisible();
2979 }
2980 
2981 
2982 
2983 
2984 
2986 {
2987  // Sends player spawn:
2988  Super::OnAddToWorld(a_World);
2989 
2990  // Update world name tracking:
2992 
2993  // Fix to stop the player falling through the world, until we get serversided collision detection:
2994  FreezeInternal(GetPosition(), false);
2995 
2996  // UpdateCapabilities was called in the constructor, and in OnRemoveFromWorld, possibly changing our visibility.
2997  // If world is in spectator mode, invisibility will need updating. If we just connected, we might be on fire from a previous game.
2998  // Hence, tell the client by sending metadata:
2999  m_ClientHandle->SendEntityMetadata(*this);
3000 
3001  // Send contents of the inventory window:
3002  m_ClientHandle->SendWholeInventory(*m_CurrentWindow);
3003 
3004  // Send health (the respawn packet, which understandably resets health, is also used for world travel...):
3005  m_ClientHandle->SendHealth();
3006 
3007  // Send experience, similar story with the respawn packet:
3008  m_ClientHandle->SendExperience();
3009 
3010  // Send hotbar active slot (also reset by respawn):
3011  m_ClientHandle->SendHeldItemChange(m_Inventory.GetEquippedSlotNum());
3012 
3013  // Update player team:
3014  UpdateTeam();
3015 
3016  // Send scoreboard data:
3018 
3019  // Update the view distance:
3020  m_ClientHandle->SetViewDistance(m_ClientHandle->GetRequestedViewDistance());
3021 
3022  // Send current weather of target world:
3023  m_ClientHandle->SendWeather(a_World.GetWeather());
3024 
3025  // Send time:
3026  m_ClientHandle->SendTimeUpdate(a_World.GetWorldAge(), a_World.GetWorldDate(), a_World.IsDaylightCycleEnabled());
3027 
3028  // Finally, deliver the notification hook:
3030 }
3031 
3032 
3033 
3034 
3035 
3037 {
3038  if (m_IsTeleporting)
3039  {
3040  // If they are teleporting, no need to figure out position:
3041  return;
3042  }
3043 
3044  int PosX = POSX_TOINT;
3045  int PosY = POSY_TOINT;
3046  int PosZ = POSZ_TOINT;
3047 
3048  // Search for a position within an area to teleport player after detachment
3049  // Position must be solid land with two air blocks above.
3050  // If nothing found, player remains where they are.
3051  for (int x = PosX - 1; x <= (PosX + 1); ++x)
3052  {
3053  for (int y = PosY; y <= (PosY + 3); ++y)
3054  {
3055  for (int z = PosZ - 1; z <= (PosZ + 1); ++z)
3056  {
3057  if (
3058  (m_World->GetBlock({ x, y, z }) == E_BLOCK_AIR) &&
3059  (m_World->GetBlock({ x, y + 1, z }) == E_BLOCK_AIR) &&
3060  cBlockInfo::IsSolid(m_World->GetBlock({ x, y - 1, z }))
3061  )
3062  {
3063  TeleportToCoords(x + 0.5, y, z + 0.5);
3064  return;
3065  }
3066  }
3067  }
3068  }
3069 }
3070 
3071 
3072 
3073 
3074 
3076 {
3077  Super::OnRemoveFromWorld(a_World);
3078 
3079  // Remove any references to this player pointer by windows in the old world:
3080  CloseWindow(false);
3081 
3082  // Stop spectation and remove our reference from the spectated:
3083  SpectateEntity(nullptr);
3084 
3085  // Remove the client handle from the world:
3087 
3088  if (m_ClientHandle->IsDestroyed()) // Note: checking IsWorldChangeScheduled not appropriate here since we can disconnecting while having a scheduled warp
3089  {
3090  // Disconnecting, do the necessary cleanup.
3091  // This isn't in the destructor to avoid crashing accessing destroyed objects during shutdown.
3092 
3093  if (!cRoot::Get()->GetPluginManager()->CallHookPlayerDestroyed(*this))
3094  {
3095  cRoot::Get()->BroadcastChatLeave(fmt::format(FMT_STRING("{} has left the game"), GetName()));
3096  LOGINFO("Player %s has left the game", GetName());
3097  }
3098 
3099  // Remove ourself from everyone's lists:
3101 
3102  // Atomically decrement player count (in world thread):
3104 
3105  // We're just disconnecting. The remaining code deals with going through portals, so bail:
3106  return;
3107  }
3108 
3109  const auto DestinationDimension = m_WorldChangeInfo.m_NewWorld->GetDimension();
3110 
3111  // Award relevant achievements:
3112  if (DestinationDimension == dimEnd)
3113  {
3115  }
3116  else if (DestinationDimension == dimNether)
3117  {
3119  }
3120 
3121  // Set capabilities based on new world:
3123 
3124  // Clientside warp start:
3125  m_ClientHandle->SendRespawn(DestinationDimension, false);
3126  m_ClientHandle->SendPlayerListUpdateGameMode(*this);
3128 
3129  // Clear sent chunk lists from the clienthandle:
3130  m_ClientHandle->RemoveFromWorld();
3131 }
3132 
3133 
3134 
3135 
3136 
3138 {
3139  if (m_ClientHandle.get() == &a_Client)
3140  {
3141  return;
3142  }
3143 
3144  a_Client.SendPlayerSpawn(*this);
3145  a_Client.SendEntityHeadLook(*this);
3146  a_Client.SendEntityEquipment(*this, 0, m_Inventory.GetEquippedItem());
3147  a_Client.SendEntityEquipment(*this, 1, m_Inventory.GetEquippedBoots());
3148  a_Client.SendEntityEquipment(*this, 2, m_Inventory.GetEquippedLeggings());
3150  a_Client.SendEntityEquipment(*this, 4, m_Inventory.GetEquippedHelmet());
3151 }
3152 
3153 
3154 
3155 
3156 
3157 void cPlayer::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
3158 {
3159  if (m_ClientHandle->IsDestroyed())
3160  {
3161  Destroy();
3162  return;
3163  }
3164 
3165  if (!m_ClientHandle->IsPlaying())
3166  {
3167  // We're not yet in the game, ignore everything:
3168  return;
3169  }
3170 
3171  {
3172  const auto TicksElapsed = static_cast<StatisticsManager::StatValue>(std::chrono::duration_cast<cTickTime>(a_Dt).count());
3173 
3176 
3177  if (IsCrouched())
3178  {
3179  m_Stats.Custom[CustomStatistic::SneakTime] += TicksElapsed;
3180  }
3181  }
3182 
3183  ASSERT((GetParentChunk() != nullptr) && (GetParentChunk()->IsValid()));
3184  ASSERT(a_Chunk.IsValid());
3185 
3186  // Handle a frozen player:
3187  TickFreezeCode();
3188 
3189  if (
3190  m_IsFrozen || // Don't do Tick updates if frozen
3191  IsWorldChangeScheduled() // If we're about to change worlds (e.g. respawn), abort processing all world interactions (GH #3939)
3192  )
3193  {
3194  return;
3195  }
3196 
3197  Super::Tick(a_Dt, a_Chunk);
3198 
3199  // Handle charging the bow:
3200  if (m_IsChargingBow)
3201  {
3202  m_BowCharge += 1;
3203  }
3204 
3205  // Handle syncing our position with the entity being spectated:
3206  if (IsGameModeSpectator() && (m_Spectating != nullptr))
3207  {
3212  }
3213 
3214  if (IsElytraFlying())
3215  {
3216  // Damage elytra, once per second:
3217  {
3218  using namespace std::chrono_literals;
3219 
3220  auto & TicksFlying = std::get<BodyStanceGliding>(m_BodyStance).TicksElytraFlying;
3221  const auto TotalFlew = TicksFlying + a_Dt;
3222  const auto Periods = static_cast<short>(TotalFlew / 1s);
3223  TicksFlying = std::chrono::duration_cast<cTickTime>(TotalFlew - Periods * 1s);
3224 
3225  UseItem(cInventory::invArmorOffset + 1, Periods);
3226  }
3227 
3228  // Check if flight is still possible:
3229  if (IsOnGround() || IsInWater() || IsRiding() || (GetEquippedChestplate().m_ItemType != E_ITEM_ELYTRA))
3230  {
3231  SetElytraFlight(false);
3232  }
3233  }
3234  else if (IsInBed())
3235  {
3236  // Check if sleeping is still possible:
3238  {
3239  m_ClientHandle->HandleLeaveBed();
3240  }
3241  }
3242 
3244 
3245  if (m_Health > 0) // make sure player is alive
3246  {
3247  if ((m_EatingFinishTick >= 0_tick) && (m_EatingFinishTick <= m_World->GetWorldAge()))
3248  {
3249  FinishEating();
3250  }
3251 
3252  HandleFood();
3253  }
3254 
3255  if (m_IsFishing)
3256  {
3257  HandleFloater();
3258  }
3259 
3260  // Update items (e.g. Maps)
3262 
3263  if (m_TicksUntilNextSave == 0)
3264  {
3265  SaveToDisk();
3267  }
3268  else
3269  {
3271  }
3272 }
static int GetBlock(lua_State *a_LuaState)
Templated bindings for the GetBlock___() functions.
@ E_BLOCK_WATER
Definition: BlockType.h:18
@ E_BLOCK_AIR
Definition: BlockType.h:10
@ E_BLOCK_VINES
Definition: BlockType.h:121
@ E_BLOCK_LADDER
Definition: BlockType.h:78
@ E_BLOCK_BED
Definition: BlockType.h:36
@ E_BLOCK_STATIONARY_WATER
Definition: BlockType.h:19
@ E_ITEM_FISHING_ROD
Definition: BlockType.h:391
@ E_ITEM_SHIELD
Definition: BlockType.h:489
@ E_ITEM_ELYTRA
Definition: BlockType.h:490
@ E_ITEM_RED_APPLE
Definition: BlockType.h:304
#define PREPARE_REL_AND_CHUNK(Position, OriginalChunk)
Definition: Chunk.h:32
std::vector< sSetBlock > sSetBlockVector
Definition: ChunkDef.h:441
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
eChatType
Definition: Defines.h:149
@ spMask
Definition: Defines.h:223
@ dimEnd
Definition: Defines.h:234
@ dimNether
Definition: Defines.h:232
eGameMode
Definition: Defines.h:125
@ gmCreative
Definition: Defines.h:135
@ gmNotSet
Definition: Defines.h:133
@ gmMax
Definition: Defines.h:140
@ gmAdventure
Definition: Defines.h:136
@ eGameMode_NotSet
Definition: Defines.h:126
@ gmSurvival
Definition: Defines.h:134
@ gmSpectator
Definition: Defines.h:137
@ gmMin
Definition: Defines.h:141
@ mtWarning
Definition: Defines.h:360
@ mtPrivateMessage
Definition: Defines.h:363
@ mtSuccess
Definition: Defines.h:359
@ mtCustom
Definition: Defines.h:356
@ mtInformation
Definition: Defines.h:358
@ mtFailure
Definition: Defines.h:357
eDamageType
Damage type, used in the TakeDamageInfo structure and related functions.
Definition: Defines.h:244
@ dtStarving
Definition: Defines.h:252
@ dtInVoid
Definition: Defines.h:260
@ dtRangedAttack
Definition: Defines.h:247
@ dtPlugin
Definition: Defines.h:289
std::vector< int > cSlotNums
List of slot numbers, used for inventory-painting.
Definition: Defines.h:9
#define POSX_TOINT
Definition: Entity.h:31
#define POSZ_TOINT
Definition: Entity.h:33
#define POSY_TOINT
Definition: Entity.h:32
#define EATING_TICKS
Definition: Player.cpp:64
#define RESPAWN_FOOD_SATURATION
Definition: Player.cpp:70
#define XP_TO_LEVEL15
Definition: Player.cpp:72
#define XP_PER_LEVEL_TO15
Definition: Player.cpp:73
#define PLAYER_INVENTORY_SAVE_INTERVAL
Definition: Player.cpp:67
#define XP_TO_LEVEL30
Definition: Player.cpp:74
MTRand & GetRandomProvider()
Returns the current thread's random number source.
Definition: FastRandom.cpp:12
unsigned int UInt32
Definition: Globals.h:157
T Clamp(T a_Value, T a_Min, T a_Max)
Clamp X to the specified range.
Definition: Globals.h:336
#define ASSERT(x)
Definition: Globals.h:276
#define UNUSED
Definition: Globals.h:72
#define FLOGD
Definition: LoggerSimple.h:91
void LOGWARNING(std::string_view a_Format, const Args &... args)
Definition: LoggerSimple.h:67
void LOG(std::string_view a_Format, const Args &... args)
Definition: LoggerSimple.h:55
#define LOGD
Definition: LoggerSimple.h:83
void LOGINFO(std::string_view a_Format, const Args &... args)
Definition: LoggerSimple.h:61
@ mtSkeleton
Definition: MonsterTypes.h:59
@ mtPig
Definition: MonsterTypes.h:47
@ mtHorse
Definition: MonsterTypes.h:34
FileStream< std::ifstream > InputFileStream
Definition: File.h:196
CustomStatistic
Item
Definition: Items.h:4
AStringVector StringSplit(const AString &str, const AString &delim)
Split the string at any of the listed delimiters.
Definition: StringUtils.cpp:55
std::vector< AString > AStringVector
Definition: StringUtils.h:12
std::string AString
Definition: StringUtils.h:11
Vector3< double > Vector3d
Definition: Vector3.h:485
Vector3< int > Vector3i
Definition: Vector3.h:487
bool IsArmor(short a_ItemType)
Definition: Defines.cpp:588
AString WriteStyledString(const Json::Value &a_Root)
Definition: JsonUtils.cpp:24
Utilities to allow casting a cWorld to one of its interfaces without including World....
Definition: OpaqueWorld.h:13
void Save(const StatisticsManager &Manager, const std::string &WorldPath, std::string &&FileName)
void Load(StatisticsManager &Manager, const std::string &WorldPath, std::string &&FileName)
static cPluginManager * Get(void)
Returns the instance of the Plugin Manager (there is only ever one)
bool CallHookPlayerCrouched(cPlayer &a_Player)
bool CallHookPlayerPlacingBlock(cPlayer &a_Player, const sSetBlock &a_BlockChange)
bool CallHookPlayerSpawned(cPlayer &a_Player)
bool CallHookPlayerPlacedBlock(cPlayer &a_Player, const sSetBlock &a_BlockChange)
static void LoadFromJson(const Json::Value &a_Value, cItemGrid &a_Grid)
static void SaveToJson(Json::Value &a_Value, const cItemGrid &a_Grid)
static float GetHardness(BLOCKTYPE Block)
Block's hardness.
Definition: BlockInfo.cpp:1187
static bool IsSolid(BLOCKTYPE Block)
Is this block solid (player cannot walk through)?
Definition: BlockInfo.cpp:892
static bool IsOneHitDig(BLOCKTYPE Block)
Is a block destroyed after a single hit? Warning: IsOneHitDig does not take into account enchantments...
Definition: BlockInfo.cpp:731
virtual cBoundingBox GetPlacementCollisionBox(BLOCKTYPE a_XM, BLOCKTYPE a_XP, BLOCKTYPE a_YM, BLOCKTYPE a_YP, BLOCKTYPE a_ZM, BLOCKTYPE a_ZP) const
Returns the relative bounding box that must be entity-free in order for the block to be placed.
static const cBlockHandler & For(BLOCKTYPE a_BlockType)
Represents two sets of coords, minimum and maximum for each direction.
Definition: BoundingBox.h:24
void Move(double a_OffX, double a_OffY, double a_OffZ)
Moves the entire boundingbox by the specified offset.
Definition: BoundingBox.cpp:62
void Expand(double a_ExpandX, double a_ExpandY, double a_ExpandZ)
Expands the bounding box by the specified amount in each direction (so the box becomes larger by 2 * ...
Definition: BoundingBox.cpp:90
cBoundingBox Union(const cBoundingBox &a_Other)
Returns the union of the two bounding boxes.
static const char * Delimiter
Definition: ChatColor.h:12
Definition: Chunk.h:36
bool IsValid(void) const
Returns true iff the chunk block data is valid (loaded / generated)
Definition: Chunk.h:58
Wraps the chunk coords into a single structure.
Definition: ChunkDef.h:57
static bool IsValidHeight(Vector3i a_BlockPosition)
Validates a height-coordinate.
Definition: ChunkDef.h:185
static const int Height
Definition: ChunkDef.h:125
void SendEntityHeadLook(const cEntity &a_Entity)
void SendInventorySlot(char a_WindowID, short a_SlotNum, const cItem &a_Item)
void SendPlayerSpawn(const cPlayer &a_Player)
void SendEntityEquipment(const cEntity &a_Entity, short a_SlotNum, const cItem &a_Item)
void SendPlayerPosition(void)
Container for a single chat message composed of multiple functional parts.
Definition: CompositeChat.h:34
void SetMessageType(eMessageType a_MessageType, const AString &a_AdditionalMessageTypeData="")
Sets the message type, which is indicated by prefixes added to the message when serializing Takes opt...
void AddTextPart(const AString &a_Message, const AString &a_Style="")
Adds a plain text part, with optional style.
const std::map< AString, UInt32 > & GetRecipeNameMap()
Gets a map of all recipes with name and recipe id.
cRecipe * GetRecipeById(UInt32 a_RecipeId)
Returns the recipe by id.
std::vector< UInt32 > FindNewRecipesForItem(const cItem &a_Item, const std::set< cItem, cItem::sItemCompare > &a_KnownItems)
Find recipes and returns the RecipeIds which contain the new item and all ingredients are in the know...
unsigned int GetLevel(int a_EnchantmentID) const
Returns the level for the specified enchantment; 0 if not stored.
cEntity * Attacker
Definition: Entity.h:62
eDamageType DamageType
Definition: Entity.h:61
float FinalDamage
Definition: Entity.h:64
Definition: Entity.h:76
float m_Health
Definition: Entity.h:584
void SetPitch(double a_Pitch)
Definition: Entity.cpp:2136
virtual void OnAddToWorld(cWorld &a_World)
Called when the entity is added to a world.
Definition: Entity.cpp:147
bool IsPlayer(void) const
Definition: Entity.h:160
Vector3d m_LastPosition
Definition: Entity.h:620
cBoundingBox GetBoundingBox() const
Definition: Entity.h:211
void BroadcastDeathMessage(TakeDamageInfo &a_TDI)
Announces a death message on chat about killing the entity.
Definition: Entity.cpp:2349
void SetRoll(double a_Roll)
Definition: Entity.cpp:2147
virtual float GetEnchantmentBlastKnockbackReduction()
Returns explosion knock back reduction percent from blast protection level.
Definition: Entity.cpp:744
void Detach(void)
Detaches from the currently attached entity, if any.
Definition: Entity.cpp:2052
virtual bool IsInWater(void) const
Returns true if any part of the entity is in a water block.
Definition: Entity.h:501
bool MoveToWorld(cWorld &a_World, Vector3d a_NewPosition, bool a_ShouldSetPortalCooldown=false, bool a_ShouldSendRespawn=true)
Definition: Entity.cpp:1616
void SetYaw(double a_Yaw)
Definition: Entity.cpp:2125
cChunk * GetParentChunk()
Returns the chunk responsible for ticking this entity.
Definition: Entity.h:541
float GetMaxHealth(void) const
Definition: Entity.h:407
virtual bool DoesPreventBlockPlacement(void) const
Returns whether blocks can be placed intersecting this entities' hitbox.
Definition: Entity.h:188
static const UInt32 INVALID_ID
Special ID that is considered an "invalid value", signifying no entity.
Definition: Entity.h:128
int m_AirLevel
Air level of a mobile.
Definition: Entity.h:660
double GetRoll(void) const
Definition: Entity.h:200
void SetSpeed(double a_SpeedX, double a_SpeedY, double a_SpeedZ)
Sets the speed of the entity, measured in m / sec.
Definition: Entity.cpp:2157
double GetPosX(void) const
Definition: Entity.h:195
sWorldChangeInfo m_WorldChangeInfo
If field m_NewWorld not nullptr, a world change is scheduled and a task is queued in the current worl...
Definition: Entity.h:627
void SetPosition(double a_PosX, double a_PosY, double a_PosZ)
Definition: Entity.h:218
cWorld * m_World
Definition: Entity.h:624
double GetPosZ(void) const
Definition: Entity.h:197
UInt32 GetUniqueID(void) const
Definition: Entity.h:253
void OnAcquireSpectator(cPlayer &a_Player)
Called when a player begins spectating this entity.
Definition: Entity.cpp:138
void Destroy()
Destroys the entity, schedules it for memory freeing and broadcasts the DestroyEntity packet.
Definition: Entity.cpp:243
bool IsWorldChangeScheduled() const
Returns true if a world change is scheduled to happen.
Definition: Entity.h:450
void SetInvulnerableTicks(int a_InvulnerableTicks)
Set the invulnerable ticks from the entity.
Definition: Entity.h:516
eEntityType GetEntityType(void) const
Definition: Entity.h:156
double GetPitch(void) const
Definition: Entity.h:199
double GetPosY(void) const
Definition: Entity.h:196
Vector3d m_Speed
Measured in meters / second (m / s)
Definition: Entity.h:577
bool m_IsHeadInWater
If the entity's head is in a water block.
Definition: Entity.h:657
void TakeDamage(cEntity &a_Attacker)
Makes this pawn take damage from an attack by a_Attacker.
Definition: Entity.cpp:272
bool IsPawn(void) const
Definition: Entity.h:163
virtual bool DoTakeDamage(TakeDamageInfo &a_TDI)
Makes this entity take damage specified in the a_TDI.
Definition: Entity.cpp:404
void StopBurning(void)
Stops the entity from burning, resets all burning timers.
Definition: Entity.cpp:1925
double GetYaw(void) const
Definition: Entity.h:198
float GetHealth(void) const
Returns the health of this entity.
Definition: Entity.h:367
void SetMaxHealth(float a_MaxHealth)
Sets the maximum value for the health.
Definition: Entity.cpp:1887
const Vector3d & GetPosition(void) const
Exported in ManualBindings.
Definition: Entity.h:297
virtual void Heal(int a_HitPoints)
Heals the specified amount of HPs.
Definition: Entity.cpp:890
virtual bool IsRiding(void) const
Definition: Entity.h:491
void SetSize(float a_Width, float a_Height)
Update an entity's size, for example, on body stance changes.
Definition: Entity.cpp:1788
Vector3d GetLookVector(void) const
Definition: Entity.cpp:2267
@ etMinecart
Definition: Entity.h:96
@ etMonster
Definition: Entity.h:94
@ etBoat
Definition: Entity.h:97
@ etPlayer
Definition: Entity.h:92
void OnLoseSpectator(cPlayer &a_Player)
Called when a player stops spectating this entity.
Definition: Entity.cpp:159
virtual void BroadcastMovementUpdate(const cClientHandle *a_Exclude=nullptr)
Updates clients of changes in the entity.
Definition: Entity.cpp:1966
cWorld * GetWorld(void) const
Definition: Entity.h:190
static const int MAX_AIR_LEVEL
Maximum air an entity can have.
Definition: Entity.h:121
cEntity * m_AttachedTo
The entity to which this entity is attached (vehicle), nullptr if none.
Definition: Entity.h:588
bool IsMob(void) const
Definition: Entity.h:162
Definition: Pawn.h:17
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 Tick(std::chrono::milliseconds a_Dt, cChunk &a_Chunk) override
Definition: Pawn.cpp:32
virtual void OnRemoveFromWorld(cWorld &a_World) override
Called when the entity is removed from a world.
Definition: Pawn.cpp:556
virtual void KilledBy(TakeDamageInfo &a_TDI) override
Called when the health drops below zero.
Definition: Pawn.cpp:129
Definition: Player.h:29
cTeam * UpdateTeam(void)
Forces the player to query the scoreboard for his team.
Definition: Player.cpp:1103
void SendMessage(const AString &a_Message)
Definition: Player.cpp:1182
void SendMessageWarning(const AString &a_Message)
Definition: Player.cpp:1218
std::string m_CurrentWorldName
The name of the world which the player currently resides in.
Definition: Player.h:667
cClientHandle * GetClientHandle(void) const
Definition: Player.h:276
bool m_IsFlightCapable
If this is true the player can fly.
Definition: Player.h:700
void SendAboveActionBarMessage(const AString &a_Message)
Definition: Player.cpp:1272
void SetFlying(bool a_ShouldFly)
Starts or stops flying, broadcasting the state change.
Definition: Player.cpp:700
const AString & GetName(void) const
Definition: Player.cpp:1299
int m_SkinParts
Displayed skin part bit mask.
Definition: Player.h:748
bool m_IsFrozen
If true, we are locking m_Position to m_FrozenPosition.
Definition: Player.h:705
const cSlotNums & GetInventoryPaintSlots(void) const
Returns the list of slots currently stored for inventory painting.
Definition: Player.cpp:581
Vector3i GetLastBedPos(void) const
Gets the player's potential respawn position (named LastBedPos for compatibility reasons).
Definition: Player.h:515
bool IsStanding() const
Returns true if a player is standing normally, that is, in a neutral pose.
Definition: Player.cpp:469
void HandleFood(void)
Called in each tick to handle food-related processing.
Definition: Player.cpp:2116
void ClearInventoryPaintSlots(void)
Clears the list of slots that are being inventory-painted.
Definition: Player.cpp:561
AString m_CustomName
Definition: Player.h:745
eGameMode m_GameMode
Definition: Player.h:672
void UpdateMovementStats(const Vector3d &a_DeltaPos, bool a_PreviousIsOnGround)
Update movement-related statistics.
Definition: Player.cpp:2216
void AwardAchievement(CustomStatistic a_Ach)
Awards the player an achievement.
Definition: Player.cpp:1372
bool m_IsChargingBow
Definition: Player.h:696
void HandleFloater(void)
Called in each tick if the player is fishing to make sure the floater dissapears when the player does...
Definition: Player.cpp:2172
AString GetColor(void) const
Returns the full color code to use for this player, based on their rank.
Definition: Player.cpp:1651
unsigned int m_TicksUntilNextSave
How long till the player's inventory will be saved Default save interval is #defined in PLAYER_INVENT...
Definition: Player.h:743
std::string m_SpawnWorldName
The name of the world which the player respawns in upon death.
Definition: Player.h:663
bool DoesPlacingBlocksIntersectEntity(std::initializer_list< sSetBlock > a_Blocks) const
Whether placing the given blocks would intersect any entitiy.
Definition: Player.cpp:2366
bool SetCurrentExperience(int a_XpTotal)
Sets the experience total Returns true on success "should" really only be called at init or player de...
Definition: Player.cpp:259
std::variant< BodyStanceCrouching, BodyStanceSleeping, BodyStanceSprinting, BodyStanceStanding, BodyStanceGliding > m_BodyStance
The current body stance the player has adopted.
Definition: Player.h:612
void LoadFromDisk()
Loads the player data from the save file.
Definition: Player.cpp:1803
void SendMessageInfo(const AString &a_Message)
Definition: Player.cpp:1191
bool IsFrozen()
Is the player frozen?
Definition: Player.cpp:1432
void AddInventoryPaintSlot(int a_SlotNum)
Adds a slot to the list for inventory painting.
Definition: Player.cpp:571
double GetSprintingMaxSpeed(void) const
Gets the sprinting relative maximum speed.
Definition: Player.h:472
double m_NormalMaxSpeed
Max speed, relative to the game default.
Definition: Player.h:684
virtual cItem GetEquippedChestplate(void) const override
Returns the currently equipped chestplate; empty item if none.
Definition: Player.h:599
void SetNormalMaxSpeed(double a_Speed)
Sets the normal relative maximum speed.
Definition: Player.cpp:611
cWorld * GetRespawnWorld()
Definition: Player.cpp:817
double m_FlyingMaxSpeed
Max speed, relative to the game default flying max speed, when flying.
Definition: Player.h:694
void CloseWindow(bool a_CanRefuse=true)
Closes the current window, resets current window to m_InventoryWindow.
Definition: Player.cpp:1144
cTeam * m_Team
Definition: Player.h:734
void RefreshRank()
(Re)loads the rank and permissions from the cRankManager.
Definition: Player.cpp:2807
const cUUID & GetUUID(void) const
Returns the UUID that has been read from the client, or nil if not available.
Definition: Player.cpp:2431
UInt32 m_FloaterID
Definition: Player.h:732
bool m_IsLeftHanded
Whether the player is left-handed, or right-handed.
Definition: Player.h:708
virtual void Killed(const cEntity &a_Victim, eDamageType a_DamageType) override
Called when the entity kills another entity.
Definition: Player.cpp:896
bool m_IsFishing
Definition: Player.h:697
double m_SprintingMaxSpeed
Max speed, relative to the game default max speed, when sprinting.
Definition: Player.h:689
void Respawn(void)
Definition: Player.cpp:936
void SendRotation(double a_YawDegrees, double a_PitchDegrees)
Sends the "look" packet to the player, forcing them to set their rotation to the specified values.
Definition: Player.cpp:1460
cItemGrid m_EnderChestContents
An item grid that stores the player specific enderchest contents.
Definition: Player.h:652
bool PlaceBlocks(std::initializer_list< sSetBlock > a_Blocks)
Calls the block placement hooks and places the blocks in the world.
Definition: Player.cpp:2449
void TossItems(const cItems &a_Items)
Tosses a list of items.
Definition: Player.cpp:478
const cItem & GetEquippedItem(void) const
Definition: Player.h:162
void CancelChargingBow(void)
Cancels the current bow charging.
Definition: Player.cpp:339
cPlayer(const std::shared_ptr< cClientHandle > &a_Client)
Definition: Player.cpp:117
bool HasCustomName(void) const
Returns true if the player has a custom name.
Definition: Player.h:505
bool Feed(int a_Food, double a_Saturation)
Adds to FoodLevel and FoodSaturationLevel, returns true if any food has been consumed,...
Definition: Player.cpp:423
float GetXpPercentage(void) const
Gets the experience bar percentage - XpP.
Definition: Player.cpp:246
void SpectateEntity(cEntity *a_Target)
Spectates the target entity.
Definition: Player.cpp:1471
void SendSystemMessage(const AString &a_Message)
Definition: Player.cpp:1263
void UpdateCapabilities()
Updates player's capabilities - flying, visibility, etc.
Definition: Player.cpp:1346
virtual void Tick(std::chrono::milliseconds a_Dt, cChunk &a_Chunk) override
Definition: Player.cpp:3157
void SendMessageFatal(const AString &a_Message)
Definition: Player.cpp:1227
void AbortEating(void)
Aborts the current eating operation.
Definition: Player.cpp:551
static bool PermissionMatches(const AStringVector &a_Permission, const AStringVector &a_Template)
Returns true iff a_Permission matches the a_Template.
Definition: Player.cpp:1622
std::string m_DefaultWorldPath
The save path of the default world.
Definition: Player.h:670
void SetIsFishing(bool a_IsFishing, UInt32 a_FloaterID=cEntity::INVALID_ID)
Definition: Player.h:388
void SaveToDisk(void)
Saves all player data, such as inventory, to JSON.
Definition: Player.cpp:1933
virtual bool IsInvisible() const override
Definition: Player.cpp:2976
int FinishChargingBow(void)
Finishes charging the current bow.
Definition: Player.cpp:324
void OpenWindow(cWindow &a_Window)
Opens the specified window; closes the current one first using CloseWindow()
Definition: Player.cpp:1123
void AddKnownItem(const cItem &a_Item)
Adds an Item to the list of known items.
Definition: Player.cpp:2708
double GetEyeHeight(void) const
Definition: Player.cpp:992
float GetDigSpeed(BLOCKTYPE a_Block)
Returns the dig speed using the current tool on the block a_Block.
Definition: Player.cpp:2607
AStringVector m_Permissions
All the permissions that this player has, based on their rank.
Definition: Player.h:618
bool IsGameModeSurvival(void) const
Returns true if the player is in Survival mode, either explicitly, or by inheriting from current worl...
Definition: Player.cpp:1034
virtual void ApplyArmorDamage(int DamageBlocked) override
Applies damage to the armor after the armor blocked the given amount.
Definition: Player.cpp:2848
void OpenHorseInventory()
Opens the inventory of any tame horse the player is riding.
Definition: Player.cpp:1904
std::set< cItem, cItem::sItemCompare > m_KnownItems
List of known items as Ids.
Definition: Player.h:754
void TossPickup(const cItem &a_Item)
tosses a pickup newly created from a_Item
Definition: Player.cpp:1791
virtual bool IsElytraFlying(void) const override
Definition: Player.cpp:2967
void SendMessageFailure(const AString &a_Message)
Definition: Player.cpp:1200
void LoadRank(void)
(Re)loads the rank and permissions from the cRankManager and sends a permission level update to the c...
Definition: Player.cpp:2312
int m_CurrentXp
Definition: Player.h:727
double m_FoodSaturationLevel
"Overcharge" for the m_FoodLevel; is depleted before m_FoodLevel
Definition: Player.h:640
bool m_IsManuallyFrozen
Was the player frozen manually by a plugin or automatically by the server?
Definition: Player.h:711
int DeltaExperience(int a_Xp_delta)
Definition: Player.cpp:279
std::shared_ptr< cClientHandle > m_ClientHandle
Definition: Player.h:677
double GetFlyingMaxSpeed(void) const
Gets the flying relative maximum speed.
Definition: Player.h:475
void AddKnownRecipe(UInt32 RecipeId)
Add the recipe Id to the known recipes.
Definition: Player.cpp:2734
int m_FoodLevel
Represents the food bar, one point equals half a "drumstick".
Definition: Player.h:637
void SetBedPos(Vector3i a_Position)
Sets the player's bed position to the specified position.
Definition: Player.cpp:786
void SetFoodTickTimer(int a_FoodTickTimer)
Definition: Player.cpp:405
AString GetSuffix(void) const
Returns the player name suffix, may contain @ format directives.
Definition: Player.cpp:1676
int GetXpLevel(void) const
Gets the current level - XpLevel.
Definition: Player.cpp:237
void SetSprintingMaxSpeed(double a_Speed)
Sets the sprinting relative maximum speed.
Definition: Player.cpp:626
virtual void Heal(int a_Health) override
Heals the player by the specified amount of HPs (positive only); sends health update.
Definition: Player.cpp:369
void UseItem(int a_SlotNumber, short a_Damage=1)
Damage the item in a_SlotNumber by a_Damage, possibly less if the equipped item is enchanted.
Definition: Player.cpp:2063
void SetFlyingMaxSpeed(double a_Speed)
Sets the flying relative maximum speed.
Definition: Player.cpp:641
void TickFreezeCode()
Definition: Player.cpp:2749
void NotifyNearbyWolves(cPawn *a_Opponent, bool a_IsPlayerInvolved)
Notify nearby wolves that the player or one of the player's wolves took damage or did damage to an en...
Definition: Player.cpp:831
static const int MAX_HEALTH
Definition: Player.h:85
AString GetIP(void) const
Definition: Player.cpp:1070
virtual bool IsCrouched(void) const override
Definition: Player.cpp:2949
bool IsLeftHanded() const
Returns true if the player's left hand is dominant.
Definition: Player.cpp:460
bool m_IsTeleporting
Flag used by food handling system to determine whether a teleport has just happened.
Definition: Player.h:718
int m_LifetimeTotalXp
Player Xp level.
Definition: Player.h:726
void TossEquippedItem(char a_Amount=1)
tosses the item in the selected hotbar slot
Definition: Player.cpp:1720
void StartChargingBow(void)
Starts charging the equipped bow.
Definition: Player.cpp:312
static int CalcLevelFromXp(int a_CurrentXp)
Inverse of XpForLevel Ref: https://minecraft.wiki/w/XP values are as per this with pre-calculations.
Definition: Player.cpp:184
bool m_IsFlying
Definition: Player.h:702
cItem m_DraggingItem
The item being dragged by the cursor while in a UI window.
Definition: Player.h:675
AString GetUUIDFileName(const cUUID &a_UUID)
Returns the filename for the player data based on the UUID given.
Definition: Player.cpp:2514
void SetDraggingItem(const cItem &a_Item)
In UI windows, set the item that the player is dragging.
Definition: Player.cpp:1707
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
unsigned int m_EnchantmentSeed
Definition: Player.h:728
bool IsClimbing(void) const
Returns whether the player is climbing (ladders, vines etc.)
Definition: Player.cpp:2191
void SetRespawnPosition(Vector3i a_Position, const cWorld &a_World)
Sets the player's forced respawn position and world.
Definition: Player.cpp:806
virtual ~cPlayer() override
Definition: Player.cpp:155
cWindow * m_InventoryWindow
Definition: Player.h:655
cTickTimeLong m_EatingFinishTick
The world tick in which eating will be finished.
Definition: Player.h:723
cInventory & GetInventory(void)
Definition: Player.h:156
virtual void KilledBy(TakeDamageInfo &a_TDI) override
Called when the health drops below zero.
Definition: Player.cpp:855
void TossHeldItem(char a_Amount=1)
tosses the item held in hand (when in UI windows)
Definition: Player.cpp:1764
virtual void TeleportToCoords(double a_PosX, double a_PosY, double a_PosZ) override
Teleports to the coordinates specified.
Definition: Player.cpp:1404
void SetVisible(bool a_bVisible)
Definition: Player.cpp:1549
void FreezeInternal(const Vector3d &a_Location, bool a_ManuallyFrozen)
Pins the player to a_Location until Unfreeze() is called.
Definition: Player.cpp:2530
virtual void OnDetach() override
Called when this entity dismounts from m_AttachedTo.
Definition: Player.cpp:3036
cItem & GetDraggingItem(void)
In UI windows, get the item that the player is dragging.
Definition: Player.h:448
virtual void BroadcastMovementUpdate(const cClientHandle *a_Exclude=nullptr) override
Updates clients of changes in the entity.
Definition: Player.cpp:2862
void AddFoodExhaustion(double a_Exhaustion)
Adds the specified exhaustion to m_FoodExhaustion.
Definition: Player.cpp:439
bool CanMobsTarget(void) const
Returns true if the player can be targeted by Mobs.
Definition: Player.cpp:1061
void SetFoodLevel(int a_FoodLevel)
Definition: Player.cpp:379
static const int MAX_FOOD_LEVEL
Definition: Player.h:87
Vector3d GetThrowSpeed(double a_SpeedCoeff) const
Returns the initial speed vector of a throw, with a 3D length of a_SpeedCoeff.
Definition: Player.cpp:1517
void Freeze(const Vector3d &a_Location)
Prevent the player from moving and lock him into a_Location.
Definition: Player.cpp:1423
bool IsInBed(void) const
Returns true if a player is sleeping in a bed.
Definition: Player.cpp:451
AStringVector m_Restrictions
All the restrictions that this player has, based on their rank.
Definition: Player.h:621
cEntity * m_Spectating
The entity that this player is spectating, nullptr if none.
Definition: Player.h:737
void PermuteEnchantmentSeed()
Permute the seed for enchanting related PRNGs, don't use this for other purposes.
Definition: Player.cpp:1576
void SetSkinParts(int a_Parts)
Definition: Player.cpp:2504
double GetNormalMaxSpeed(void) const
Gets the normal relative maximum speed.
Definition: Player.h:469
bool IsGameModeSpectator(void) const
Returns true if the player is in Spectator mode, either explicitly, or by inheriting from current wor...
Definition: Player.cpp:1052
void SetLeftHanded(bool a_IsLeftHanded)
Sets the dominant hand of the player.
Definition: Player.cpp:719
int m_FoodTickTimer
Count-up to the healing or damaging action, based on m_FoodLevel.
Definition: Player.h:643
bool CanInstantlyMine(BLOCKTYPE a_Block)
Given tool, enchantments, status effects, and world position returns whether a_Block would be instant...
Definition: Player.cpp:2696
bool HasPermission(const AString &a_Permission) const
Definition: Player.cpp:1586
bool IsFlying(void) const
Returns true if the player is currently flying.
Definition: Player.h:377
bool IsInsideWater()
Checks if the player is inside of water.
Definition: Player.cpp:2578
void SendMessageSuccess(const AString &a_Message)
Definition: Player.cpp:1209
const std::set< UInt32 > & GetKnownRecipes() const
Gets the set of IDs for recipes this player has discovered.
Definition: Player.cpp:206
void SetFoodExhaustionLevel(double a_FoodExhaustionLevel)
Definition: Player.cpp:414
void SetTeam(cTeam *a_Team)
Sets the player team, nullptr if none.
Definition: Player.cpp:1079
void SetElytraFlight(bool a_ShouldElytraFly)
Starts or stops elytra flight, if our current body stance permits, broadcasting the state change.
Definition: Player.cpp:682
AString m_Rank
The name of the rank assigned to this player.
Definition: Player.h:615
virtual void OnAddToWorld(cWorld &a_World) override
Called when the entity is added to a world.
Definition: Player.cpp:2985
virtual float GetEnchantmentBlastKnockbackReduction() override
Returns explosion knock back reduction percent from blast protection level.
Definition: Player.cpp:2932
void SendMessageRaw(const AString &a_MessageRaw, eChatType a_Type=eChatType::ctChatBox)
Definition: Player.cpp:1254
cWindow * GetWindow(void)
Definition: Player.h:262
void StartEating(void)
Starts eating the currently equipped item.
Definition: Player.cpp:514
void SetCrouch(bool a_ShouldCrouch)
Starts or stops crouching, if our current body stance permits, broadcasting the state change.
Definition: Player.cpp:656
void SendBlocksAround(Vector3i a_BlockPos, int a_Range=1)
Sends the block in the specified range around the specified coord to the client as a block change pac...
Definition: Player.cpp:2325
cInventory m_Inventory
Stores the player's inventory, consisting of crafting grid, hotbar, and main slots.
Definition: Player.h:649
Vector3i m_RespawnPosition
The player's potential respawn position, initialised to world spawn by default.
Definition: Player.h:659
cWindow * m_CurrentWindow
Definition: Player.h:654
void SendMessagePrivateMsg(const AString &a_Message, const AString &a_Sender)
Definition: Player.cpp:1236
void ForceSetSpeed(const Vector3d &a_Speed)
Forces the player to move in the given direction.
Definition: Player.cpp:1540
void CloseWindowIfID(char a_WindowID, bool a_CanRefuse=true)
Closes the current window if it matches the specified ID, resets current window to m_InventoryWindow.
Definition: Player.cpp:1169
AStringVectorVector m_SplitRestrictions
All the restrictions that this player has, based on their rank, split into individual dot-delimited p...
Definition: Player.h:629
virtual void SpawnOn(cClientHandle &a_Client) override
Descendants override this function to send a command to the specified client to spawn the entity on t...
Definition: Player.cpp:3137
void SetFoodSaturationLevel(double a_FoodSaturationLevel)
Definition: Player.cpp:396
Vector3d GetEyePosition(void) const
Definition: Player.cpp:1001
virtual bool IsSprinting(void) const override
Definition: Player.cpp:2958
bool IsSatiated(void) const
Returns true if the player is satiated, i.
Definition: Player.h:360
Vector3d GetThrowStartPos(void) const
Returns the position where projectiles thrown by this player should start, player eye position + adju...
Definition: Player.cpp:1501
void SetSprint(bool a_ShouldSprint)
Starts or stops sprinting, if our current body stance permits, broadcasting the state change.
Definition: Player.cpp:729
float GetLiquidHeightPercent(NIBBLETYPE a_Meta)
Returns how high the liquid is in percent.
Definition: Player.cpp:2565
AStringVectorVector m_SplitPermissions
All the permissions that this player has, based on their rank, split into individual dot-delimited pa...
Definition: Player.h:625
void Unfreeze()
Cancels Freeze(...) and allows the player to move naturally.
Definition: Player.cpp:1441
void SetCustomName(const AString &a_CustomName)
Sets the custom name of this player.
Definition: Player.cpp:763
AString GetPrefix(void) const
Returns the player name prefix, may contain @ format directives.
Definition: Player.cpp:1667
void ReplaceOneEquippedItemTossRest(const cItem &)
Removes one item from the the current equipped item stack, and attempts to add the specified item sta...
Definition: Player.cpp:1745
bool IsGameModeAdventure(void) const
Returns true if the player is in Adventure mode, either explicitly, or by inheriting from current wor...
Definition: Player.cpp:1043
AString GetPlayerListName(void) const
Returns the name that is used in the playerlist.
Definition: Player.cpp:1685
AString m_MsgSuffix
Definition: Player.h:632
void SetCanFly(bool a_CanFly)
If true the player can fly even when he's not in creative.
Definition: Player.cpp:748
void SetTouchGround(bool a_bTouchGround)
Definition: Player.cpp:351
virtual void OnRemoveFromWorld(cWorld &a_World) override
Called when the entity is removed from a world.
Definition: Player.cpp:3075
double m_FoodExhaustionLevel
A "buffer" which adds up hunger before it is substracted from m_FoodSaturationLevel or m_FoodLevel.
Definition: Player.h:646
StatisticsManager m_Stats
Definition: Player.h:739
MTRand GetEnchantmentRandomProvider()
Get a copy of the PRNG for enchanting related generation, don't use this for other purposes.
Definition: Player.cpp:1567
double GetMaxSpeed(void) const
Returns the current relative maximum speed (takes current sprinting / flying state into account)
Definition: Player.cpp:591
void OnLoseSpectated()
Called when spectation stops, because the player crouched or when the entity we're spectating gets re...
Definition: Player.cpp:173
virtual bool DoTakeDamage(TakeDamageInfo &TDI) override
Makes this entity take damage specified in the a_TDI.
Definition: Player.cpp:2881
int m_BowCharge
Definition: Player.h:730
static int XpForLevel(int a_Level)
Calculates the amount of XP needed for a given level Ref: https://minecraft.wiki/w/XP.
Definition: Player.cpp:215
virtual bool IsOnGround(void) const override
Returns whether the entity is on ground or not.
Definition: Player.h:604
void FinishEating(void)
Finishes eating the currently equipped item.
Definition: Player.cpp:527
float GetMiningProgressPerTick(BLOCKTYPE a_Block)
Returns the progress mined per tick for the block a_Block as a fraction (1 would be completely mined)...
Definition: Player.cpp:2673
std::set< UInt32 > m_KnownRecipes
List on known recipes as Ids.
Definition: Player.h:751
eGameMode GetEffectiveGameMode(void) const
Returns the current effective gamemode (inherited gamemode is resolved before returning)
Definition: Player.cpp:1531
void UseEquippedItem(short a_Damage=1)
Damage the player's equipped item by a_Damage, possibly less if the equipped item is enchanted.
Definition: Player.cpp:2033
cSlotNums m_InventoryPaintSlots
Definition: Player.h:679
void SetIsInBed(bool a_IsInBed)
Sets a player's in-bed state.
Definition: Player.cpp:496
AString m_MsgPrefix
Definition: Player.h:632
bool m_IsRespawnPointForced
Whether we unconditionally respawn to m_RespawnPosition, or check if a bed is unobstructed and availa...
Definition: Player.h:714
bool m_IsVisible
Definition: Player.h:720
bool PlaceBlock(Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
Attempts to place the block in the world with a call to PlaceBlocks.
Definition: Player.cpp:2440
AString m_MsgNameColorCode
Definition: Player.h:633
void SetGameMode(eGameMode a_GameMode)
Sets the gamemode for the player.
Definition: Player.cpp:1308
Tag representing a sneaking pose.
Definition: Player.h:36
BodyStanceCrouching(cPlayer &a_Player)
Definition: Player.cpp:80
Tag representing a sleeping pose.
Definition: Player.h:43
BodyStanceSleeping(cPlayer &a_Player)
Definition: Player.cpp:89
Tag representing a sprinting pose.
Definition: Player.h:49
Tag representing the neutral stance.
Definition: Player.h:54
BodyStanceStanding(cPlayer &a_Player)
Definition: Player.cpp:98
Tag representing a swimming or elytra flying pose.
Definition: Player.h:60
BodyStanceGliding(cPlayer &a_Player)
Definition: Player.cpp:107
Class to wrap any random engine to provide a more convenient interface.
Definition: FastRandom.h:58
IntType RandInt(IntType a_Min, IntType a_Max)
Return a random IntType in the range [a_Min, a_Max].
Definition: FastRandom.h:78
bool LoadFromJson(Json::Value &a_Value)
Definition: Inventory.cpp:744
void UpdateItems(void)
Update items (e.g.
Definition: Inventory.cpp:686
const cItem & GetEquippedChestplate(void) const
Definition: Inventory.h:177
cItemGrid & GetHotbarGrid(void)
Returns the cItemGrid object representing the hotbar slots.
Definition: Inventory.h:120
void CopyToItems(cItems &a_Items)
Copies the non-empty slots into a_ItemStacks; preserves the original a_Items contents.
Definition: Inventory.cpp:549
@ invArmorOffset
Definition: Inventory.h:47
@ invShieldOffset
Definition: Inventory.h:50
@ invHotbarOffset
Definition: Inventory.h:49
void SetEquippedSlotNum(int a_SlotNum)
Sets equiped item to the a_SlotNum slot number.
Definition: Inventory.cpp:472
void SaveToJson(Json::Value &a_Value)
Definition: Inventory.cpp:699
const cItem & GetEquippedBoots(void) const
Definition: Inventory.h:179
const cItem & GetSlot(int a_SlotNum) const
Returns current item in a_SlotNum slot.
Definition: Inventory.cpp:390
const cItem & GetEquippedHelmet(void) const
Definition: Inventory.h:176
void Clear(void)
Removes all items from the entire inventory.
Definition: Inventory.cpp:40
int ReplaceOneEquippedItem(const cItem &a_Item, bool a_TryOtherSlots=true)
Removes one item from the the current equipped item stack, and attempts to add the specified item sta...
Definition: Inventory.cpp:247
bool DamageItem(int a_SlotNum, short a_Amount)
Adds the specified damage to the specified item; deletes the item and returns true if the item broke.
Definition: Inventory.cpp:514
int GetEquippedSlotNum(void)
Returns slot number of equiped item.
Definition: Inventory.h:162
const cItem & GetEquippedItem(void) const
Returns current equiped item.
Definition: Inventory.cpp:463
const cItem & GetEquippedLeggings(void) const
Definition: Inventory.h:178
Definition: Item.h:37
const cItemHandler & GetHandler(void) const
Returns the cItemHandler responsible for this item type.
Definition: Item.cpp:216
cEnchantments m_Enchantments
Definition: Item.h:166
char m_ItemCount
Definition: Item.h:164
bool IsEmpty(void) const
Returns true if the item represents an empty stack - either the type is invalid, or count is zero.
Definition: Item.h:69
short m_ItemType
Definition: Item.h:163
void Empty(void)
Empties the item and frees up any dynamic storage used by the internals.
Definition: Item.cpp:63
cItem CopyOne(void) const
Returns a copy of this item with m_ItemCount set to 1.
Definition: Item.cpp:93
This class bridges a vector of cItem for safe access via Lua.
Definition: Item.h:215
size_t Size(void) const
Definition: Item.h:238
void Add(const cItem &a_Item)
Definition: Item.h:233
char ChangeSlotCount(int a_SlotNum, char a_AddToCount)
Adds (or subtracts, if a_AddToCount is negative) to the count of items in the specified slot.
Definition: ItemGrid.cpp:468
virtual float GetBlockBreakingStrength(BLOCKTYPE a_Block) const
Returns the strength to break a specific block.
eDurabilityLostAction
Actions that may cause durability of an item may be lost, where the magnitude of the loss depends on ...
Definition: ItemHandler.h:31
virtual bool CanHarvestBlock(BLOCKTYPE a_BlockType) const
Returns whether this tool / item can harvest a specific block (e.g.
Definition: Horse.h:14
void PlayerOpenWindow(cPlayer &a_Player)
Definition: Horse.cpp:306
@ mfHostile
Definition: Monster.h:30
eMonsterType GetMobType(void) const
Definition: Monster.h:70
Definition: File.h:38
static bool CreateFolderRecursive(const AString &a_FolderPath)
Creates a new folder with the specified name, creating its parents if needed.
Definition: File.cpp:467
@ fmWrite
Definition: File.h:55
bool Open(const AString &iFileName, eMode iMode)
Definition: File.cpp:52
int Write(const void *a_Buffer, size_t a_NumBytes)
Writes up to a_NumBytes bytes from a_Buffer, returns the number of bytes actually written,...
Definition: File.cpp:180
AStringVector GetPlayerPermissions(const cUUID &a_PlayerUUID)
Returns the permissions that the specified player has assigned to them.
bool GetRankVisuals(const AString &a_RankName, AString &a_MsgPrefix, AString &a_MsgSuffix, AString &a_MsgNameColorCode)
Returns the message visuals of an existing rank.
const AString & GetDefaultRank(void) const
Returns the name of the default rank.
Definition: RankManager.h:253
AString GetPlayerRankName(const cUUID &a_PlayerUUID)
Returns the name of the rank that the specified player has assigned to them.
Definition: RankManager.cpp:90
bool UpdatePlayerName(const cUUID &a_PlayerUUID, const AString &a_NewPlayerName)
Updates the playername that is saved with this uuid.
AStringVector GetPlayerRestrictions(const cUUID &a_PlayerUUID)
Returns the restrictions that the specified player has assigned to them.
The root of the object hierarchy.
Definition: Root.h:50
cServer * GetServer(void)
Definition: Root.h:71
static cRoot * Get()
Definition: Root.h:52
cWorld * GetDefaultWorld(void)
Definition: Root.cpp:455
void BroadcastChatLeave(const AString &a_Message)
Definition: Root.h:179
cCraftingRecipes * GetCraftingRecipes(void)
Definition: Root.h:92
cPluginManager * GetPluginManager(void)
Definition: Root.h:111
cWorld * GetWorld(const AString &a_WorldName)
Returns a pointer to the world specified.
Definition: Root.cpp:465
void BroadcastPlayerListsRemovePlayer(const cPlayer &a_Player, const cClientHandle *a_Exclude=nullptr)
Broadcast playerlist removal through all worlds.
Definition: Root.cpp:633
cRankManager * GetRankManager(void)
Definition: Root.h:114
@ otTotalKillCount
Definition: Scoreboard.h:43
@ otDeathCount
Definition: Scoreboard.h:41
@ otPlayerKillCount
Definition: Scoreboard.h:42
bool AllowsFriendlyFire(void) const
Definition: Scoreboard.h:155
bool RemovePlayer(const AString &a_Name)
Removes a player from the team.
Definition: Scoreboard.cpp:222
bool AddPlayer(const AString &a_Name)
Adds a new player to the team.
Definition: Scoreboard.cpp:213
cTeam * QueryPlayerTeam(const AString &a_Name)
Definition: Scoreboard.cpp:435
void AddPlayerScore(const AString &a_Name, cObjective::eType a_Type, cObjective::Score a_Value=1)
Definition: Scoreboard.cpp:550
void SendTo(cClientHandle &a_Client)
Send this scoreboard to the specified client.
Definition: Scoreboard.cpp:567
void PlayerDestroyed()
Notifies the server that a player is being destroyed; the server uses this to adjust the number of pl...
Definition: Server.cpp:144
bool SatisfiesPrerequisite(CustomStatistic a_Stat) const
Returns whether the prerequisite for awarding an achievement are satisfied.
std::unordered_map< CustomStatistic, StatValue > Custom
Represents a UI window.
Definition: Window.h:54
virtual void OpenedByPlayer(cPlayer &a_Player)
Definition: Window.cpp:284
virtual bool ClosedByPlayer(cPlayer &a_Player, bool a_CanRefuse)
Called when a player closes this window; notifies all slot areas.
Definition: Window.cpp:306
char GetWindowID(void) const
Definition: Window.h:80
void SendWholeWindow(cClientHandle &a_Client)
Sends the contents of the whole window to the specified client.
Definition: Window.cpp:384
Definition: UUID.h:11
AString ToShortString() const
Converts the UUID to a short form string (i.e without dashes).
Definition: UUID.cpp:133
AString ToLongString() const
Converts the UUID to a long form string (i.e.
Definition: UUID.cpp:151
Vector3< T > addedY(T a_AddY) const
Returns a copy of this vector moved by the specified amount on the y axis.
Definition: Vector3.h:314
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
void Normalize(void)
Definition: Vector3.h:49
void Set(T a_x, T a_y, T a_z)
Definition: Vector3.h:42
T z
Definition: Vector3.h:17
double SqrLength(void) const
Definition: Vector3.h:105
Definition: World.h:53
cScoreboard & GetScoreBoard(void)
Returns the associated scoreboard instance.
Definition: World.h:700
virtual void BroadcastPlayerListUpdateGameMode(const cPlayer &a_Player, const cClientHandle *a_Exclude=nullptr) override
void BroadcastEntityProperties(const cEntity &a_Entity)
void RemoveClientFromChunks(cClientHandle *a_Client)
Removes the client from all chunks it is present in.
Definition: World.cpp:2514
int GetSpawnX(void) const
Definition: World.h:585
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 BroadcastEntityMetadata(const cEntity &a_Entity, const cClientHandle *a_Exclude=nullptr) override
virtual void BroadcastPlayerListAddPlayer(const cPlayer &a_Player, const cClientHandle *a_Exclude=nullptr) override
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 cTickTimeLong GetWorldAge(void) const override
Definition: World.cpp:491
bool DoWithEntityByID(UInt32 a_UniqueID, cEntityCallback a_Callback)
Calls the callback if the entity with the specified ID is found, with the entity object as the callba...
Definition: World.cpp:2464
const AString & GetName(void) const
Returns the name of the world.
Definition: World.h:691
bool GetBlockTypeMeta(Vector3i a_BlockPos, BLOCKTYPE &a_BlockType, NIBBLETYPE &a_BlockMeta) const
Retrieves the block type and meta at the specified coords.
Definition: World.cpp:1779
bool ShouldBroadcastAchievementMessages(void) const
Definition: World.h:718
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
int GetSpawnZ(void) const
Definition: World.h:587
virtual eDimension GetDimension(void) const override
Definition: World.h:133
eGameMode GetGameMode(void) const
Returns the current game mode.
Definition: World.h:108
virtual void BroadcastSpawnEntity(cEntity &a_Entity, const cClientHandle *a_Exclude=nullptr) override
virtual bool IsDaylightCycleEnabled(void) const
Is the daylight cycle enabled?
Definition: World.h:89
eWeather GetWeather(void) const
Returns the current weather.
Definition: World.h:808
void PlaceBlock(const Vector3i a_Position, const BLOCKTYPE a_BlockType, const NIBBLETYPE a_BlockMeta)
Replaces the specified block with another, and calls the OnPlaced block handler.
Definition: World.cpp:2043
virtual void BroadcastChat(const AString &a_Message, const cClientHandle *a_Exclude=nullptr, eMessageType a_ChatPrefix=mtCustom) override
void SpawnItemPickups(const cItems &a_Pickups, Vector3i a_BlockPos, double a_FlyAwaySpeed=1.0, bool a_IsPlayerCreated=false)
Spawns item pickups for each item in the list.
Definition: World.cpp:1806
virtual void SendBlockTo(int a_X, int a_Y, int a_Z, const cPlayer &a_Player) override
Sends the block at the specified coords to the player.
Definition: World.cpp:2114
bool GetBlocks(sSetBlockVector &a_Blocks, bool a_ContinueOnFailure)
Retrieves block types of the specified blocks.
Definition: World.cpp:2060
int GetSpawnY(void) const
Definition: World.h:586
cTickTimeLong GetWorldDate() const
Definition: World.cpp:500
cChunkMap * GetChunkMap(void)
Definition: World.h:852
virtual void BroadcastPlayerListRemovePlayer(const cPlayer &a_Player, const cClientHandle *a_Exclude=nullptr) override