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 <unordered_map>
5 
6 #include "Player.h"
7 #include "../Mobs/Wolf.h"
8 #include "../Mobs/Horse.h"
9 #include "../BoundingBox.h"
10 #include "../ChatColor.h"
11 #include "../Server.h"
12 #include "../UI/InventoryWindow.h"
13 #include "../UI/WindowOwner.h"
14 #include "../Bindings/PluginManager.h"
15 #include "../BlockEntities/BlockEntity.h"
16 #include "../BlockEntities/EnderChestEntity.h"
17 #include "../Root.h"
18 #include "../Chunk.h"
19 #include "../Items/ItemHandler.h"
20 #include "../FastRandom.h"
21 #include "../ClientHandle.h"
22 
23 #include "../WorldStorage/StatSerializer.h"
24 #include "../CompositeChat.h"
25 
26 #include "../Blocks/BlockHandler.h"
27 #include "../Blocks/BlockSlab.h"
28 #include "../Blocks/ChunkInterface.h"
29 
30 #include "../IniFile.h"
31 #include "json/json.h"
32 
33 // 6000 ticks or 5 minutes
34 #define PLAYER_INVENTORY_SAVE_INTERVAL 6000
35 
36 // 1000 = once per second
37 #define PLAYER_LIST_TIME_MS std::chrono::milliseconds(1000)
38 
39 namespace
40 {
41 
43 cUUID GetOldStyleOfflineUUID(const AString & a_PlayerName)
44 {
45  // Use lowercase username
46  auto BaseUUID = cUUID::GenerateVersion3(StrToLower(a_PlayerName)).ToRaw();
47  // Clobber a full nibble around the variant bits
48  BaseUUID[8] = (BaseUUID[8] & 0x0f) | 0x80;
49 
50  cUUID Ret;
51  Ret.FromRaw(BaseUUID);
52  return Ret;
53 }
54 
55 
56 
57 
58 
61 AString GetUUIDFolderName(const cUUID & a_Uuid)
62 {
63  AString UUID = a_Uuid.ToShortString();
64 
65  AString res(FILE_IO_PREFIX "players/");
66  res.append(UUID, 0, 2);
67  res.push_back('/');
68  return res;
69 }
70 
71 } // namespace (anonymous)
72 
73 
74 
75 
76 
77 const int cPlayer::MAX_HEALTH = 20;
78 
79 const int cPlayer::MAX_FOOD_LEVEL = 20;
80 
82 const int cPlayer::EATING_TICKS = 30;
83 
84 
85 
86 
87 
88 cPlayer::cPlayer(cClientHandlePtr a_Client, const AString & a_PlayerName) :
89  super(etPlayer, 0.6, 1.8),
90  m_bVisible(true),
91  m_FoodLevel(MAX_FOOD_LEVEL),
92  m_FoodSaturationLevel(5.0),
93  m_FoodTickTimer(0),
94  m_FoodExhaustionLevel(0.0),
95  m_Stance(0.0),
96  m_Inventory(*this),
97  m_EnderChestContents(9, 3),
98  m_CurrentWindow(nullptr),
99  m_InventoryWindow(nullptr),
100  m_GameMode(eGameMode_NotSet),
101  m_IP(""),
102  m_ClientHandle(a_Client),
103  m_IsFrozen(false),
104  m_NormalMaxSpeed(1.0),
105  m_SprintingMaxSpeed(1.3),
106  m_FlyingMaxSpeed(1.0),
107  m_IsCrouched(false),
108  m_IsSprinting(false),
109  m_IsFlying(false),
110  m_IsFishing(false),
111  m_CanFly(false),
112  m_EatingFinishTick(-1),
113  m_LifetimeTotalXp(0),
114  m_CurrentXp(0),
115  m_bDirtyExperience(false),
116  m_IsChargingBow(false),
117  m_BowCharge(0),
118  m_FloaterID(cEntity::INVALID_ID),
119  m_Team(nullptr),
120  m_bIsInBed(false),
121  m_TicksUntilNextSave(PLAYER_INVENTORY_SAVE_INTERVAL),
122  m_bIsTeleporting(false),
123  m_UUID((a_Client != nullptr) ? a_Client->GetUUID() : cUUID{}),
124  m_CustomName(""),
125  m_SkinParts(0),
127 {
128  ASSERT(a_PlayerName.length() <= 16); // Otherwise this player could crash many clients...
129 
130  m_InventoryWindow = new cInventoryWindow(*this);
132  m_InventoryWindow->OpenedByPlayer(*this);
133 
136 
137  m_LastPlayerListTime = std::chrono::steady_clock::now();
138  m_PlayerName = a_PlayerName;
139 
140  cWorld * World = nullptr;
141  if (!LoadFromDisk(World))
142  {
143  m_Inventory.Clear();
144  SetPosX(World->GetSpawnX());
145  SetPosY(World->GetSpawnY());
146  SetPosZ(World->GetSpawnZ());
147 
148  // This is a new player. Set the player spawn point to the spawn point of the default world
149  SetBedPos(Vector3i(static_cast<int>(World->GetSpawnX()), static_cast<int>(World->GetSpawnY()), static_cast<int>(World->GetSpawnZ())), World);
150 
151  SetWorld(World); // Use default world
152 
153  FLOGD("Player \"{0}\" is connecting for the first time, spawning at default world spawn {1:.2f}",
154  a_PlayerName, GetPosition()
155  );
156  }
157 
158  m_LastGroundHeight = static_cast<float>(GetPosY());
159  m_Stance = GetPosY() + 1.62;
160 
161 
162  if (m_GameMode == gmNotSet)
163  {
164  if (World->IsGameModeCreative())
165  {
166  m_CanFly = true;
167  }
168  if (World->IsGameModeSpectator()) // Otherwise Player will fall out of the world on join
169  {
170  m_CanFly = true;
171  m_IsFlying = true;
172  }
173  }
174 
175  if (m_GameMode == gmSpectator) // If player is reconnecting to the server in spectator mode
176  {
177  m_CanFly = true;
178  m_IsFlying = true;
179  m_bVisible = false;
180  }
181 }
182 
183 
184 
185 
186 
187 bool cPlayer::Initialize(OwnedEntity a_Self, cWorld & a_World)
188 {
189  UNUSED(a_World);
190  ASSERT(GetWorld() != nullptr);
191  ASSERT(GetParentChunk() == nullptr);
192  GetWorld()->AddPlayer(std::unique_ptr<cPlayer>(static_cast<cPlayer *>(a_Self.release())));
193 
195 
196  // Spawn the entity on the clients:
197  GetWorld()->BroadcastSpawnEntity(*this);
198 
199  return true;
200 }
201 
202 
203 
204 
205 
207 {
208  if (!cRoot::Get()->GetPluginManager()->CallHookPlayerDestroyed(*this))
209  {
210  cRoot::Get()->BroadcastChatLeave(Printf("%s has left the game", GetName().c_str()));
211  LOGINFO("Player %s has left the game", GetName().c_str());
212  }
213 
214  LOGD("Deleting cPlayer \"%s\" at %p, ID %d", GetName().c_str(), static_cast<void *>(this), GetUniqueID());
215 
216  SaveToDisk();
217 
218  m_ClientHandle = nullptr;
219 
220  delete m_InventoryWindow;
221  m_InventoryWindow = nullptr;
222 
223  LOGD("Player %p deleted", static_cast<void *>(this));
224 }
225 
226 
227 
228 
229 
231 {
232  CloseWindow(false);
234 }
235 
236 
237 
238 
239 
241 {
242  if (!m_bVisible || (m_ClientHandle.get() == (&a_Client)))
243  {
244  return;
245  }
246  a_Client.SendPlayerSpawn(*this);
247  a_Client.SendEntityHeadLook(*this);
248  a_Client.SendEntityEquipment(*this, 0, m_Inventory.GetEquippedItem());
249  a_Client.SendEntityEquipment(*this, 1, m_Inventory.GetEquippedBoots());
252  a_Client.SendEntityEquipment(*this, 4, m_Inventory.GetEquippedHelmet());
253 }
254 
255 
256 
257 
258 
259 void cPlayer::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
260 {
261  if (m_ClientHandle != nullptr)
262  {
263  if (m_ClientHandle->IsDestroyed())
264  {
265  // This should not happen, because destroying a client will remove it from the world, but just in case
266  ASSERT(!"Player ticked whilst in the process of destruction!");
267  m_ClientHandle = nullptr;
268  return;
269  }
270 
271  if (!m_ClientHandle->IsPlaying())
272  {
273  // We're not yet in the game, ignore everything
274  return;
275  }
276  }
277  else
278  {
279  ASSERT(!"Player ticked whilst in the process of destruction!");
280  }
281 
282 
284 
285  // Handle the player detach, when the player is in spectator mode
286  if (
287  (IsGameModeSpectator()) &&
288  (m_AttachedTo != nullptr) &&
289  (
290  (m_AttachedTo->IsDestroyed()) || // Watching entity destruction
291  (m_AttachedTo->GetHealth() <= 0) || // Watching entity dead
292  (IsCrouched()) // Or the player wants to be detached
293  )
294  )
295  {
296  Detach();
297  }
298 
299  // Handle a frozen player
300  TickFreezeCode();
301  if (m_IsFrozen)
302  {
303  return;
304  }
305  ASSERT((GetParentChunk() != nullptr) && (GetParentChunk()->IsValid()));
306 
307  ASSERT(a_Chunk.IsValid());
308 
309  super::Tick(a_Dt, a_Chunk);
310 
311  // Handle charging the bow:
312  if (m_IsChargingBow)
313  {
314  m_BowCharge += 1;
315  }
316 
317  // Handle updating experience
318  if (m_bDirtyExperience)
319  {
320  SendExperience();
321  }
322 
324 
325  if (m_Health > 0) // make sure player is alive
326  {
328 
329  if ((m_EatingFinishTick >= 0) && (m_EatingFinishTick <= m_World->GetWorldAge()))
330  {
331  FinishEating();
332  }
333 
334  HandleFood();
335  }
336 
337  if (m_IsFishing)
338  {
339  HandleFloater();
340  }
341 
342  // Update items (e.g. Maps)
344 
345  // Send Player List (Once per m_LastPlayerListTime/1000 ms)
346  if (m_LastPlayerListTime + PLAYER_LIST_TIME_MS <= std::chrono::steady_clock::now())
347  {
349  m_LastPlayerListTime = std::chrono::steady_clock::now();
350  }
351 
352  if (m_TicksUntilNextSave == 0)
353  {
354  SaveToDisk();
356  }
357  else
358  {
360  }
361 }
362 
363 
364 
365 
366 
368 {
369  if (m_IsFrozen)
370  {
371  if ((!m_IsManuallyFrozen) && (GetClientHandle()->IsPlayerChunkSent()))
372  {
373  // If the player was automatically frozen, unfreeze if the chunk the player is inside is loaded and sent
374  Unfreeze();
375 
376  // Pull the player out of any solids that might have loaded on them.
378  if (RelSuccess)
379  {
380  int NewY = Rel.y;
381  if (NewY < 0)
382  {
383  NewY = 0;
384  }
385  while (NewY < cChunkDef::Height - 2)
386  {
387  // If we find a position with enough space for the player
388  if (
389  !cBlockInfo::IsSolid(Chunk->GetBlock(Rel.x, NewY, Rel.z)) &&
390  !cBlockInfo::IsSolid(Chunk->GetBlock(Rel.x, NewY + 1, Rel.z))
391  )
392  {
393  // If the found position is not the same as the original
394  if (NewY != Rel.y)
395  {
396  SetPosition(GetPosition().x, NewY, GetPosition().z);
398  }
399  break;
400  }
401  ++NewY;
402  }
403  }
404  }
405  else if (GetWorld()->GetWorldAge() % 100 == 0)
406  {
407  // Despite the client side freeze, the player may be able to move a little by
408  // Jumping or canceling flight. Re-freeze every now and then
410  }
411  }
412  else
413  {
414  if (!GetClientHandle()->IsPlayerChunkSent() || (!GetParentChunk()->IsValid()))
415  {
416  FreezeInternal(GetPosition(), false);
417  }
418  }
419 }
420 
421 
422 
423 
424 
425 int cPlayer::CalcLevelFromXp(int a_XpTotal)
426 {
427  // level 0 to 15
428  if (a_XpTotal <= XP_TO_LEVEL15)
429  {
430  return a_XpTotal / XP_PER_LEVEL_TO15;
431  }
432 
433  // level 30+
434  if (a_XpTotal > XP_TO_LEVEL30)
435  {
436  return static_cast<int>((151.5 + sqrt( 22952.25 - (14 * (2220 - a_XpTotal)))) / 7);
437  }
438 
439  // level 16 to 30
440  return static_cast<int>((29.5 + sqrt( 870.25 - (6 * ( 360 - a_XpTotal)))) / 3);
441 }
442 
443 
444 
445 
446 
447 int cPlayer::XpForLevel(int a_Level)
448 {
449  // level 0 to 15
450  if (a_Level <= 15)
451  {
452  return a_Level * XP_PER_LEVEL_TO15;
453  }
454 
455  // level 30+
456  if (a_Level >= 31)
457  {
458  return static_cast<int>((3.5 * a_Level * a_Level) - (151.5 * a_Level) + 2220);
459  }
460 
461  // level 16 to 30
462  return static_cast<int>((1.5 * a_Level * a_Level) - (29.5 * a_Level) + 360);
463 }
464 
465 
466 
467 
468 
470 {
472 }
473 
474 
475 
476 
477 
479 {
480  int currentLevel = CalcLevelFromXp(m_CurrentXp);
481  int currentLevel_XpBase = XpForLevel(currentLevel);
482 
483  return static_cast<float>(m_CurrentXp - currentLevel_XpBase) /
484  static_cast<float>(XpForLevel(1 + currentLevel) - currentLevel_XpBase);
485 }
486 
487 
488 
489 
490 
491 bool cPlayer::SetCurrentExperience(int a_CurrentXp)
492 {
493  if (!(a_CurrentXp >= 0) || (a_CurrentXp > (std::numeric_limits<int>::max() - m_LifetimeTotalXp)))
494  {
495  LOGWARNING("Tried to update experiece with an invalid Xp value: %d", a_CurrentXp);
496  return false; // oops, they gave us a dodgey number
497  }
498 
499  m_CurrentXp = a_CurrentXp;
500 
501  // Set experience to be updated
502  m_bDirtyExperience = true;
503 
504  return true;
505 }
506 
507 
508 
509 
510 
511 int cPlayer::DeltaExperience(int a_Xp_delta)
512 {
513  if (a_Xp_delta > (std::numeric_limits<int>().max() - m_CurrentXp))
514  {
515  // Value was bad, abort and report
516  LOGWARNING("Attempt was made to increment Xp by %d, which overflowed the int datatype. Ignoring.", a_Xp_delta);
517  return -1; // Should we instead just return the current Xp?
518  }
519 
520  m_CurrentXp += a_Xp_delta;
521 
522  // Make sure they didn't subtract too much
523  m_CurrentXp = std::max(m_CurrentXp, 0);
524 
525 
526  // Update total for score calculation
527  if (a_Xp_delta > 0)
528  {
529  m_LifetimeTotalXp += a_Xp_delta;
530  }
531 
532  LOGD("Player \"%s\" gained / lost %d experience, total is now: %d", GetName().c_str(), a_Xp_delta, m_CurrentXp);
533 
534  // Set experience to be updated
535  m_bDirtyExperience = true;
536 
537  return m_CurrentXp;
538 }
539 
540 
541 
542 
543 
545 {
546  LOGD("Player \"%s\" started charging their bow", GetName().c_str());
547  m_IsChargingBow = true;
548  m_BowCharge = 0;
550 }
551 
552 
553 
554 
555 
557 {
558  LOGD("Player \"%s\" finished charging their bow at a charge of %d", GetName().c_str(), m_BowCharge);
559  int res = m_BowCharge;
560  m_IsChargingBow = false;
561  m_BowCharge = 0;
563 
564  return res;
565 }
566 
567 
568 
569 
570 
572 {
573  LOGD("Player \"%s\" cancelled charging their bow at a charge of %d", GetName().c_str(), m_BowCharge);
574  m_IsChargingBow = false;
575  m_BowCharge = 0;
577 }
578 
579 
580 
581 
582 
583 void cPlayer::SetTouchGround(bool a_bTouchGround)
584 {
585  if (IsGameModeSpectator()) // You can fly through the ground in Spectator
586  {
587  return;
588  }
589 
590  UNUSED(a_bTouchGround);
591  /* Unfortunately whatever the reason, there are still desyncs in on-ground status between the client and server. For example:
592  1. Walking off a ledge (whatever height)
593  2. Initial login
594  Thus, it is too risky to compare their value against ours and kick them for hacking */
595 }
596 
597 
598 
599 
600 
601 void cPlayer::Heal(int a_Health)
602 {
603  super::Heal(a_Health);
604  SendHealth();
605 }
606 
607 
608 
609 
610 
611 void cPlayer::SetFoodLevel(int a_FoodLevel)
612 {
613  int FoodLevel = Clamp(a_FoodLevel, 0, MAX_FOOD_LEVEL);
614 
615  if (cRoot::Get()->GetPluginManager()->CallHookPlayerFoodLevelChange(*this, FoodLevel))
616  {
617  m_FoodSaturationLevel = 5.0;
618  return;
619  }
620 
621  m_FoodLevel = FoodLevel;
622  SendHealth();
623 }
624 
625 
626 
627 
628 
629 void cPlayer::SetFoodSaturationLevel(double a_FoodSaturationLevel)
630 {
631  m_FoodSaturationLevel = Clamp(a_FoodSaturationLevel, 0.0, static_cast<double>(m_FoodLevel));
632 }
633 
634 
635 
636 
637 
638 void cPlayer::SetFoodTickTimer(int a_FoodTickTimer)
639 {
640  m_FoodTickTimer = a_FoodTickTimer;
641 }
642 
643 
644 
645 
646 
647 void cPlayer::SetFoodExhaustionLevel(double a_FoodExhaustionLevel)
648 {
649  m_FoodExhaustionLevel = Clamp(a_FoodExhaustionLevel, 0.0, 40.0);
650 }
651 
652 
653 
654 
655 
656 bool cPlayer::Feed(int a_Food, double a_Saturation)
657 {
658  if (IsSatiated())
659  {
660  return false;
661  }
662 
664  SetFoodLevel(m_FoodLevel + a_Food);
665  return true;
666 }
667 
668 
669 
670 
671 
672 void cPlayer::AddFoodExhaustion(double a_Exhaustion)
673 {
675  {
676  m_FoodExhaustionLevel = std::min(m_FoodExhaustionLevel + a_Exhaustion, 40.0);
677  }
678 }
679 
680 
681 
682 
683 
685 {
686  // Set the timer:
688 
689  // Send the packets:
692 }
693 
694 
695 
696 
697 
699 {
700  // Reset the timer:
701  m_EatingFinishTick = -1;
702 
703  // Send the packets:
704  m_ClientHandle->SendEntityStatus(*this, esPlayerEatingAccepted);
706 
707  // consume the item:
708  cItem Item(GetEquippedItem());
709  Item.m_ItemCount = 1;
711  if (!ItemHandler->EatItem(this, &Item))
712  {
713  return;
714  }
715  if (!IsGameModeCreative())
716  {
718  }
719  ItemHandler->OnFoodEaten(m_World, this, &Item);
720 }
721 
722 
723 
724 
725 
727 {
728  m_EatingFinishTick = -1;
730 }
731 
732 
733 
734 
735 
737 {
738  if (m_ClientHandle != nullptr)
739  {
740  m_ClientHandle->SendHealth();
741  }
742 }
743 
744 
745 
746 
747 
749 {
750  if (m_ClientHandle != nullptr)
751  {
752  m_ClientHandle->SendHeldItemChange(m_Inventory.GetEquippedSlotNum());
753  }
754 }
755 
756 
757 
758 
759 
761 {
762  if (m_ClientHandle != nullptr)
763  {
764  m_ClientHandle->SendExperience();
765  m_bDirtyExperience = false;
766  }
767 }
768 
769 
770 
771 
772 
774 {
775  // Clear the list of slots that are being inventory-painted. Used by cWindow only
776  m_InventoryPaintSlots.clear();
777 }
778 
779 
780 
781 
782 
784 {
785  // Add a slot to the list for inventory painting. Used by cWindow only
786  m_InventoryPaintSlots.push_back(a_SlotNum);
787 }
788 
789 
790 
791 
792 
794 {
795  // Return the list of slots currently stored for inventory painting. Used by cWindow only
796  return m_InventoryPaintSlots;
797 }
798 
799 
800 
801 
802 
803 double cPlayer::GetMaxSpeed(void) const
804 {
805  if (m_IsFlying)
806  {
807  return m_FlyingMaxSpeed;
808  }
809  else if (m_IsSprinting)
810  {
811  return m_SprintingMaxSpeed;
812  }
813  else
814  {
815  return m_NormalMaxSpeed;
816  }
817 }
818 
819 
820 
821 
822 
823 void cPlayer::SetNormalMaxSpeed(double a_Speed)
824 {
825  m_NormalMaxSpeed = a_Speed;
826  if (!m_IsSprinting && !m_IsFlying && !m_IsFrozen)
827  {
828  // If we are frozen, we do not send this yet. We send when unfreeze() is called
829  m_ClientHandle->SendPlayerMaxSpeed();
830  }
831 }
832 
833 
834 
835 
836 
837 void cPlayer::SetSprintingMaxSpeed(double a_Speed)
838 {
839  m_SprintingMaxSpeed = a_Speed;
840  if (m_IsSprinting && !m_IsFlying && !m_IsFrozen)
841  {
842  // If we are frozen, we do not send this yet. We send when unfreeze() is called
843  m_ClientHandle->SendPlayerMaxSpeed();
844  }
845 }
846 
847 
848 
849 
850 
851 void cPlayer::SetFlyingMaxSpeed(double a_Speed)
852 {
853  m_FlyingMaxSpeed = a_Speed;
854 
855  // Update the flying speed, always:
856  if (!m_IsFrozen)
857  {
858  // If we are frozen, we do not send this yet. We send when unfreeze() is called
859  m_ClientHandle->SendPlayerAbilities();
860  }
861 }
862 
863 
864 
865 
866 
867 void cPlayer::SetCrouch(bool a_IsCrouched)
868 {
869  // Set the crouch status, broadcast to all visible players
870 
871  if (a_IsCrouched == m_IsCrouched)
872  {
873  // No change
874  return;
875  }
876  m_IsCrouched = a_IsCrouched;
878 }
879 
880 
881 
882 
883 
884 void cPlayer::SetSprint(bool a_IsSprinting)
885 {
886  if (a_IsSprinting == m_IsSprinting)
887  {
888  // No change
889  return;
890  }
891 
892  m_IsSprinting = a_IsSprinting;
893  m_ClientHandle->SendPlayerMaxSpeed();
894 }
895 
896 
897 
898 
899 
900 void cPlayer::SetCanFly(bool a_CanFly)
901 {
902  if (a_CanFly == m_CanFly)
903  {
904  return;
905  }
906 
907  m_CanFly = a_CanFly;
908  m_ClientHandle->SendPlayerAbilities();
909 }
910 
911 
912 
913 
914 
915 void cPlayer::SetCustomName(const AString & a_CustomName)
916 {
917  if (m_CustomName == a_CustomName)
918  {
919  return;
920  }
921 
923 
924  m_CustomName = a_CustomName;
925  if (m_CustomName.length() > 16)
926  {
927  m_CustomName = m_CustomName.substr(0, 16);
928  }
929 
932 }
933 
934 
935 
936 
937 
938 void cPlayer::SetBedPos(const Vector3i & a_Pos)
939 {
940  m_LastBedPos = a_Pos;
942 }
943 
944 
945 
946 
947 
948 void cPlayer::SetBedPos(const Vector3i & a_Pos, cWorld * a_World)
949 {
950  m_LastBedPos = a_Pos;
951  ASSERT(a_World != nullptr);
952  m_SpawnWorld = a_World;
953 }
954 
955 
956 
957 
958 
960 {
961  return m_SpawnWorld;
962 }
963 
964 
965 
966 
967 
968 void cPlayer::SetFlying(bool a_IsFlying)
969 {
970  if (a_IsFlying == m_IsFlying)
971  {
972  return;
973  }
974 
975  m_IsFlying = a_IsFlying;
976  if (!m_IsFrozen)
977  {
978  // If we are frozen, we do not send this yet. We send when unfreeze() is called
979  m_ClientHandle->SendPlayerAbilities();
980  }
981 }
982 
983 
984 
985 
986 
987 void cPlayer::ApplyArmorDamage(int a_DamageBlocked)
988 {
989  short ArmorDamage = static_cast<short>(std::max(a_DamageBlocked / 4, 1));
990 
991  for (int i = 0; i < 4; i++)
992  {
993  UseItem(cInventory::invArmorOffset + i, ArmorDamage);
994  }
995 }
996 
997 
998 
999 
1000 
1002 {
1003  SetSpeed(0, 0, 0);
1004  // Prevents knocking the player in the wrong direction due to
1005  // the speed vector problems, see #2865
1006  // In the future, the speed vector should be fixed
1007  if ((a_TDI.DamageType != dtInVoid) && (a_TDI.DamageType != dtPlugin))
1008  {
1010  {
1011  // No damage / health in creative or spectator mode if not void or plugin damage
1012  return false;
1013  }
1014  }
1015 
1016  if ((a_TDI.Attacker != nullptr) && (a_TDI.Attacker->IsPlayer()))
1017  {
1018  cPlayer * Attacker = static_cast<cPlayer *>(a_TDI.Attacker);
1019 
1020  if ((m_Team != nullptr) && (m_Team == Attacker->m_Team))
1021  {
1022  if (!m_Team->AllowsFriendlyFire())
1023  {
1024  // Friendly fire is disabled
1025  return false;
1026  }
1027  }
1028  }
1029 
1030  if (super::DoTakeDamage(a_TDI))
1031  {
1032  // Any kind of damage adds food exhaustion
1033  AddFoodExhaustion(0.3f);
1034  SendHealth();
1035 
1036  // Tell the wolves
1037  if (a_TDI.Attacker != nullptr)
1038  {
1039  if (a_TDI.Attacker->IsPawn())
1040  {
1041  NotifyNearbyWolves(static_cast<cPawn*>(a_TDI.Attacker), true);
1042  }
1043  }
1044  m_Stats.AddValue(statDamageTaken, FloorC<StatValue>(a_TDI.FinalDamage * 10 + 0.5));
1045  return true;
1046  }
1047  return false;
1048 }
1049 
1050 
1051 
1052 
1053 
1054 void cPlayer::NotifyNearbyWolves(cPawn * a_Opponent, bool a_IsPlayerInvolved)
1055 {
1056  ASSERT(a_Opponent != nullptr);
1057 
1058  m_World->ForEachEntityInBox(cBoundingBox(GetPosition(), 16), [&] (cEntity & a_Entity)
1059  {
1060  if (a_Entity.IsMob())
1061  {
1062  auto & Mob = static_cast<cMonster&>(a_Entity);
1063  if (Mob.GetMobType() == mtWolf)
1064  {
1065  auto & Wolf = static_cast<cWolf&>(Mob);
1066  Wolf.ReceiveNearbyFightInfo(GetUUID(), a_Opponent, a_IsPlayerInvolved);
1067  }
1068  }
1069  return false;
1070  }
1071  );
1072 }
1073 
1074 
1075 
1076 
1077 
1079 {
1080  super::KilledBy(a_TDI);
1081 
1082  if (m_Health > 0)
1083  {
1084  return; // not dead yet =]
1085  }
1086 
1087  m_bVisible = false; // So new clients don't see the player
1088 
1089  // Detach player from object / entity. If the player dies, the server still says
1090  // that the player is attached to the entity / object
1091  Detach();
1092 
1093  // Puke out all the items
1094  cItems Pickups;
1095  m_Inventory.CopyToItems(Pickups);
1096  m_Inventory.Clear();
1097 
1098  if (GetName() == "Notch")
1099  {
1100  Pickups.Add(cItem(E_ITEM_RED_APPLE));
1101  }
1102  m_Stats.AddValue(statItemsDropped, static_cast<StatValue>(Pickups.Size()));
1103 
1104  m_World->SpawnItemPickups(Pickups, GetPosX(), GetPosY(), GetPosZ(), 10);
1105  SaveToDisk(); // Save it, yeah the world is a tough place !
1106  cPluginManager * PluginManager = cRoot::Get()->GetPluginManager();
1107 
1108  if ((a_TDI.Attacker == nullptr) && m_World->ShouldBroadcastDeathMessages())
1109  {
1110  const AString DamageText = [&]
1111  {
1112  switch (a_TDI.DamageType)
1113  {
1114  case dtRangedAttack: return "was shot";
1115  case dtLightning: return "was plasmified by lightining";
1116  case dtFalling: return GetRandomProvider().RandBool() ? "fell to death" : "hit the ground too hard";
1117  case dtDrowning: return "drowned";
1118  case dtSuffocating: return GetRandomProvider().RandBool() ? "git merge'd into a block" : "fused with a block";
1119  case dtStarving: return "forgot the importance of food";
1120  case dtCactusContact: return "was impaled on a cactus";
1121  case dtLavaContact: return "was melted by lava";
1122  case dtPoisoning: return "died from septicaemia";
1123  case dtWithering: return "is a husk of their former selves";
1124  case dtOnFire: return "forgot to stop, drop, and roll";
1125  case dtFireContact: return "burnt themselves to death";
1126  case dtInVoid: return "somehow fell out of the world";
1127  case dtPotionOfHarming: return "was magicked to death";
1128  case dtEnderPearl: return "misused an ender pearl";
1129  case dtAdmin: return "was administrator'd";
1130  case dtExplosion: return "blew up";
1131  case dtAttack: return "was attacked by thin air";
1132  }
1133  UNREACHABLE("Unsupported damage type");
1134  }();
1135  AString DeathMessage = Printf("%s %s", GetName().c_str(), DamageText.c_str());
1136  PluginManager->CallHookKilled(*this, a_TDI, DeathMessage);
1137  if (DeathMessage != AString(""))
1138  {
1139  GetWorld()->BroadcastChatDeath(DeathMessage);
1140  }
1141  }
1142  else if (a_TDI.Attacker == nullptr) // && !m_World->ShouldBroadcastDeathMessages() by fallthrough
1143  {
1144  // no-op
1145  }
1146  else if (a_TDI.Attacker->IsPlayer())
1147  {
1148  cPlayer * Killer = static_cast<cPlayer *>(a_TDI.Attacker);
1149  AString DeathMessage = Printf("%s was killed by %s", GetName().c_str(), Killer->GetName().c_str());
1150  PluginManager->CallHookKilled(*this, a_TDI, DeathMessage);
1151  if (DeathMessage != AString(""))
1152  {
1153  GetWorld()->BroadcastChatDeath(DeathMessage);
1154  }
1155  }
1156  else
1157  {
1158  AString KillerClass = a_TDI.Attacker->GetClass();
1159  KillerClass.erase(KillerClass.begin()); // Erase the 'c' of the class (e.g. "cWitch" -> "Witch")
1160  AString DeathMessage = Printf("%s was killed by a %s", GetName().c_str(), KillerClass.c_str());
1161  PluginManager->CallHookKilled(*this, a_TDI, DeathMessage);
1162  if (DeathMessage != AString(""))
1163  {
1164  GetWorld()->BroadcastChatDeath(DeathMessage);
1165  }
1166  }
1167 
1169 
1171 }
1172 
1173 
1174 
1175 
1176 
1177 void cPlayer::Killed(cEntity * a_Victim)
1178 {
1179  cScoreboard & ScoreBoard = m_World->GetScoreBoard();
1180 
1181  if (a_Victim->IsPlayer())
1182  {
1184 
1186  }
1187  else if (a_Victim->IsMob())
1188  {
1189  if (static_cast<cMonster *>(a_Victim)->GetMobFamily() == cMonster::mfHostile)
1190  {
1192  }
1193 
1195  }
1196 
1198 }
1199 
1200 
1201 
1202 
1203 
1205 {
1206  ASSERT(m_World != nullptr);
1207 
1208  m_Health = GetMaxHealth();
1210 
1211  // Reset food level:
1213  m_FoodSaturationLevel = 5.0;
1214  m_FoodExhaustionLevel = 0.0;
1215 
1216  // Reset Experience
1217  m_CurrentXp = 0;
1218  m_LifetimeTotalXp = 0;
1219  // ToDo: send score to client? How?
1220 
1221  m_ClientHandle->SendRespawn(m_SpawnWorld->GetDimension(), true);
1222 
1223  // Extinguish the fire:
1224  StopBurning();
1225 
1226  if (GetWorld() != m_SpawnWorld)
1227  {
1229  }
1230  else
1231  {
1233  }
1234 
1235  SetVisible(true);
1236 }
1237 
1238 
1239 
1240 
1241 
1242 double cPlayer::GetEyeHeight(void) const
1243 {
1244  return m_Stance;
1245 }
1246 
1247 
1248 
1249 
1250 
1252 {
1253  return Vector3d( GetPosX(), m_Stance, GetPosZ());
1254 }
1255 
1256 
1257 
1258 
1259 
1261 {
1262  return (GetEffectiveGameMode() == gmCreative);
1263 }
1264 
1265 
1266 
1267 
1268 
1270 {
1271  return (GetEffectiveGameMode() == gmSurvival);
1272 }
1273 
1274 
1275 
1276 
1277 
1279 {
1280  return (GetEffectiveGameMode() == gmAdventure);
1281 }
1282 
1283 
1284 
1285 
1286 
1288 {
1289  return (GetEffectiveGameMode() == gmSpectator);
1290 }
1291 
1292 
1293 
1294 
1295 
1296 bool cPlayer::CanMobsTarget(void) const
1297 {
1298  return (IsGameModeSurvival() || IsGameModeAdventure()) && (m_Health > 0);
1299 }
1300 
1301 
1302 
1303 
1304 
1305 void cPlayer::SetTeam(cTeam * a_Team)
1306 {
1307  if (m_Team == a_Team)
1308  {
1309  return;
1310  }
1311 
1312  if (m_Team)
1313  {
1315  }
1316 
1317  m_Team = a_Team;
1318 
1319  if (m_Team)
1320  {
1321  m_Team->AddPlayer(GetName());
1322  }
1323 }
1324 
1325 
1326 
1327 
1328 
1330 {
1331  if (m_World == nullptr)
1332  {
1333  SetTeam(nullptr);
1334  }
1335  else
1336  {
1337  cScoreboard & Scoreboard = m_World->GetScoreBoard();
1338 
1339  SetTeam(Scoreboard.QueryPlayerTeam(GetName()));
1340  }
1341 
1342  return m_Team;
1343 }
1344 
1345 
1346 
1347 
1348 
1350 {
1351  if (cRoot::Get()->GetPluginManager()->CallHookPlayerOpeningWindow(*this, a_Window))
1352  {
1353  return;
1354  }
1355 
1356  if (&a_Window != m_CurrentWindow)
1357  {
1358  CloseWindow(false);
1359  }
1360 
1361  a_Window.OpenedByPlayer(*this);
1362  m_CurrentWindow = &a_Window;
1363  a_Window.SendWholeWindow(*GetClientHandle());
1364 }
1365 
1366 
1367 
1368 
1369 
1370 void cPlayer::CloseWindow(bool a_CanRefuse)
1371 {
1372  if (m_CurrentWindow == nullptr)
1373  {
1375  return;
1376  }
1377 
1378  if (m_CurrentWindow->ClosedByPlayer(*this, a_CanRefuse) || !a_CanRefuse)
1379  {
1380  // Close accepted, go back to inventory window (the default):
1382  }
1383  else
1384  {
1385  // Re-open the window
1388  }
1389 }
1390 
1391 
1392 
1393 
1394 
1395 void cPlayer::CloseWindowIfID(char a_WindowID, bool a_CanRefuse)
1396 {
1397  if ((m_CurrentWindow == nullptr) || (m_CurrentWindow->GetWindowID() != a_WindowID))
1398  {
1399  return;
1400  }
1401  CloseWindow();
1402 }
1403 
1404 
1405 
1406 
1407 
1408 void cPlayer::SendMessage(const AString & a_Message)
1409 {
1410  m_ClientHandle->SendChat(a_Message, mtCustom);
1411 }
1412 
1413 
1414 
1415 
1416 
1417 void cPlayer::SendMessageInfo(const AString & a_Message)
1418 {
1419  m_ClientHandle->SendChat(a_Message, mtInformation);
1420 }
1421 
1422 
1423 
1424 
1425 
1426 void cPlayer::SendMessageFailure(const AString & a_Message)
1427 {
1428  m_ClientHandle->SendChat(a_Message, mtFailure);
1429 }
1430 
1431 
1432 
1433 
1434 
1435 void cPlayer::SendMessageSuccess(const AString & a_Message)
1436 {
1437  m_ClientHandle->SendChat(a_Message, mtSuccess);
1438 }
1439 
1440 
1441 
1442 
1443 
1444 void cPlayer::SendMessageWarning(const AString & a_Message)
1445 {
1446  m_ClientHandle->SendChat(a_Message, mtWarning);
1447 }
1448 
1449 
1450 
1451 
1452 
1453 void cPlayer::SendMessageFatal(const AString & a_Message)
1454 {
1455  m_ClientHandle->SendChat(a_Message, mtFailure);
1456 }
1457 
1458 
1459 
1460 
1461 
1462 void cPlayer::SendMessagePrivateMsg(const AString & a_Message, const AString & a_Sender)
1463 {
1464  m_ClientHandle->SendChat(a_Message, mtPrivateMessage, a_Sender);
1465 }
1466 
1467 
1468 
1469 
1470 
1471 void cPlayer::SendMessage(const cCompositeChat & a_Message)
1472 {
1473  m_ClientHandle->SendChat(a_Message);
1474 }
1475 
1476 
1477 
1478 
1479 
1480 void cPlayer::SendMessageRaw(const AString & a_MessageRaw, eChatType a_Type)
1481 {
1482  m_ClientHandle->SendChatRaw(a_MessageRaw, a_Type);
1483 }
1484 
1485 
1486 
1487 
1488 
1489 void cPlayer::SendSystemMessage(const AString & a_Message)
1490 {
1491  m_ClientHandle->SendChatSystem(a_Message, mtCustom);
1492 }
1493 
1494 
1495 
1496 
1497 
1499 {
1500  m_ClientHandle->SendChatAboveActionBar(a_Message, mtCustom);
1501 }
1502 
1503 
1504 
1505 
1506 
1508 {
1509  m_ClientHandle->SendChatSystem(a_Message);
1510 }
1511 
1512 
1513 
1514 
1515 
1517 {
1518  m_ClientHandle->SendChatAboveActionBar(a_Message);
1519 }
1520 
1521 
1522 
1523 
1524 
1526 {
1527  if ((a_GameMode < gmMin) || (a_GameMode >= gmMax))
1528  {
1529  LOGWARNING("%s: Setting invalid gamemode: %d", GetName().c_str(), a_GameMode);
1530  return;
1531  }
1532 
1533  if (m_GameMode == a_GameMode)
1534  {
1535  // Gamemode already set
1536  return;
1537  }
1538 
1539  // Detach, if the player is switching from or to the spectator mode
1540  if ((m_GameMode == gmSpectator) || (a_GameMode == gmSpectator))
1541  {
1542  Detach();
1543  }
1544 
1545  m_GameMode = a_GameMode;
1546  m_ClientHandle->SendGameMode(a_GameMode);
1547 
1548  SetCapabilities();
1549 
1551 }
1552 
1553 
1554 
1555 
1556 
1558 {
1559  // Fly ability
1561  {
1562  SetCanFly(true);
1563  }
1564  else
1565  {
1566  SetFlying(false);
1567  SetCanFly(false);
1568  }
1569 
1570  // Visible
1571  if (IsGameModeSpectator())
1572  {
1573  SetVisible(false);
1574  }
1575  else
1576  {
1577  SetVisible(true);
1578  }
1579 
1580  // Set for spectator
1581  if (IsGameModeSpectator())
1582  {
1583  // Clear the current dragging item of the player
1584  if (GetWindow() != nullptr)
1585  {
1588  }
1589  }
1590 }
1591 
1592 
1593 
1594 
1595 
1596 void cPlayer::SetIP(const AString & a_IP)
1597 {
1598  m_IP = a_IP;
1599 }
1600 
1601 
1602 
1603 
1604 
1605 unsigned int cPlayer::AwardAchievement(const eStatistic a_Ach)
1606 {
1607  eStatistic Prerequisite = cStatInfo::GetPrerequisite(a_Ach);
1608 
1609  // Check if the prerequisites are met
1610  if (Prerequisite != statInvalid)
1611  {
1612  if (m_Stats.GetValue(Prerequisite) == 0)
1613  {
1614  return 0;
1615  }
1616  }
1617 
1618  StatValue Old = m_Stats.GetValue(a_Ach);
1619 
1620  if (Old > 0)
1621  {
1622  return static_cast<unsigned int>(m_Stats.AddValue(a_Ach));
1623  }
1624  else
1625  {
1627  {
1628  cCompositeChat Msg;
1631  m_World->BroadcastChat(Msg);
1632  }
1633 
1634  // Increment the statistic
1635  StatValue New = m_Stats.AddValue(a_Ach);
1636 
1637  // Achievement Get!
1638  m_ClientHandle->SendStatistics(m_Stats);
1639 
1640  return static_cast<unsigned int>(New);
1641  }
1642 }
1643 
1644 
1645 
1646 
1647 
1648 void cPlayer::TeleportToCoords(double a_PosX, double a_PosY, double a_PosZ)
1649 {
1650  // ask plugins to allow teleport to the new position.
1651  if (!cRoot::Get()->GetPluginManager()->CallHookEntityTeleport(*this, m_LastPosition, Vector3d(a_PosX, a_PosY, a_PosZ)))
1652  {
1653  ResetPosition({a_PosX, a_PosY, a_PosZ});
1654  FreezeInternal(GetPosition(), false);
1655  m_bIsTeleporting = true;
1656 
1658  m_ClientHandle->SendPlayerMoveLook();
1659  }
1660 }
1661 
1662 
1663 
1664 
1665 
1666 void cPlayer::Freeze(const Vector3d & a_Location)
1667 {
1668  FreezeInternal(a_Location, true);
1669 }
1670 
1671 
1672 
1673 
1674 
1676 {
1677  return m_IsFrozen;
1678 }
1679 
1680 
1681 
1682 
1683 
1685 {
1688 
1689  m_IsFrozen = false;
1692 }
1693 
1694 
1695 
1696 
1697 
1698 void cPlayer::SendRotation(double a_YawDegrees, double a_PitchDegrees)
1699 {
1700  SetYaw(a_YawDegrees);
1701  SetPitch(a_PitchDegrees);
1702  m_ClientHandle->SendPlayerMoveLook();
1703 }
1704 
1705 
1706 
1707 
1708 
1710 {
1711  Vector3d res = GetEyePosition();
1712 
1713  // Adjust the position to be just outside the player's bounding box:
1714  res.x += 0.16 * cos(GetPitch());
1715  res.y += -0.1;
1716  res.z += 0.16 * sin(GetPitch());
1717 
1718  return res;
1719 }
1720 
1721 
1722 
1723 
1724 
1725 Vector3d cPlayer::GetThrowSpeed(double a_SpeedCoeff) const
1726 {
1727  Vector3d res = GetLookVector();
1728  res.Normalize();
1729 
1730  // TODO: Add a slight random change (+-0.0075 in each direction)
1731 
1732  return res * a_SpeedCoeff;
1733 }
1734 
1735 
1736 
1737 
1738 
1739 void cPlayer::ForceSetSpeed(const Vector3d & a_Speed)
1740 {
1741  SetSpeed(a_Speed);
1742 }
1743 
1744 
1745 
1746 
1747 
1748 void cPlayer::DoSetSpeed(double a_SpeedX, double a_SpeedY, double a_SpeedZ)
1749 {
1750  if (m_IsFrozen)
1751  {
1752  // Do not set speed to a frozen client
1753  return;
1754  }
1755  super::DoSetSpeed(a_SpeedX, a_SpeedY, a_SpeedZ);
1756  // Send the speed to the client so he actualy moves
1757  m_ClientHandle->SendEntityVelocity(*this);
1758 }
1759 
1760 
1761 
1762 
1763 
1764 void cPlayer::SetVisible(bool a_bVisible)
1765 {
1766  // Need to Check if the player or other players are in gamemode spectator, but will break compatibility
1767  if (a_bVisible && !m_bVisible) // Make visible
1768  {
1769  m_bVisible = true;
1770  m_World->BroadcastSpawnEntity(*this);
1771  }
1772  if (!a_bVisible && m_bVisible)
1773  {
1774  m_bVisible = false;
1775  m_World->BroadcastDestroyEntity(*this, m_ClientHandle.get()); // Destroy on all clients
1776  }
1777 }
1778 
1779 
1780 
1781 
1782 
1783 bool cPlayer::HasPermission(const AString & a_Permission)
1784 {
1785  if (a_Permission.empty())
1786  {
1787  // Empty permission request is always granted
1788  return true;
1789  }
1790 
1791  AStringVector Split = StringSplit(a_Permission, ".");
1792 
1793  // Iterate over all restrictions; if any matches, then return failure:
1794  for (auto & Restriction: m_SplitRestrictions)
1795  {
1796  if (PermissionMatches(Split, Restriction))
1797  {
1798  return false;
1799  }
1800  } // for Restriction - m_SplitRestrictions[]
1801 
1802  // Iterate over all granted permissions; if any matches, then return success:
1803  for (auto & Permission: m_SplitPermissions)
1804  {
1805  if (PermissionMatches(Split, Permission))
1806  {
1807  return true;
1808  }
1809  } // for Permission - m_SplitPermissions[]
1810 
1811  // No granted permission matches
1812  return false;
1813 }
1814 
1815 
1816 
1817 
1818 
1819 bool cPlayer::PermissionMatches(const AStringVector & a_Permission, const AStringVector & a_Template)
1820 {
1821  // Check the sub-items if they are the same or there's a wildcard:
1822  size_t lenP = a_Permission.size();
1823  size_t lenT = a_Template.size();
1824  size_t minLen = std::min(lenP, lenT);
1825  for (size_t i = 0; i < minLen; i++)
1826  {
1827  if (a_Template[i] == "*")
1828  {
1829  // Has matched so far and now there's a wildcard in the template, so the permission matches:
1830  return true;
1831  }
1832  if (a_Permission[i] != a_Template[i])
1833  {
1834  // Found a mismatch
1835  return false;
1836  }
1837  }
1838 
1839  // So far all the sub-items have matched
1840  // If the sub-item count is the same, then the permission matches:
1841  if (lenP == lenT)
1842  {
1843  return true;
1844  }
1845 
1846  // There are more sub-items in either the permission or the template, not a match:
1847  return false;
1848 }
1849 
1850 
1851 
1852 
1853 
1855 {
1856  if (m_MsgNameColorCode.empty() || (m_MsgNameColorCode == "-"))
1857  {
1858  // Color has not been assigned, return an empty string:
1859  return AString();
1860  }
1861 
1862  // Return the color, including the delimiter:
1864 }
1865 
1866 
1867 
1868 
1869 
1871 {
1872  return m_MsgPrefix;
1873 }
1874 
1875 
1876 
1877 
1878 
1880 {
1881  return m_MsgSuffix;
1882 }
1883 
1884 
1885 
1886 
1887 
1889 {
1890  const AString & Color = GetColor();
1891 
1892  if (HasCustomName())
1893  {
1894  return m_CustomName;
1895  }
1896  else if ((GetName().length() <= 14) && !Color.empty())
1897  {
1898  return Printf("%s%s", Color.c_str(), GetName().c_str());
1899  }
1900  else
1901  {
1902  return GetName();
1903  }
1904 }
1905 
1906 
1907 
1908 
1909 
1910 void cPlayer::SetDraggingItem(const cItem & a_Item)
1911 {
1912  if (GetWindow() != nullptr)
1913  {
1914  m_DraggingItem = a_Item;
1916  }
1917 }
1918 
1919 
1920 
1921 
1922 
1923 void cPlayer::TossEquippedItem(char a_Amount)
1924 {
1925  cItems Drops;
1926  cItem DroppedItem(GetInventory().GetEquippedItem());
1927  if (!DroppedItem.IsEmpty())
1928  {
1929  char NewAmount = a_Amount;
1930  if (NewAmount > GetInventory().GetEquippedItem().m_ItemCount)
1931  {
1932  NewAmount = GetInventory().GetEquippedItem().m_ItemCount; // Drop only what's there
1933  }
1934 
1935  GetInventory().GetHotbarGrid().ChangeSlotCount(GetInventory().GetEquippedSlotNum() /* Returns hotbar subslot, which HotbarGrid takes */, -a_Amount);
1936 
1937  DroppedItem.m_ItemCount = NewAmount;
1938  Drops.push_back(DroppedItem);
1939  }
1940 
1941  TossItems(Drops);
1942 }
1943 
1944 
1945 
1946 
1947 
1948 void cPlayer::TossHeldItem(char a_Amount)
1949 {
1950  cItems Drops;
1951  cItem & Item = GetDraggingItem();
1952  if (!Item.IsEmpty())
1953  {
1954  char OriginalItemAmount = Item.m_ItemCount;
1955  Item.m_ItemCount = std::min(OriginalItemAmount, a_Amount);
1956  Drops.push_back(Item);
1957 
1958  if (OriginalItemAmount > a_Amount)
1959  {
1960  Item.m_ItemCount = OriginalItemAmount - a_Amount;
1961  }
1962  else
1963  {
1964  Item.Empty();
1965  }
1966  }
1967 
1968  TossItems(Drops);
1969 }
1970 
1971 
1972 
1973 
1974 
1975 void cPlayer::TossPickup(const cItem & a_Item)
1976 {
1977  cItems Drops;
1978  Drops.push_back(a_Item);
1979 
1980  TossItems(Drops);
1981 }
1982 
1983 
1984 
1985 
1986 
1987 void cPlayer::TossItems(const cItems & a_Items)
1988 {
1989  if (IsGameModeSpectator()) // Players can't toss items in spectator
1990  {
1991  return;
1992  }
1993 
1994  m_Stats.AddValue(statItemsDropped, static_cast<StatValue>(a_Items.Size()));
1995 
1996  double vX = 0, vY = 0, vZ = 0;
1997  EulerToVector(-GetYaw(), GetPitch(), vZ, vX, vY);
1998  vY = -vY * 2 + 1.f;
1999  m_World->SpawnItemPickups(a_Items, GetPosX(), GetEyeHeight(), GetPosZ(), vX * 3, vY * 3, vZ * 3, true); // 'true' because created by player
2000 }
2001 
2002 
2003 
2004 
2005 
2006 bool cPlayer::DoMoveToWorld(cWorld * a_World, bool a_ShouldSendRespawn, Vector3d a_NewPosition)
2007 {
2008  ASSERT(a_World != nullptr);
2009  ASSERT(IsTicking());
2010 
2011  if (GetWorld() == a_World)
2012  {
2013  // Don't move to same world
2014  return false;
2015  }
2016 
2017  // Ask the plugins if the player is allowed to change the world
2018  if (cRoot::Get()->GetPluginManager()->CallHookEntityChangingWorld(*this, *a_World))
2019  {
2020  // A Plugin doesn't allow the player to change the world
2021  return false;
2022  }
2023 
2024  GetWorld()->QueueTask([this, a_World, a_ShouldSendRespawn, a_NewPosition](cWorld & a_OldWorld)
2025  {
2026  // The clienthandle caches the coords of the chunk we're standing at. Invalidate this.
2028 
2029  // Prevent further ticking in this world
2030  SetIsTicking(false);
2031 
2032  // Tell others we are gone
2033  GetWorld()->BroadcastDestroyEntity(*this);
2034 
2035  // Remove player from world
2036  // Make sure that RemovePlayer didn't return a valid smart pointer, due to the second parameter being false
2037  // We remain valid and not destructed after this call
2038  VERIFY(!GetWorld()->RemovePlayer(*this, false));
2039 
2040  // Set position to the new position
2041  ResetPosition(a_NewPosition);
2042  FreezeInternal(a_NewPosition, false);
2043 
2044  // Stop all mobs from targeting this player
2046 
2047  // Deal with new world
2048  SetWorld(a_World);
2049 
2050  // Set capabilities based on new world
2051  SetCapabilities();
2052 
2053  cClientHandle * ch = this->GetClientHandle();
2054  if (ch != nullptr)
2055  {
2056  // Send the respawn packet:
2057  if (a_ShouldSendRespawn)
2058  {
2059  m_ClientHandle->SendRespawn(a_World->GetDimension());
2060  }
2061 
2062  // Update the view distance.
2063  ch->SetViewDistance(m_ClientHandle->GetRequestedViewDistance());
2064 
2065  // Send current weather of target world to player
2066  if (a_World->GetDimension() == dimOverworld)
2067  {
2068  ch->SendWeather(a_World->GetWeather());
2069  }
2070  }
2071 
2072  // Broadcast the player into the new world.
2073  a_World->BroadcastSpawnEntity(*this);
2074 
2075  // Queue add to new world and removal from the old one
2076 
2077  // Chunks may be streamed before cWorld::AddPlayer() sets the world to the new value
2078  cChunk * ParentChunk = this->GetParentChunk();
2079 
2080  LOGD("Warping player \"%s\" from world \"%s\" to \"%s\". Source chunk: (%d, %d) ",
2081  this->GetName().c_str(),
2082  a_OldWorld.GetName().c_str(), a_World->GetName().c_str(),
2083  ParentChunk->GetPosX(), ParentChunk->GetPosZ()
2084  );
2085 
2086  // New world will take over and announce client at its next tick
2087  auto PlayerPtr = static_cast<cPlayer *>(ParentChunk->RemoveEntity(*this).release());
2088  a_World->AddPlayer(std::unique_ptr<cPlayer>(PlayerPtr), &a_OldWorld);
2089  });
2090 
2091  return true;
2092 }
2093 
2094 
2095 
2096 
2097 
2099 {
2100  LoadRank();
2101 
2102  // Load from the UUID file:
2103  if (LoadFromFile(GetUUIDFileName(m_UUID), a_World))
2104  {
2105  return true;
2106  }
2107 
2108  // Check for old offline UUID filename, if it exists migrate to new filename
2110  auto OldFilename = GetUUIDFileName(GetOldStyleOfflineUUID(GetName()));
2111  auto NewFilename = GetUUIDFileName(m_UUID);
2112  // Only move if there isn't already a new file
2113  if (!cFile::IsFile(NewFilename) && cFile::IsFile(OldFilename))
2114  {
2115  cFile::CreateFolderRecursive(GetUUIDFolderName(m_UUID)); // Ensure folder exists to move to
2116  if (
2117  cFile::Rename(OldFilename, NewFilename) &&
2118  (m_UUID == OfflineUUID) &&
2119  LoadFromFile(NewFilename, a_World)
2120  )
2121  {
2122  return true;
2123  }
2124  }
2125 
2126  // Load from the offline UUID file, if allowed:
2127  const char * OfflineUsage = " (unused)";
2128  if (cRoot::Get()->GetServer()->ShouldLoadOfflinePlayerData())
2129  {
2130  OfflineUsage = "";
2131  if (LoadFromFile(GetUUIDFileName(OfflineUUID), a_World))
2132  {
2133  return true;
2134  }
2135  }
2136 
2137  // Load from the old-style name-based file, if allowed:
2138  if (cRoot::Get()->GetServer()->ShouldLoadNamedPlayerData())
2139  {
2140  AString OldStyleFileName = Printf("players/%s.json", GetName().c_str());
2141  if (LoadFromFile(OldStyleFileName, a_World))
2142  {
2143  // Save in new format and remove the old file
2144  if (SaveToDisk())
2145  {
2146  cFile::Delete(OldStyleFileName);
2147  }
2148  return true;
2149  }
2150  }
2151 
2152  // None of the files loaded successfully
2153  LOG("Player data file not found for %s (%s, offline %s%s), will be reset to defaults.",
2154  GetName().c_str(), m_UUID.ToShortString().c_str(), OfflineUUID.ToShortString().c_str(), OfflineUsage
2155  );
2156 
2157  if (a_World == nullptr)
2158  {
2159  a_World = cRoot::Get()->GetDefaultWorld();
2160  }
2161  return false;
2162 }
2163 
2164 
2165 
2166 
2167 
2168 bool cPlayer::LoadFromFile(const AString & a_FileName, cWorldPtr & a_World)
2169 {
2170  // Load the data from the file:
2171  cFile f;
2172  if (!f.Open(a_FileName, cFile::fmRead))
2173  {
2174  // This is a new player whom we haven't seen yet, bail out, let them have the defaults
2175  return false;
2176  }
2177  AString buffer;
2178  if (f.ReadRestOfFile(buffer) != f.GetSize())
2179  {
2180  LOGWARNING("Cannot read player data from file \"%s\"", a_FileName.c_str());
2181  return false;
2182  }
2183  f.Close();
2184 
2185  // Parse the JSON format:
2186  Json::Value root;
2187  Json::Reader reader;
2188  if (!reader.parse(buffer, root, false))
2189  {
2190  LOGWARNING("Cannot parse player data in file \"%s\"", a_FileName.c_str());
2191  return false;
2192  }
2193 
2194  // Load the player data:
2195  Json::Value & JSON_PlayerPosition = root["position"];
2196  if (JSON_PlayerPosition.size() == 3)
2197  {
2198  SetPosX(JSON_PlayerPosition[0].asDouble());
2199  SetPosY(JSON_PlayerPosition[1].asDouble());
2200  SetPosZ(JSON_PlayerPosition[2].asDouble());
2202  }
2203 
2204  Json::Value & JSON_PlayerRotation = root["rotation"];
2205  if (JSON_PlayerRotation.size() == 3)
2206  {
2207  SetYaw (static_cast<float>(JSON_PlayerRotation[0].asDouble()));
2208  SetPitch (static_cast<float>(JSON_PlayerRotation[1].asDouble()));
2209  SetRoll (static_cast<float>(JSON_PlayerRotation[2].asDouble()));
2210  }
2211 
2212  m_Health = root.get("health", 0).asFloat();
2213  m_AirLevel = root.get("air", MAX_AIR_LEVEL).asInt();
2214  m_FoodLevel = root.get("food", MAX_FOOD_LEVEL).asInt();
2215  m_FoodSaturationLevel = root.get("foodSaturation", MAX_FOOD_LEVEL).asDouble();
2216  m_FoodTickTimer = root.get("foodTickTimer", 0).asInt();
2217  m_FoodExhaustionLevel = root.get("foodExhaustion", 0).asDouble();
2218  m_LifetimeTotalXp = root.get("xpTotal", 0).asInt();
2219  m_CurrentXp = root.get("xpCurrent", 0).asInt();
2220  m_IsFlying = root.get("isflying", 0).asBool();
2221 
2222  m_GameMode = static_cast<eGameMode>(root.get("gamemode", eGameMode_NotSet).asInt());
2223 
2225  {
2226  m_CanFly = true;
2227  }
2228 
2229  m_Inventory.LoadFromJson(root["inventory"]);
2230 
2231  int equippedSlotNum = root.get("equippedItemSlot", 0).asInt();
2232  m_Inventory.SetEquippedSlotNum(equippedSlotNum);
2233 
2234  cEnderChestEntity::LoadFromJson(root["enderchestinventory"], m_EnderChestContents);
2235 
2236  m_LoadedWorldName = root.get("world", "world").asString();
2237  a_World = cRoot::Get()->GetWorld(GetLoadedWorldName());
2238  if (a_World == nullptr)
2239  {
2240  a_World = cRoot::Get()->GetDefaultWorld();
2241  }
2242 
2243 
2244  m_LastBedPos.x = root.get("SpawnX", a_World->GetSpawnX()).asInt();
2245  m_LastBedPos.y = root.get("SpawnY", a_World->GetSpawnY()).asInt();
2246  m_LastBedPos.z = root.get("SpawnZ", a_World->GetSpawnZ()).asInt();
2247  AString SpawnWorldName = root.get("SpawnWorld", cRoot::Get()->GetDefaultWorld()->GetName()).asString();
2248  m_SpawnWorld = cRoot::Get()->GetWorld(SpawnWorldName);
2249  if (m_SpawnWorld == nullptr)
2250  {
2252  }
2253 
2254  // Load the player stats.
2255  // We use the default world name (like bukkit) because stats are shared between dimensions / worlds.
2256  cStatSerializer StatSerializer(cRoot::Get()->GetDefaultWorld()->GetDataPath(), GetName(), GetUUID().ToLongString(), &m_Stats);
2257  StatSerializer.Load();
2258 
2259  FLOGD("Player {0} was read from file \"{1}\", spawning at {2:.2f} in world \"{3}\"",
2260  GetName(), a_FileName, GetPosition(), a_World->GetName()
2261  );
2262 
2263  return true;
2264 }
2265 
2266 
2267 
2268 
2269 
2271 {
2272  if (
2273  (m_AttachedTo == nullptr) ||
2274  !m_AttachedTo->IsMob()
2275  )
2276  {
2277  return;
2278  }
2279 
2280  auto & Mob = static_cast<cMonster &>(*m_AttachedTo);
2281 
2282  if (Mob.GetMobType() != mtHorse)
2283  {
2284  return;
2285  }
2286 
2287  auto & Horse = static_cast<cHorse &>(Mob);
2288  // The client sends requests for untame horses as well but shouldn't actually open
2289  if (Horse.IsTame())
2290  {
2291  Horse.PlayerOpenWindow(*this);
2292  }
2293 }
2294 
2295 
2296 
2297 
2298 
2300 {
2301  cFile::CreateFolderRecursive(GetUUIDFolderName(m_UUID));
2302 
2303  // create the JSON data
2304  Json::Value JSON_PlayerPosition;
2305  JSON_PlayerPosition.append(Json::Value(GetPosX()));
2306  JSON_PlayerPosition.append(Json::Value(GetPosY()));
2307  JSON_PlayerPosition.append(Json::Value(GetPosZ()));
2308 
2309  Json::Value JSON_PlayerRotation;
2310  JSON_PlayerRotation.append(Json::Value(GetYaw()));
2311  JSON_PlayerRotation.append(Json::Value(GetPitch()));
2312  JSON_PlayerRotation.append(Json::Value(GetRoll()));
2313 
2314  Json::Value JSON_Inventory;
2315  m_Inventory.SaveToJson(JSON_Inventory);
2316 
2317  Json::Value JSON_EnderChestInventory;
2318  cEnderChestEntity::SaveToJson(JSON_EnderChestInventory, m_EnderChestContents);
2319 
2320  Json::Value root;
2321  root["position"] = JSON_PlayerPosition;
2322  root["rotation"] = JSON_PlayerRotation;
2323  root["inventory"] = JSON_Inventory;
2324  root["equippedItemSlot"] = m_Inventory.GetEquippedSlotNum();
2325  root["enderchestinventory"] = JSON_EnderChestInventory;
2326  root["health"] = m_Health;
2327  root["xpTotal"] = m_LifetimeTotalXp;
2328  root["xpCurrent"] = m_CurrentXp;
2329  root["air"] = m_AirLevel;
2330  root["food"] = m_FoodLevel;
2331  root["foodSaturation"] = m_FoodSaturationLevel;
2332  root["foodTickTimer"] = m_FoodTickTimer;
2333  root["foodExhaustion"] = m_FoodExhaustionLevel;
2334  root["isflying"] = IsFlying();
2335  root["lastknownname"] = GetName();
2336  root["SpawnX"] = GetLastBedPos().x;
2337  root["SpawnY"] = GetLastBedPos().y;
2338  root["SpawnZ"] = GetLastBedPos().z;
2339  root["SpawnWorld"] = m_SpawnWorld->GetName();
2340 
2341  if (m_World != nullptr)
2342  {
2343  root["world"] = m_World->GetName();
2344  if (m_GameMode == m_World->GetGameMode())
2345  {
2346  root["gamemode"] = static_cast<int>(eGameMode_NotSet);
2347  }
2348  else
2349  {
2350  root["gamemode"] = static_cast<int>(m_GameMode);
2351  }
2352  }
2353  else
2354  {
2355  // This happens if the player is saved to new format after loading from the old format
2356  root["world"] = m_LoadedWorldName;
2357  root["gamemode"] = static_cast<int>(eGameMode_NotSet);
2358  }
2359 
2360  Json::StyledWriter writer;
2361  std::string JsonData = writer.write(root);
2362 
2363  AString SourceFile = GetUUIDFileName(m_UUID);
2364 
2365  cFile f;
2366  if (!f.Open(SourceFile, cFile::fmWrite))
2367  {
2368  LOGWARNING("Error writing player \"%s\" to file \"%s\" - cannot open file. Player will lose their progress.",
2369  GetName().c_str(), SourceFile.c_str()
2370  );
2371  return false;
2372  }
2373  if (f.Write(JsonData.c_str(), JsonData.size()) != static_cast<int>(JsonData.size()))
2374  {
2375  LOGWARNING("Error writing player \"%s\" to file \"%s\" - cannot save data. Player will lose their progress. ",
2376  GetName().c_str(), SourceFile.c_str()
2377  );
2378  return false;
2379  }
2380 
2381  // Save the player stats.
2382  // We use the default world name (like bukkit) because stats are shared between dimensions / worlds.
2383  cStatSerializer StatSerializer(cRoot::Get()->GetDefaultWorld()->GetDataPath(), GetName(), GetUUID().ToLongString(), &m_Stats);
2384  if (!StatSerializer.Save())
2385  {
2386  LOGWARNING("Could not save stats for player %s", GetName().c_str());
2387  return false;
2388  }
2389 
2390  return true;
2391 }
2392 
2393 
2394 
2395 
2396 
2397 void cPlayer::UseEquippedItem(short a_Damage)
2398 {
2399  // No durability loss in creative or spectator modes:
2401  {
2402  return;
2403  }
2404 
2406 }
2407 
2408 
2409 
2410 
2411 
2413 {
2414  // Get item being used:
2415  cItem Item = GetEquippedItem();
2416 
2417  // Get base damage for action type:
2418  short Dmg = cItemHandler::GetItemHandler(Item)->GetDurabilityLossByAction(a_Action);
2419 
2420  UseEquippedItem(Dmg);
2421 }
2422 
2423 
2424 
2425 
2426 
2427 void cPlayer::UseItem(int a_SlotNumber, short a_Damage)
2428 {
2429  const cItem & Item = m_Inventory.GetSlot(a_SlotNumber);
2430  if (Item.IsEmpty())
2431  {
2432  return;
2433  }
2434 
2435  // Ref: https://minecraft.gamepedia.com/Enchanting#Unbreaking
2436  unsigned int UnbreakingLevel = Item.m_Enchantments.GetLevel(cEnchantments::enchUnbreaking);
2437  double chance = ItemCategory::IsArmor(Item.m_ItemType)
2438  ? (0.6 + (0.4 / (UnbreakingLevel + 1))) : (1.0 / (UnbreakingLevel + 1));
2439 
2440  // When durability is reduced by multiple points
2441  // Unbreaking is applied for each point of reduction.
2442  std::binomial_distribution<short> Dist(a_Damage, chance);
2443  short ReducedDamage = Dist(GetRandomProvider().Engine());
2444  if (m_Inventory.DamageItem(a_SlotNumber, ReducedDamage))
2445  {
2446  m_World->BroadcastSoundEffect("entity.item.break", GetPosition(), 0.5f, static_cast<float>(0.75 + (static_cast<float>((GetUniqueID() * 23) % 32)) / 64));
2447  }
2448 }
2449 
2450 
2451 
2452 
2453 
2455 {
2456  // Ref.: https://minecraft.gamepedia.com/Hunger
2457 
2459  {
2460  // Hunger is disabled for Creative and Spectator
2461  return;
2462  }
2463 
2464  // Apply food exhaustion that has accumulated:
2465  if (m_FoodExhaustionLevel > 4.0)
2466  {
2467  m_FoodExhaustionLevel -= 4.0;
2468 
2469  if (m_FoodSaturationLevel > 0.0)
2470  {
2471  m_FoodSaturationLevel = std::max(m_FoodSaturationLevel - 1.0, 0.0);
2472  }
2473  else
2474  {
2476  }
2477  }
2478 
2479  // Heal or damage, based on the food level, using the m_FoodTickTimer:
2480  if ((m_FoodLevel >= 18) || (m_FoodLevel <= 0))
2481  {
2482  m_FoodTickTimer++;
2483  if (m_FoodTickTimer >= 80)
2484  {
2485  m_FoodTickTimer = 0;
2486 
2487  if ((m_FoodLevel >= 18) && (GetHealth() < GetMaxHealth()))
2488  {
2489  // Regenerate health from food, incur 3 pts of food exhaustion:
2490  Heal(1);
2491  AddFoodExhaustion(3.0);
2492  }
2493  else if ((m_FoodLevel <= 0) && (m_Health > 1))
2494  {
2495  // Damage from starving
2496  TakeDamage(dtStarving, nullptr, 1, 1, 0);
2497  }
2498  }
2499  }
2500  else
2501  {
2502  m_FoodTickTimer = 0;
2503  }
2504 }
2505 
2506 
2507 
2508 
2509 
2511 {
2512  if (GetEquippedItem().m_ItemType == E_ITEM_FISHING_ROD)
2513  {
2514  return;
2515  }
2516  m_World->DoWithEntityByID(m_FloaterID, [](cEntity & a_Entity)
2517  {
2518  a_Entity.Destroy(true);
2519  return true;
2520  }
2521  );
2522  SetIsFishing(false);
2523 }
2524 
2525 
2526 
2527 
2528 
2529 bool cPlayer::IsClimbing(void) const
2530 {
2531  int PosX = POSX_TOINT;
2532  int PosY = POSY_TOINT;
2533  int PosZ = POSZ_TOINT;
2534 
2535  if ((PosY < 0) || (PosY >= cChunkDef::Height))
2536  {
2537  return false;
2538  }
2539 
2540  BLOCKTYPE Block = m_World->GetBlock(PosX, PosY, PosZ);
2541  switch (Block)
2542  {
2543  case E_BLOCK_LADDER:
2544  case E_BLOCK_VINES:
2545  {
2546  return true;
2547  }
2548  default: return false;
2549  }
2550 }
2551 
2552 
2553 
2554 
2555 
2556 void cPlayer::UpdateMovementStats(const Vector3d & a_DeltaPos, bool a_PreviousIsOnGround)
2557 {
2558  if (m_bIsTeleporting)
2559  {
2560  m_bIsTeleporting = false;
2561  return;
2562  }
2563 
2564  StatValue Value = FloorC<StatValue>(a_DeltaPos.Length() * 100 + 0.5);
2565  if (m_AttachedTo == nullptr)
2566  {
2567  if (IsFlying())
2568  {
2569  m_Stats.AddValue(statDistFlown, Value);
2570  // May be flying and doing any of the following:
2571  }
2572 
2573  if (IsClimbing())
2574  {
2575  if (a_DeltaPos.y > 0.0) // Going up
2576  {
2577  m_Stats.AddValue(statDistClimbed, FloorC<StatValue>(a_DeltaPos.y * 100 + 0.5));
2578  }
2579  }
2580  else if (IsInWater())
2581  {
2582  m_Stats.AddValue(statDistSwum, Value);
2583  AddFoodExhaustion(0.00015 * static_cast<double>(Value));
2584  }
2585  else if (IsOnGround())
2586  {
2588  AddFoodExhaustion((IsSprinting() ? 0.001 : 0.0001) * static_cast<double>(Value));
2589  }
2590  else
2591  {
2592  // If a jump just started, process food exhaustion:
2593  if ((a_DeltaPos.y > 0.0) && a_PreviousIsOnGround)
2594  {
2596  AddFoodExhaustion((IsSprinting() ? 0.008 : 0.002) * static_cast<double>(Value));
2597  }
2598  else if (a_DeltaPos.y < 0.0)
2599  {
2600  // Increment statistic
2601  m_Stats.AddValue(statDistFallen, static_cast<StatValue>(std::abs(a_DeltaPos.y) * 100 + 0.5));
2602  }
2603  // TODO: good opportunity to detect illegal flight (check for falling tho)
2604  }
2605  }
2606  else
2607  {
2608  switch (m_AttachedTo->GetEntityType())
2609  {
2611  case cEntity::etBoat: m_Stats.AddValue(statDistBoat, Value); break;
2612  case cEntity::etMonster:
2613  {
2614  cMonster * Monster = static_cast<cMonster *>(m_AttachedTo);
2615  switch (Monster->GetMobType())
2616  {
2617  case mtPig: m_Stats.AddValue(statDistPig, Value); break;
2618  case mtHorse: m_Stats.AddValue(statDistHorse, Value); break;
2619  default: break;
2620  }
2621  break;
2622  }
2623  default: break;
2624  }
2625  }
2626 }
2627 
2628 
2629 
2630 
2631 
2633 {
2634  // Load the values from cRankManager:
2635  cRankManager * RankMgr = cRoot::Get()->GetRankManager();
2636  m_Rank = RankMgr->GetPlayerRankName(m_UUID);
2637  if (m_Rank.empty())
2638  {
2639  m_Rank = RankMgr->GetDefaultRank();
2640  }
2641  else
2642  {
2643  // Update the name:
2645  }
2649 
2650  // Break up the individual permissions on each dot, into m_SplitPermissions:
2651  m_SplitPermissions.clear();
2652  m_SplitPermissions.reserve(m_Permissions.size());
2653  for (auto & Permission: m_Permissions)
2654  {
2655  m_SplitPermissions.push_back(StringSplit(Permission, "."));
2656  } // for Permission - m_Permissions[]
2657 
2658  // Break up the individual restrictions on each dot, into m_SplitRestrictions:
2659  m_SplitRestrictions.clear();
2660  m_SplitRestrictions.reserve(m_Restrictions.size());
2661  for (auto & Restriction: m_Restrictions)
2662  {
2663  m_SplitRestrictions.push_back(StringSplit(Restriction, "."));
2664  } // for itr - m_Restrictions[]
2665 }
2666 
2667 
2668 
2669 
2670 
2671 bool cPlayer::PlaceBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
2672 {
2673  sSetBlockVector blk{{a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta}};
2674  return PlaceBlocks(blk);
2675 }
2676 
2677 
2678 
2679 
2680 
2681 void cPlayer::SendBlocksAround(int a_BlockX, int a_BlockY, int a_BlockZ, int a_Range)
2682 {
2683  // Collect the coords of all the blocks to send:
2684  sSetBlockVector blks;
2685  for (int y = a_BlockY - a_Range + 1; y < a_BlockY + a_Range; y++)
2686  {
2687  for (int z = a_BlockZ - a_Range + 1; z < a_BlockZ + a_Range; z++)
2688  {
2689  for (int x = a_BlockX - a_Range + 1; x < a_BlockX + a_Range; x++)
2690  {
2691  blks.emplace_back(x, y, z, E_BLOCK_AIR, 0); // Use fake blocktype, it will get set later on.
2692  }
2693  }
2694  } // for y
2695 
2696  // Get the values of all the blocks:
2697  if (!m_World->GetBlocks(blks, false))
2698  {
2699  LOGD("%s: Cannot query all blocks, not sending an update", __FUNCTION__);
2700  return;
2701  }
2702 
2703  // Divide the block changes by their respective chunks:
2704  std::unordered_map<cChunkCoords, sSetBlockVector, cChunkCoordsHash> Changes;
2705  for (const auto & blk: blks)
2706  {
2707  Changes[cChunkCoords(blk.m_ChunkX, blk.m_ChunkZ)].push_back(blk);
2708  } // for blk - blks[]
2709  blks.clear();
2710 
2711  // Send the blocks for each affected chunk:
2712  for (auto itr = Changes.cbegin(), end = Changes.cend(); itr != end; ++itr)
2713  {
2714  m_ClientHandle->SendBlockChanges(itr->first.m_ChunkX, itr->first.m_ChunkZ, itr->second);
2715  }
2716 }
2717 
2718 
2719 
2720 
2721 
2723 {
2724  // Compute the bounding box for each block to be placed
2725  std::vector<cBoundingBox> PlacementBoxes;
2726  cBoundingBox PlacingBounds(0, 0, 0, 0, 0, 0);
2727  bool HasInitializedBounds = false;
2728  for (auto blk: a_Blocks)
2729  {
2730  cBlockHandler * BlockHandler = cBlockInfo::GetHandler(blk.m_BlockType);
2731  int x = blk.GetX();
2732  int y = blk.GetY();
2733  int z = blk.GetZ();
2734  cBoundingBox BlockBox = BlockHandler->GetPlacementCollisionBox(
2735  m_World->GetBlock(x - 1, y, z),
2736  m_World->GetBlock(x + 1, y, z),
2737  (y == 0) ? E_BLOCK_AIR : m_World->GetBlock(x, y - 1, z),
2738  (y == cChunkDef::Height - 1) ? E_BLOCK_AIR : m_World->GetBlock(x, y + 1, z),
2739  m_World->GetBlock(x, y, z - 1),
2740  m_World->GetBlock(x, y, z + 1)
2741  );
2742  BlockBox.Move(x, y, z);
2743 
2744  PlacementBoxes.push_back(BlockBox);
2745 
2746  if (HasInitializedBounds)
2747  {
2748  PlacingBounds = PlacingBounds.Union(BlockBox);
2749  }
2750  else
2751  {
2752  PlacingBounds = BlockBox;
2753  HasInitializedBounds = true;
2754  }
2755  }
2756 
2757  cWorld * World = GetWorld();
2758 
2759  // Check to see if any entity intersects any block being placed
2760  return !World->ForEachEntityInBox(PlacingBounds, [&](cEntity & a_Entity)
2761  {
2762  // The distance inside the block the entity can still be.
2763  const double EPSILON = 0.0005;
2764 
2765  if (!a_Entity.DoesPreventBlockPlacement())
2766  {
2767  return false;
2768  }
2769  cBoundingBox EntBox(a_Entity.GetPosition(), a_Entity.GetWidth() / 2, a_Entity.GetHeight());
2770  for (auto BlockBox : PlacementBoxes)
2771  {
2772  // Put in a little bit of wiggle room
2773  BlockBox.Expand(-EPSILON, -EPSILON, -EPSILON);
2774  if (EntBox.DoesIntersect(BlockBox))
2775  {
2776  return true;
2777  }
2778  }
2779  return false;
2780  }
2781  );
2782 }
2783 
2784 
2785 
2786 
2787 
2789 {
2790  if (DoesPlacingBlocksIntersectEntity(a_Blocks))
2791  {
2792  // Abort - re-send all the current blocks in the a_Blocks' coords to the client:
2793  for (auto blk2: a_Blocks)
2794  {
2795  m_World->SendBlockTo(blk2.GetX(), blk2.GetY(), blk2.GetZ(), *this);
2796  }
2797  return false;
2798  }
2799 
2800  // Call the "placing" hooks; if any fail, abort:
2802  for (auto blk: a_Blocks)
2803  {
2804  if (pm->CallHookPlayerPlacingBlock(*this, blk))
2805  {
2806  // Abort - re-send all the current blocks in the a_Blocks' coords to the client:
2807  for (auto blk2: a_Blocks)
2808  {
2809  m_World->SendBlockTo(blk2.GetX(), blk2.GetY(), blk2.GetZ(), *this);
2810  }
2811  return false;
2812  }
2813  } // for blk - a_Blocks[]
2814 
2815  // Set the blocks:
2816  m_World->SetBlocks(a_Blocks);
2817 
2818  // Notify the blockhandlers:
2819  cChunkInterface ChunkInterface(m_World->GetChunkMap());
2820  for (auto blk: a_Blocks)
2821  {
2822  cBlockHandler * newBlock = BlockHandler(blk.m_BlockType);
2823  newBlock->OnPlacedByPlayer(ChunkInterface, *m_World, *this, blk);
2824  }
2825 
2826  // Call the "placed" hooks:
2827  for (auto blk: a_Blocks)
2828  {
2829  pm->CallHookPlayerPlacedBlock(*this, blk);
2830  }
2831  return true;
2832 }
2833 
2834 
2835 
2836 
2837 
2838 void cPlayer::SetSkinParts(int a_Parts)
2839 {
2840  m_SkinParts = a_Parts & spMask;
2842 }
2843 
2844 
2845 
2846 
2847 
2849 {
2850  m_MainHand = a_Hand;
2852 }
2853 
2854 
2855 
2856 
2857 
2858 void cPlayer::AttachTo(cEntity * a_AttachTo)
2859 {
2860  // Different attach, if this is a spectator
2861  if (IsGameModeSpectator())
2862  {
2863  m_AttachedTo = a_AttachTo;
2865  return;
2866  }
2867 
2868  super::AttachTo(a_AttachTo);
2869 }
2870 
2871 
2872 
2873 
2874 
2876 {
2877  if (m_AttachedTo == nullptr)
2878  {
2879  // The player is not attached to anything. Bail out.
2880  return;
2881  }
2882 
2883  // Different detach, if this is a spectator
2884  if (IsGameModeSpectator())
2885  {
2886  GetClientHandle()->SendCameraSetTo(*this);
2888  m_AttachedTo = nullptr;
2889  return;
2890  }
2891 
2892  super::Detach();
2893  int PosX = POSX_TOINT;
2894  int PosY = POSY_TOINT;
2895  int PosZ = POSZ_TOINT;
2896 
2897  // Search for a position within an area to teleport player after detachment
2898  // Position must be solid land with two air blocks above.
2899  // If nothing found, player remains where they are
2900  for (int x = PosX - 1; x <= (PosX + 1); ++x)
2901  {
2902  for (int y = PosY; y <= (PosY + 3); ++y)
2903  {
2904  for (int z = PosZ - 1; z <= (PosZ + 1); ++z)
2905  {
2906  if (
2907  (m_World->GetBlock(x, y, z) == E_BLOCK_AIR) &&
2908  (m_World->GetBlock(x, y + 1, z) == E_BLOCK_AIR) &&
2909  cBlockInfo::IsSolid(m_World->GetBlock(x, y - 1, z))
2910  )
2911  {
2912  TeleportToCoords(x + 0.5, y, z + 0.5);
2913  return;
2914  }
2915  }
2916  }
2917  }
2918 }
2919 
2920 
2921 
2922 
2923 
2925 {
2926  ASSERT(m_ClientHandle != nullptr);
2927  m_ClientHandle.reset();
2928 }
2929 
2930 
2931 
2932 
2933 
2935 {
2936  AString UUID = a_UUID.ToLongString();
2937 
2938  AString res(FILE_IO_PREFIX "players/");
2939  res.append(UUID, 0, 2);
2940  res.push_back('/');
2941  res.append(UUID, 2, AString::npos);
2942  res.append(".json");
2943  return res;
2944 }
2945 
2946 
2947 
2948 
2949 
2950 void cPlayer::FreezeInternal(const Vector3d & a_Location, bool a_ManuallyFrozen)
2951 {
2952  SetSpeed(0, 0, 0);
2953  SetPosition(a_Location);
2954  m_IsFrozen = true;
2955  m_IsManuallyFrozen = a_ManuallyFrozen;
2956 
2957  double NormalMaxSpeed = GetNormalMaxSpeed();
2958  double SprintMaxSpeed = GetSprintingMaxSpeed();
2959  double FlyingMaxpeed = GetFlyingMaxSpeed();
2960  bool IsFlying = m_IsFlying;
2961 
2962  // Set the client-side speed to 0
2963  m_NormalMaxSpeed = 0;
2964  m_SprintingMaxSpeed = 0;
2965  m_FlyingMaxSpeed = 0;
2966  m_IsFlying = true;
2967 
2968  // Send the client its fake speed and max speed of 0
2973 
2974  // Keep the server side speed variables as they were in the first place
2975  m_NormalMaxSpeed = NormalMaxSpeed;
2976  m_SprintingMaxSpeed = SprintMaxSpeed;
2977  m_FlyingMaxSpeed = FlyingMaxpeed;
2978  m_IsFlying = IsFlying;
2979 }
2980 
2981 
2982 
2983 
2984 
2986 {
2987  if (a_Meta >= 8)
2988  {
2989  a_Meta = 0;
2990  }
2991  return static_cast<float>(a_Meta + 1) / 9.0f;
2992 }
2993 
2994 
2995 
2996 
2997 
2999 {
3001  if ((Block != E_BLOCK_WATER) && (Block != E_BLOCK_STATIONARY_WATER))
3002  {
3003  return false;
3004  }
3006  float f = GetLiquidHeightPercent(Meta) - 0.11111111f;
3007  float f1 = static_cast<float>(m_Stance + 1) - f;
3008  bool flag = (m_Stance < f1);
3009  return flag;
3010 }
3011 
3012 
3013 
3014 
3015 
3017 {
3018  float f = GetEquippedItem().GetHandler()->GetBlockBreakingStrength(a_Block);
3019  if (f > 1.0f)
3020  {
3021  unsigned int efficiencyModifier = GetEquippedItem().m_Enchantments.GetLevel(cEnchantments::eEnchantment::enchEfficiency);
3022  if (efficiencyModifier > 0)
3023  {
3024  f += (efficiencyModifier * efficiencyModifier) + 1;
3025  }
3026  }
3027 
3029  if (Haste != nullptr)
3030  {
3031  int intensity = Haste->GetIntensity() + 1;
3032  f *= 1.0f + (intensity * 0.2f);
3033  }
3034 
3035  auto MiningFatigue = GetEntityEffect(cEntityEffect::effMiningFatigue);
3036  if (MiningFatigue != nullptr)
3037  {
3038  int intensity = MiningFatigue->GetIntensity();
3039  switch (intensity)
3040  {
3041  case 0: f *= 0.3f; break;
3042  case 1: f *= 0.09f; break;
3043  case 2: f *= 0.0027f; break;
3044  default: f *= 0.00081f; break;
3045 
3046  }
3047  }
3048 
3049  if (IsInsideWater() && !(GetEquippedItem().m_Enchantments.GetLevel(cEnchantments::eEnchantment::enchAquaAffinity) > 0))
3050  {
3051  f /= 5.0f;
3052  }
3053 
3054  if (!IsOnGround())
3055  {
3056  f /= 5.0f;
3057  }
3058 
3059  return f;
3060 }
3061 
3062 
3063 
3064 
3065 
3067 {
3068  float blockHardness = cBlockInfo::GetHardness(a_Block);
3069  float digSpeed = GetDigSpeed(a_Block);
3070  float canHarvestBlockDivisor = GetEquippedItem().GetHandler()->CanHarvestBlock(a_Block) ? 30.0f : 100.0f;
3071  // LOGD("blockHardness: %f, digSpeed: %f, canHarvestBlockDivisor: %f\n", blockHardness, digSpeed, canHarvestBlockDivisor);
3072  return (blockHardness < 0) ? 0 : ((digSpeed / blockHardness) / canHarvestBlockDivisor);
3073 }
3074 
3075 
3076 
3077 
3078 
3079 float cPlayer::GetExplosionExposureRate(Vector3d a_ExplosionPosition, float a_ExlosionPower)
3080 {
3081  if (
3082  IsGameModeSpectator() ||
3083  (IsGameModeCreative() && !IsOnGround())
3084  )
3085  {
3086  return 0; // No impact from explosion
3087  }
3088 
3089  return super::GetExplosionExposureRate(a_ExplosionPosition, a_ExlosionPower);
3090 }
3091 
3092 
3093 
3094 
3095 
3096 
3097 
3098 
3099 
3100 
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 SetSprint(bool a_IsSprinting)
Starts or stops sprinting, sends the max speed update to the client, if needed.
Definition: Player.cpp:884
void SetCanFly(bool a_CanFly)
If true the player can fly even when he&#39;s not in creative.
Definition: Player.cpp:900
AString ToLongString() const
Converts the UUID to a long form string (i.e.
Definition: UUID.cpp:151
AString m_MsgNameColorCode
Definition: Player.h:609
double GetPosY(void) const
Definition: Entity.h:207
void SetBlocks(const sSetBlockVector &a_Blocks)
Performs the specified single-block set operations simultaneously, as if SetBlock() was called for ea...
Definition: World.cpp:2153
void SetFlyingMaxSpeed(double a_Speed)
Sets the flying relative maximum speed.
Definition: Player.cpp:851
void SetFlying(bool a_IsFlying)
Flags the player as flying.
Definition: Player.cpp:968
void CopyToItems(cItems &a_Items)
Copies the non-empty slots into a_ItemStacks; preserves the original a_Items contents.
Definition: Inventory.cpp:472
bool IsValid(void) const
Returns true iff the chunk block data is valid (loaded / generated)
Definition: Chunk.h:72
void SetFoodSaturationLevel(double a_FoodSaturationLevel)
Definition: Player.cpp:629
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:2729
int FinishChargingBow(void)
Finishes charging the current bow.
Definition: Player.cpp:556
const cItem & GetEquippedBoots(void) const
Definition: Inventory.h:166
double GetPitch(void) const
Definition: Entity.h:210
eMainHand
Definition: Defines.h:216
virtual void BroadcastEntityAnimation(const cEntity &a_Entity, Int8 a_Animation, const cClientHandle *a_Exclude=nullptr) override
bool IsClimbing(void) const
Returns whether the player is climbing (ladders, vines etc.)
Definition: Player.cpp:2529
void SendMessage(const AString &a_Message)
Definition: Player.cpp:1408
eGameMode
Definition: Defines.h:116
double GetPosX(void) const
Definition: Entity.h:206
static bool Delete(const AString &a_Path)
Deletes a file or a folder, returns true if successful.
Definition: File.cpp:304
void SendHotbarActiveSlot(void)
Definition: Player.cpp:748
void SetTeam(cTeam *a_Team)
Sets the player team, nullptr if none.
Definition: Player.cpp:1305
BLOCKTYPE GetBlock(Vector3i a_BlockPos)
Returns the block type at the specified position.
Definition: World.h:416
int m_FoodLevel
Represents the food bar, one point equals half a "drumstick".
Definition: Player.h:626
StatValue GetValue(const eStatistic a_Stat) const
Return the value of the specified stat.
Definition: Statistics.cpp:150
T x
Definition: Vector3.h:17
void SendMessageFatal(const AString &a_Message)
Definition: Player.cpp:1453
eEntityType GetEntityType(void) const
Definition: Entity.h:168
eMonsterType GetMobType(void) const
Definition: Monster.h:68
cTeam * UpdateTeam(void)
Forces the player to query the scoreboard for his team.
Definition: Player.cpp:1329
int GetXpLevel(void)
Gets the current level - XpLevel.
Definition: Player.cpp:469
cItemHandler * GetHandler(void) const
Returns the cItemHandler responsible for this item type.
Definition: Item.cpp:137
virtual bool IsCrouched(void) const override
Definition: Player.h:568
void OpenHorseInventory()
Opens the inventory of any tame horse the player is riding.
Definition: Player.cpp:2270
virtual void BroadcastSpawnEntity(cEntity &a_Entity, const cClientHandle *a_Exclude=nullptr) override
static bool Rename(const AString &a_OrigPath, const AString &a_NewPath)
Renames a file or folder, returns true if successful.
Definition: File.cpp:377
double m_FlyingMaxSpeed
Max speed, relative to the game default flying max speed, when flying.
Definition: Player.h:685
void SendEntityVelocity(const cEntity &a_Entity)
static eStatistic GetPrerequisite(const eStatistic a_Type)
Returns stat prerequisite.
Definition: Statistics.cpp:130
cSlotNums m_InventoryPaintSlots
Definition: Player.h:664
void TickFreezeCode()
Definition: Player.cpp:367
virtual bool CanHarvestBlock(BLOCKTYPE a_BlockType)
Returns whether this tool / item can harvest a specific block (e.g.
virtual bool DoesPreventBlockPlacement(void) const
Returns whether blocks can be placed intersecting this entities&#39; hitbox.
Definition: Entity.h:199
void SendMessagePrivateMsg(const AString &a_Message, const AString &a_Sender)
Definition: Player.cpp:1462
void SendMessageInfo(const AString &a_Message)
Definition: Player.cpp:1417
bool AllowsFriendlyFire(void) const
Definition: Scoreboard.h:159
void SetSprintingMaxSpeed(double a_Speed)
Sets the sprinting relative maximum speed.
Definition: Player.cpp:837
#define VERIFY(x)
Definition: Globals.h:339
UInt32 m_FloaterID
Definition: Player.h:707
cChunk * GetParentChunk()
Returns the chunk responsible for ticking this entity.
Definition: Entity.h:540
static void LoadFromJson(const Json::Value &a_Value, cItemGrid &a_Grid)
const AString & GetDefaultRank(void) const
Returns the name of the default rank.
Definition: RankManager.h:253
void SetNormalMaxSpeed(double a_Speed)
Sets the normal relative maximum speed.
Definition: Player.cpp:823
AString ToShortString() const
Converts the UUID to a short form string (i.e without dashes).
Definition: UUID.cpp:133
void SetInvulnerableTicks(int a_InvulnerableTicks)
Set the invulnerable ticks from the entity.
Definition: Entity.h:515
int GetEquippedSlotNum(void)
Returns slot number of equiped item.
Definition: Inventory.h:149
static bool IsSolid(BLOCKTYPE a_Type)
Definition: BlockInfo.h:48
void SendAboveActionBarMessage(const AString &a_Message)
Definition: Player.cpp:1498
unsigned int AwardAchievement(const eStatistic a_Ach)
Awards the player an achievement.
Definition: Player.cpp:1605
int m_BowCharge
Definition: Player.h:705
AString GetPrefix(void) const
Returns the player name prefix, may contain @ format directives.
Definition: Player.cpp:1870
unsigned char BLOCKTYPE
The datatype used by blockdata.
Definition: ChunkDef.h:42
size_t Size(void) const
Definition: Item.h:257
void SetFoodLevel(int a_FoodLevel)
Definition: Player.cpp:611
virtual bool DoTakeDamage(TakeDamageInfo &a_TDI)
Makes this entity take damage specified in the a_TDI.
Definition: Entity.cpp:384
bool HasCustomName(void) const
Returns true if the player has a custom name.
Definition: Player.h:488
bool RemoveOneEquippedItem(void)
Removes one item out of the currently equipped item stack, returns true if successful, false if empty-handed.
Definition: Inventory.cpp:207
bool m_IsFrozen
If true, we are locking m_Position to m_FrozenPosition.
Definition: Player.h:667
MTRand & GetRandomProvider()
Returns the current thread&#39;s random number source.
Definition: FastRandom.cpp:20
double GetMaxSpeed(void) const
Returns the current relative maximum speed (takes current sprinting / flying state into account) ...
Definition: Player.cpp:803
void SendExperience(void)
Definition: Player.cpp:760
double m_LastGroundHeight
Definition: Pawn.h:77
eGameMode m_GameMode
Definition: Player.h:654
void SendBlocksAround(int a_BlockX, int a_BlockY, int a_BlockZ, 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:2681
long GetSize(void) const
Returns the size of file, in bytes, or -1 for failure; asserts if not open.
Definition: File.cpp:232
#define FILE_IO_PREFIX
Definition: Globals.h:196
virtual void DoSetSpeed(double a_SpeedX, double a_SpeedY, double a_SpeedZ) override
Sets the speed and sends it to the client, so that they are forced to move so.
Definition: Player.cpp:1748
virtual bool DoMoveToWorld(cWorld *a_World, bool a_ShouldSendRespawn, Vector3d a_NewPosition) override
Moves the player to the specified world.
Definition: Player.cpp:2006
static cBlockHandler * GetHandler(BLOCKTYPE a_Type)
Definition: BlockInfo.h:57
eChatType
Definition: Defines.h:140
cWindow * GetWindow(void)
Definition: Player.h:239
void SetPosition(double a_PosX, double a_PosY, double a_PosZ)
Definition: Entity.h:226
void StartEating(void)
Starts eating the currently equipped item.
Definition: Player.cpp:684
virtual void BroadcastEntityMetadata(const cEntity &a_Entity, const cClientHandle *a_Exclude=nullptr) override
int m_SkinParts
Displayed skin part bit mask.
Definition: Player.h:733
void SendPlayerSpawn(const cPlayer &a_Player)
void TossEquippedItem(char a_Amount=1)
tosses the item in the selected hotbar slot
Definition: Player.cpp:1923
AString GetPlayerListName(void) const
Returns the name that is used in the playerlist.
Definition: Player.cpp:1888
cWorld * m_World
Definition: Entity.h:620
virtual void Heal(int a_Health) override
Heals the player by the specified amount of HPs (positive only); sends health update.
Definition: Player.cpp:601
cClientHandlePtr m_ClientHandle
Definition: Player.h:662
virtual void Detach(void)
Detaches from the currently attached entity, if any.
Definition: Entity.cpp:1988
const cItem & GetEquippedItem(void) const
Definition: Player.h:142
virtual float GetBlockBreakingStrength(BLOCKTYPE a_Block)
Returns the strength to break a specific block.
Definition: Player.h:27
void Unfreeze()
Cancels Freeze(...) and allows the player to move naturally.
Definition: Player.cpp:1684
AString GetPlayerRankName(const cUUID &a_PlayerUUID)
Returns the name of the rank that the specified player has assigned to them.
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
void SendInventorySlot(char a_WindowID, short a_SlotNum, const cItem &a_Item)
void SetSkinParts(int a_Parts)
Definition: Player.cpp:2838
int ChangeSlotCount(int a_SlotNum, int a_AddToCount)
Adds (or subtracts, if a_AddToCount is negative) to the count of items in the specified slot...
Definition: ItemGrid.cpp:443
cItem & GetDraggingItem(void)
In UI windows, get the item that the player is dragging.
Definition: Player.h:437
bool IsEmpty(void) const
Definition: Item.h:116
AStringVector GetPlayerPermissions(const cUUID &a_PlayerUUID)
Returns the permissions that the specified player has assigned to them.
AString m_CustomName
Definition: Player.h:730
virtual void Detach(void) override
Detaches from the currently attached entity, if any.
Definition: Player.cpp:2875
virtual void BroadcastPlayerListUpdatePing(const cPlayer &a_Player, const cClientHandle *a_Exclude=nullptr) override
void SetIsTicking(bool a_IsTicking)
Set the entity&#39;s status to either ticking or not ticking.
Definition: Entity.cpp:1688
AStringVector GetPlayerRestrictions(const cUUID &a_PlayerUUID)
Returns the restrictions that the specified player has assigned to them.
virtual void OnPlacedByPlayer(cChunkInterface &a_ChunkInterface, cWorldInterface &a_WorldInterface, cPlayer &a_Player, const sSetBlock &a_BlockChange)
Called by cPlayer::PlaceBlocks() for each block after it has been set to the world.
void TossHeldItem(char a_Amount=1)
tosses the item held in hand (when in UI windows)
Definition: Player.cpp:1948
static cItemHandler * GetItemHandler(int a_ItemType)
Definition: ItemHandler.cpp:74
static const char * Delimiter
Definition: ChatColor.h:12
void ScheduleMoveToWorld(cWorld *a_World, Vector3d a_NewPosition, bool a_ShouldSetPortalCooldown=false, bool a_ShouldSendRespawn=false)
Schedules a MoveToWorld call to occur on the next Tick of the entity.
Definition: Entity.cpp:1313
bool LoadFromDisk(cWorldPtr &a_World)
Loads the player data from the disk file Sets a_World to the world where the player will spawn...
Definition: Player.cpp:2098
bool AddPlayer(const AString &a_Name)
Adds a new player to the team.
Definition: Scoreboard.cpp:213
bool IsMob(void) const
Definition: Entity.h:173
bool GetRankVisuals(const AString &a_RankName, AString &a_MsgPrefix, AString &a_MsgSuffix, AString &a_MsgNameColorCode)
Returns the message visuals of an existing rank.
cWorld * GetWorld(const AString &a_WorldName)
Returns a pointer to the world specified.
Definition: Root.cpp:641
bool m_IsCrouched
Definition: Player.h:687
AString GetSuffix(void) const
Returns the player name suffix, may contain @ format directives.
Definition: Player.cpp:1879
eDamageType DamageType
Definition: Entity.h:59
virtual short GetDurabilityLossByAction(eDurabilityLostAction a_Action)
Get the durability lost which the item will get, when a specified action was performed.
unsigned int GetLevel(int a_EnchantmentID) const
Returns the level for the specified enchantment; 0 if not stored.
cRankManager * GetRankManager(void)
Definition: Root.h:117
cWorld * GetBedWorld()
Definition: Player.cpp:959
void SendPlayerMaxSpeed(void)
Informs the client of the maximum player speed (1.6.1+)
virtual bool IsInWater(void) const
Returns true if any part of the entity is in a water block.
Definition: Entity.h:500
OwnedEntity RemoveEntity(cEntity &a_Entity)
Releases ownership of the given entity if it was found in this chunk.
Definition: Chunk.cpp:1816
virtual bool IsOnGround(void) const override
Returns whether the entity is on ground or not.
Definition: Player.h:134
cWindow * m_InventoryWindow
Definition: Player.h:646
void TossItems(const cItems &a_Items)
Tosses a list of items.
Definition: Player.cpp:1987
void SetPitch(double a_Pitch)
Definition: Entity.cpp:2070
const AString & GetName(void) const
Definition: Player.h:277
bool LoadFromFile(const AString &a_FileName, cWorldPtr &a_World)
Loads the player data from the specified file Sets a_World to the world where the player will spawn...
Definition: Player.cpp:2168
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:240
Definition: Horse.h:11
unsigned char NIBBLETYPE
The datatype used by nibbledata (meta, light, skylight)
Definition: ChunkDef.h:45
void HandleFood(void)
Called in each tick to handle food-related processing.
Definition: Player.cpp:2454
void SetVisible(bool a_bVisible)
Definition: Player.cpp:1764
const AString & GetLoadedWorldName()
Definition: Player.h:411
void SetBedPos(const Vector3i &a_Pos)
Sets the player&#39;s bed (home / respawn) position to the specified position.
Definition: Player.cpp:938
bool CallHookKilled(cEntity &a_Victim, TakeDamageInfo &a_TDI, AString &a_DeathMessage)
void SetGameMode(eGameMode a_GameMode)
Sets the gamemode for the player.
Definition: Player.cpp:1525
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:2427
eWeather GetWeather(void) const
Returns the current weather.
Definition: World.h:991
static const int MAX_FOOD_LEVEL
Definition: Player.h:35
Represents two sets of coords, minimum and maximum for each direction.
Definition: BoundingBox.h:23
int ReadRestOfFile(AString &a_Contents)
Reads the file from current position till EOF into an AString; returns the number of bytes read or -1...
Definition: File.cpp:262
bool SaveToDisk(void)
Saves all player data, such as inventory, to JSON.
Definition: Player.cpp:2299
virtual void KilledBy(TakeDamageInfo &a_TDI) override
Called when the health drops below zero.
Definition: Player.cpp:1078
float m_Health
Definition: Entity.h:584
bool PlaceBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
Calls the block-placement hook and places the block in the world, unless refused by the hook...
Definition: Player.cpp:2671
AString GetColor(void) const
Returns the full color code to use for this player, based on their rank.
Definition: Player.cpp:1854
double GetWidth(void) const
Definition: Entity.h:216
static bool PermissionMatches(const AStringVector &a_Permission, const AStringVector &a_Template)
Returns true iff a_Permission matches the a_Template.
Definition: Player.cpp:1819
int m_FoodTickTimer
Count-up to the healing or damaging action, based on m_FoodLevel.
Definition: Player.h:632
static cPluginManager * Get(void)
Returns the instance of the Plugin Manager (there is only ever one)
Definition: Chunk.h:49
AStringVector m_Permissions
All the permissions that this player has, based on their rank.
Definition: Player.h:593
virtual void Destroyed() override
Definition: Pawn.cpp:39
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:1936
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:1395
static void SaveToJson(Json::Value &a_Value, const cItemGrid &a_Grid)
virtual bool DoTakeDamage(TakeDamageInfo &TDI) override
Filters out damage for creative mode / friendly fire.
Definition: Player.cpp:1001
StatValue AddValue(const eStatistic a_Stat, const StatValue a_Delta=1)
Increments the specified stat.
Definition: Statistics.cpp:172
double GetRoll(void) const
Definition: Entity.h:211
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:2738
bool IsGameModeSpectator(void) const
Returns true if the world is in Spectator mode.
Definition: World.h:141
T y
Definition: Vector3.h:17
NIBBLETYPE GetBlockMeta(Vector3i a_BlockPos)
Returns the block meta at the specified position.
Definition: World.h:431
void SetPosY(double a_PosY)
Definition: Entity.h:224
void SendWeather(eWeather a_Weather)
const cItem & GetEquippedItem(void) const
Returns current equiped item.
Definition: Inventory.cpp:386
void CancelChargingBow(void)
Cancels the current bow charging.
Definition: Player.cpp:571
Vector3d GetThrowStartPos(void) const
Returns the position where projectiles thrown by this player should start, player eye position + adju...
Definition: Player.cpp:1709
void SetFoodExhaustionLevel(double a_FoodExhaustionLevel)
Definition: Player.cpp:647
virtual void Destroy(bool a_ShouldBroadcast=true)
Destroys the entity and schedules it for memory freeing; if a_ShouldBroadcast is set to true...
Definition: Entity.cpp:219
void SetTouchGround(bool a_bTouchGround)
Definition: Player.cpp:583
virtual void OnFoodEaten(cWorld *a_World, cPlayer *a_Player, cItem *a_Item)
Called after the player has eaten this item.
virtual ~cPlayer() override
Definition: Player.cpp:206
double GetHeight(void) const
Definition: Entity.h:204
void SendCameraSetTo(const cEntity &a_Entity)
virtual void TeleportToEntity(cEntity &a_Entity)
Teleports to the entity specified.
Definition: Entity.cpp:1855
T z
Definition: Vector3.h:17
void QueueTask(std::function< void(cWorld &)> a_Task)
Queues a task onto the tick thread.
Definition: World.cpp:3010
cTeam * m_Team
Definition: Player.h:709
static const int Height
Definition: ChunkDef.h:135
Vector3d m_LastPosition
Definition: Entity.h:616
void AddInventoryPaintSlot(int a_SlotNum)
Adds a slot to the list for inventory painting.
Definition: Player.cpp:783
bool IsPawn(void) const
Definition: Entity.h:174
void SetMainHand(eMainHand a_Hand)
Definition: Player.cpp:2848
void SetMaxHealth(float a_MaxHealth)
Sets the maximum value for the health.
Definition: Entity.cpp:1798
bool CallHookSpawnedEntity(cWorld &a_World, cEntity &a_Entity)
virtual void BroadcastSoundEffect(const AString &a_SoundName, Vector3d a_Position, float a_Volume, float a_Pitch, const cClientHandle *a_Exclude=nullptr) override
AString m_MsgSuffix
Definition: Player.h:608
Definition: UUID.h:10
bool PlaceBlocks(const sSetBlockVector &a_Blocks)
Calls the block placement hooks and places the blocks in the world.
Definition: Player.cpp:2788
std::vector< AString > AStringVector
Definition: StringUtils.h:14
Utilities to allow casting a cWorld to one of its interfaces without including World.h.
Definition: OpaqueWorld.h:12
void SetIP(const AString &a_IP)
Definition: Player.cpp:1596
cBoundingBox Union(const cBoundingBox &a_Other)
Returns the union of the two bounding boxes.
cEnchantments m_Enchantments
Definition: Item.h:212
const cSlotNums & GetInventoryPaintSlots(void) const
Returns the list of slots currently stored for inventory painting.
Definition: Player.cpp:793
bool IsGameModeAdventure(void) const
Returns true if the player is in Adventure mode, either explicitly, or by inheriting from current wor...
Definition: Player.cpp:1278
void Move(double a_OffX, double a_OffY, double a_OffZ)
Moves the entire boundingbox by the specified offset.
Definition: BoundingBox.cpp:62
cWorld * m_SpawnWorld
The world which the player respawns in upon death.
Definition: Player.h:652
void SetIsFishing(bool a_IsFishing, UInt32 a_FloaterID=cEntity::INVALID_ID)
Definition: Player.h:353
void SetRoll(double a_Roll)
Definition: Entity.cpp:2081
void Normalize(void)
Definition: Vector3.h:44
static cUUID GenerateVersion3(const AString &a_Name)
Generates a version 3, variant 1 UUID based on the md5 hash of a_Name.
Definition: UUID.cpp:263
void UpdateItems(void)
Update items (e.g.
Definition: Inventory.cpp:609
static bool IsFile(const AString &a_Path)
Returns true if the specified path is a regular file.
Definition: File.cpp:425
void LoadRank(void)
(Re)loads the rank and permissions from the cRankManager.
Definition: Player.cpp:2632
Container for a single chat message composed of multiple functional parts.
Definition: CompositeChat.h:31
bool GetBlocks(sSetBlockVector &a_Blocks, bool a_ContinueOnFailure)
Retrieves block types of the specified blocks.
Definition: World.cpp:2171
virtual void BroadcastDestroyEntity(const cEntity &a_Entity, const cClientHandle *a_Exclude=nullptr) override
bool m_bVisible
Definition: Player.h:622
void SendMessageFailure(const AString &a_Message)
Definition: Player.cpp:1426
bool DoesPlacingBlocksIntersectEntity(const sSetBlockVector &a_Blocks)
Whether placing the given blocks would intersect any entitiy.
Definition: Player.cpp:2722
Definition: Defines.h:133
const cItem & GetEquippedLeggings(void) const
Definition: Inventory.h:165
Int64 m_EatingFinishTick
The world tick in which eating will be finished.
Definition: Player.h:695
Vector3d GetLookVector(void) const
Definition: Entity.cpp:2209
bool m_bDirtyExperience
Definition: Player.h:702
float FinalDamage
Definition: Entity.h:62
double GetSpawnY(void) const
Definition: World.h:692
bool CallHookPlayerPlacingBlock(cPlayer &a_Player, const sSetBlock &a_BlockChange)
cStatManager m_Stats
Definition: Player.h:711
Definition: File.h:37
unsigned int m_TicksUntilNextSave
How long till the player&#39;s inventory will be saved Default save interval is #defined in PLAYER_INVENT...
Definition: Player.h:719
bool IsFrozen()
Is the player frozen?
Definition: Player.cpp:1675
Definition: World.h:65
float GetLiquidHeightPercent(NIBBLETYPE a_Meta)
Returns how high the liquid is in percent.
Definition: Player.cpp:2985
eGameMode GetGameMode(void) const
Returns the current game mode.
Definition: World.h:129
void Add(const cItem &a_Item)
Definition: Item.h:254
void SendEntityHeadLook(const cEntity &a_Entity)
double m_SprintingMaxSpeed
Max speed, relative to the game default max speed, when sprinting.
Definition: Player.h:680
bool IsTicking(void) const
Returns true if the entity is valid and ticking.
Definition: Entity.cpp:2201
bool IsFlying(void) const
Returns true if the player is currently flying.
Definition: Player.h:345
AString m_MsgPrefix
Definition: Player.h:608
void Respawn(void)
Definition: Player.cpp:1204
bool m_IsManuallyFrozen
Was the player frozen manually by a plugin or automatically by the server?
Definition: Player.h:670
double m_FoodSaturationLevel
"Overcharge" for the m_FoodLevel; is depleted before m_FoodLevel
Definition: Player.h:629
bool Open(const AString &iFileName, eMode iMode)
Definition: File.cpp:50
double GetNormalMaxSpeed(void) const
Gets the normal relative maximum speed.
Definition: Player.h:458
cEntityEffect * GetEntityEffect(cEntityEffect::eType a_EffectType)
Returns the entity effect, if it is currently applied or nullptr if not.
Definition: Pawn.cpp:489
void InvalidateCachedSentChunk()
#define PLAYER_INVENTORY_SAVE_INTERVAL
Definition: Player.cpp:34
double Length(void) const
Definition: Vector3.h:95
static const int MAX_HEALTH
Definition: Player.h:33
virtual void OpenedByPlayer(cPlayer &a_Player)
Definition: Window.cpp:286
char m_ItemCount
Definition: Item.h:210
void SetCrouch(bool a_IsCrouched)
Sets the crouch status, broadcasts to all visible players.
Definition: Player.cpp:867
int GetPosX(void) const
Definition: Chunk.h:150
float GetXpPercentage(void)
Gets the experience bar percentage - XpP.
Definition: Player.cpp:478
AString m_IP
Definition: Player.h:655
Vector3< double > Vector3d
Definition: Vector3.h:445
float GetDigSpeed(BLOCKTYPE a_Block)
Returns the dig speed using the current tool on the block a_Block.
Definition: Player.cpp:3016
const cItem & GetEquippedHelmet(void) const
Definition: Inventory.h:163
virtual void Tick(std::chrono::milliseconds a_Dt, cChunk &a_Chunk) override
Definition: Player.cpp:259
void CollectPickupsByPlayer(cPlayer &a_Player)
Definition: World.cpp:2438
#define POSX_TOINT
Definition: Entity.h:29
double GetEyeHeight(void) const
Definition: Player.cpp:1242
virtual cBoundingBox GetPlacementCollisionBox(BLOCKTYPE a_XM, BLOCKTYPE a_XP, BLOCKTYPE a_YM, BLOCKTYPE a_YP, BLOCKTYPE a_ZM, BLOCKTYPE a_ZP)
Returns the relative bounding box that must be entity-free in order for the block to be placed...
void RemoveClientHandle(void)
Called by cClientHandle when the client is being destroyed.
Definition: Player.cpp:2924
bool IsDestroyed() const
Deprecated.
Definition: Entity.h:264
void LOGINFO(const char *a_Format, fmt::ArgList a_ArgList)
Definition: Logger.cpp:165
float GetPlayerRelativeBlockHardness(BLOCKTYPE a_Block)
Returns the relative block hardness for the block a_Block.
Definition: Player.cpp:3066
std::chrono::steady_clock::time_point m_LastPlayerListTime
Definition: Player.h:660
AString & Printf(AString &str, const char *format, fmt::ArgList args)
Output the formatted text into the string.
Definition: StringUtils.cpp:55
double m_FoodExhaustionLevel
A "buffer" which adds up hunger before it is substracted from m_FoodSaturationLevel or m_FoodLevel...
Definition: Player.h:635
#define POSY_TOINT
Definition: Entity.h:30
bool CallHookPlayerPlacedBlock(cPlayer &a_Player, const sSetBlock &a_BlockChange)
virtual void DoSetSpeed(double a_SpeedX, double a_SpeedY, double a_SpeedZ)
Does the actual speed-setting.
Definition: Entity.cpp:1698
int DeltaExperience(int a_Xp_delta)
Definition: Player.cpp:511
#define PLAYER_LIST_TIME_MS
Definition: Player.cpp:37
virtual Int64 GetWorldAge(void) const override
Definition: World.h:109
void SetViewDistance(int a_ViewDistance)
Sets the maximal view distance.
Definition: Defines.h:132
float GetHealth(void) const
Returns the health of this entity.
Definition: Entity.h:380
bool IsGameModeCreative(void) const
Returns true if the world is in Creative mode.
Definition: World.h:132
cScoreboard & GetScoreBoard(void)
Returns the associated scoreboard instance.
Definition: World.h:883
bool Feed(int a_Food, double a_Saturation)
Adds to FoodLevel and FoodSaturationLevel, returns true if any food has been consumed, false if player "full".
Definition: Player.cpp:656
virtual void BroadcastPlayerListAddPlayer(const cPlayer &a_Player, const cClientHandle *a_Exclude=nullptr) override
#define ASSERT(x)
Definition: Globals.h:335
void LOGWARNING(const char *a_Format, fmt::ArgList a_ArgList)
Definition: Logger.cpp:174
cWindow * m_CurrentWindow
Definition: Player.h:645
bool UpdatePlayerName(const cUUID &a_PlayerUUID, const AString &a_NewPlayerName)
Updates the playername that is saved with this uuid.
Vector3i m_LastBedPos
The player&#39;s last saved bed position.
Definition: Player.h:649
#define LOGD(...)
Definition: LoggerSimple.h:40
void SetCapabilities()
Definition: Player.cpp:1557
void SetWorld(cWorld *a_World)
Sets the internal world pointer to a new cWorld, doesn&#39;t update anything else.
Definition: Entity.h:533
virtual eDimension GetDimension(void) const override
Definition: World.h:151
virtual void BroadcastPlayerListUpdateGameMode(const cPlayer &a_Player, const cClientHandle *a_Exclude=nullptr) override
void Empty(void)
Definition: Item.h:92
void StartChargingBow(void)
Starts charging the equipped bow.
Definition: Player.cpp:544
bool m_IsFishing
Definition: Player.h:690
void NotifyNearbyWolves(cPawn *a_Opponent, bool a_IsPlayerInvolved)
Notify nearby wolves that the player or one of the player&#39;s wolves took damage or did damage to an en...
Definition: Player.cpp:1054
void CloseWindow(bool a_CanRefuse=true)
Closes the current window, resets current window to m_InventoryWindow.
Definition: Player.cpp:1370
void SendEntityEquipment(const cEntity &a_Entity, short a_SlotNum, const cItem &a_Item)
void SendMessageRaw(const AString &a_MessageRaw, eChatType a_Type=eChatType::ctChatBox)
Definition: Player.cpp:1480
void SendPlayerPosition(void)
float GetMaxHealth(void) const
Definition: Entity.h:417
virtual void ResetPosition(Vector3d a_NewPosition) override
Set the entities position and last sent position.
Definition: Pawn.cpp:499
int m_AirLevel
Air level of a mobile.
Definition: Entity.h:660
void Clear(void)
Removes all items from the entire inventory.
Definition: Inventory.cpp:40
void FreezeInternal(const Vector3d &a_Location, bool a_ManuallyFrozen)
Pins the player to a_Location until Unfreeze() is called.
Definition: Player.cpp:2950
double GetSpawnZ(void) const
Definition: World.h:693
Vector3i GetLastBedPos(void) const
Gets the last position that the player slept in This is initialised to the world spawn point if the p...
Definition: Player.h:500
void UpdateMovementStats(const Vector3d &a_DeltaPos, bool a_PreviousIsOnGround)
Update movement-related statistics.
Definition: Player.cpp:2556
void ClearInventoryPaintSlots(void)
Clears the list of slots that are being inventory-painted.
Definition: Player.cpp:773
#define UNUSED
Definition: Globals.h:152
void Freeze(const Vector3d &a_Location)
Prevent the player from moving and lock him into a_Location.
Definition: Player.cpp:1666
Definition: Pawn.h:15
bool ShouldBroadcastDeathMessages(void) const
Definition: World.h:900
void BroadcastChatLeave(const AString &a_Message)
Definition: Root.h:185
void SetSpeed(double a_SpeedX, double a_SpeedY, double a_SpeedZ)
Sets the speed of the entity, measured in m / sec.
Definition: Entity.cpp:2091
T Clamp(T a_Value, T a_Min, T a_Max)
Clamp X to the specified range.
Definition: Globals.h:351
virtual void BroadcastTeleportEntity(const cEntity &a_Entity, const cClientHandle *a_Exclude=nullptr) override
virtual void BroadcastPlayerListRemovePlayer(const cPlayer &a_Player, const cClientHandle *a_Exclude=nullptr) override
cBlockHandler * BlockHandler(BLOCKTYPE a_BlockType)
Definition: BlockInfo.h:159
virtual void Killed(cEntity *a_Victim) override
Called when the entity kills another entity.
Definition: Player.cpp:1177
bool IsArmor(short a_ItemType)
Definition: Defines.h:1152
virtual void TeleportToCoords(double a_PosX, double a_PosY, double a_PosZ) override
Teleports to the coordinates specified.
Definition: Player.cpp:1648
void SendMessageSuccess(const AString &a_Message)
Definition: Player.cpp:1435
void SendWholeWindow(cClientHandle &a_Client)
Sends the contents of the whole window to the specified client.
Definition: Window.cpp:729
bool IsSatiated(void) const
Returns true if the player is satiated, i.
Definition: Player.h:328
void SendMessageWarning(const AString &a_Message)
Definition: Player.cpp:1444
eMainHand m_MainHand
The main hand of the player.
Definition: Player.h:736
static bool CreateFolderRecursive(const AString &a_FolderPath)
Creates a new folder with the specified name, creating its parents if needed.
Definition: File.cpp:467
const cItem & GetSlot(int a_SlotNum) const
Returns current item in a_SlotNum slot.
Definition: Inventory.cpp:313
void FromRaw(const std::array< Byte, 16 > &a_Raw)
Assigns from raw memory representation, respecting UUID variant.
Definition: UUID.cpp:238
virtual bool ClosedByPlayer(cPlayer &a_Player, bool a_CanRefuse)
Called when a player closes this window; notifies all slot areas.
Definition: Window.cpp:308
AStringVectorVector m_SplitRestrictions
All the restrictions that this player has, based on their rank, split into individual dot-delimited p...
Definition: Player.h:604
cWorld * GetDefaultWorld(void)
Definition: Root.cpp:632
double GetYaw(void) const
Definition: Entity.h:209
cChunkMap * GetChunkMap(void)
Definition: World.h:1044
void TakeDamage(cEntity &a_Attacker)
Makes this pawn take damage from an attack by a_Attacker.
Definition: Entity.cpp:269
cEntity * m_AttachedTo
The entity to which this entity is attached (vehicle), nullptr if none.
Definition: Entity.h:588
void GenerateOfflineUUID(void)
Generates an UUID based on the username stored for this client, and stores it in the m_UUID member...
std::string AString
Definition: StringUtils.h:13
const AString & GetName(void) const
Returns the name of the world.
Definition: World.h:874
void EulerToVector(double a_Pan, double a_Pitch, double &a_X, double &a_Y, double &a_Z)
Definition: Defines.h:914
#define FLOGD(...)
Definition: LoggerSimple.h:48
bool IsPlayer(void) const
Definition: Entity.h:171
bool HasPermission(const AString &a_Permission)
Definition: Player.cpp:1783
double GetSprintingMaxSpeed(void) const
Gets the sprinting relative maximum speed.
Definition: Player.h:461
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:1698
static const int MAX_AIR_LEVEL
Maximum air an entity can have.
Definition: Entity.h:149
void FinishEating(void)
Finishes eating the currently equipped item.
Definition: Player.cpp:698
virtual void Heal(int a_HitPoints)
Heals the specified amount of HPs.
Definition: Entity.cpp:822
static int XpForLevel(int a_Level)
Calculates the amount of XP needed for a given level Ref: https://minecraft.gamepedia.com/XP.
Definition: Player.cpp:447
static int CalcLevelFromXp(int a_CurrentXp)
Inverse of XpForLevel Ref: https://minecraft.gamepedia.com/XP values are as per this with pre-calcula...
Definition: Player.cpp:425
bool LoadFromJson(Json::Value &a_Value)
Definition: Inventory.cpp:667
void SendPlayerMoveLook(void)
void AddShowAchievementPart(const AString &a_PlayerName, const AString &a_Achievement, const AString &a_Style="")
Adds a part that fully formats a specified achievement using client translatable strings Takes achiev...
cTeam * QueryPlayerTeam(const AString &a_Name)
Definition: Scoreboard.cpp:431
virtual void AttachTo(cEntity *a_AttachTo) override
Attaches to the specified entity; detaches from any previous one first.
Definition: Player.cpp:2858
void SetCustomName(const AString &a_CustomName)
Sets the custom name of this player.
Definition: Player.cpp:915
void AbortEating(void)
Aborts the current eating operation.
Definition: Player.cpp:726
bool m_IsChargingBow
Definition: Player.h:704
bool IsGameModeSurvival(void) const
Returns true if the player is in Survival mode, either explicitly, or by inheriting from current worl...
Definition: Player.cpp:1269
int GetPosZ(void) const
Definition: Chunk.h:151
AString m_LoadedWorldName
Definition: Player.h:612
void TossPickup(const cItem &a_Item)
tosses a pickup newly created from a_Item
Definition: Player.cpp:1975
static cRoot * Get()
Definition: Root.h:51
void LOG(const char *a_Format, fmt::ArgList a_ArgList)
Definition: Logger.cpp:156
double GetFlyingMaxSpeed(void) const
Gets the flying relative maximum speed.
Definition: Player.h:464
int m_LifetimeTotalXp
Player Xp level.
Definition: Player.h:698
virtual void BroadcastChatDeath(const AString &a_Message, const cClientHandle *a_Exclude=nullptr) override
Definition: World.h:176
Vector3d GetEyePosition(void) const
Definition: Player.cpp:1251
bool m_bIsTeleporting
Flag used by food handling system to determine whether a teleport has just happened Will not apply fo...
Definition: Player.h:724
int m_CurrentXp
Definition: Player.h:699
void UseEquippedItem(short a_Damage=1)
Damage the player&#39;s equipped item by a_Damage, possibly less if the equipped item is enchanted...
Definition: Player.cpp:2397
double m_NormalMaxSpeed
Max speed, relative to the game default.
Definition: Player.h:675
eStatistic
Definition: Statistics.h:13
void SendSystemMessage(const AString &a_Message)
Definition: Player.cpp:1489
void PlayerOpenWindow(cPlayer &a_Player)
Definition: Horse.cpp:295
virtual bool IsSprinting(void) const override
Definition: Player.h:569
Definition: Entity.h:73
AStringVector StringSplit(const AString &str, const AString &delim)
Split the string at any of the listed delimiters.
Definition: StringUtils.cpp:76
bool RandBool(double a_TrueProbability=0.5)
Return a random bool with the given probability of being true.
Definition: FastRandom.h:158
virtual void ApplyArmorDamage(int DamageBlocked) override
Applies damage to the armor after the armor blocked the given amount.
Definition: Player.cpp:987
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:2510
const Vector3d & GetPosition(void) const
Exported in ManualBindings.
Definition: Entity.h:307
bool CanMobsTarget(void) const
Returns true if the player can be targeted by Mobs.
Definition: Player.cpp:1296
Represents a UI window.
Definition: Window.h:53
void ForceSetSpeed(const Vector3d &a_Speed)
Forces the player to move in the given direction.
Definition: Player.cpp:1739
virtual void AttachTo(cEntity *a_AttachTo)
Attaches to the specified entity; detaches from any previous one first.
Definition: Entity.cpp:1962
void SetFoodTickTimer(int a_FoodTickTimer)
Definition: Player.cpp:638
std::unique_ptr< cEntity > OwnedEntity
Definition: ChunkDef.h:32
virtual float GetExplosionExposureRate(Vector3d a_ExplosionPosition, float a_ExlosionPower) override
get player explosion exposure rate
Definition: Player.cpp:3079
Vector3< int > Vector3i
Definition: Vector3.h:447
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:179
bool ShouldBroadcastAchievementMessages(void) const
Definition: World.h:901
void SendPlayerAbilities(void)
virtual void Destroyed(void) override
Definition: Player.cpp:230
Definition: Wolf.h:12
void SendHealth(void)
Definition: Player.cpp:736
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:491
double GetPosZ(void) const
Definition: Entity.h:208
AString m_Rank
The name of the rank assigned to this player.
Definition: Player.h:590
bool IsGameModeCreative(void) const
Returns true if the player is in Creative mode, either explicitly, or by inheriting from current worl...
Definition: Player.cpp:1260
bool m_IsFlying
Definition: Player.h:689
static const int EATING_TICKS
Number of ticks it takes to eat an item.
Definition: Player.h:38
char GetWindowID(void) const
Definition: Window.h:80
#define POSZ_TOINT
Definition: Entity.h:31
short m_ItemType
Definition: Item.h:209
void AddPlayer(std::unique_ptr< cPlayer > a_Player, cWorld *a_OldWorld=nullptr)
Adds the player to the world.
Definition: World.cpp:2447
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:437
Vector3d GetThrowSpeed(double a_SpeedCoeff) const
Returns the initial speed vector of a throw, with a 3D length of a_SpeedCoeff.
Definition: Player.cpp:1725
void StopEveryoneFromTargetingMe()
Tells all pawns which are targeting us to stop targeting us.
Definition: Pawn.cpp:458
cPlayer(cClientHandlePtr a_Client, const AString &a_PlayerName)
Definition: Player.cpp:88
virtual const char * GetClass(void) const
Returns the topmost class name for the object.
Definition: Entity.cpp:113
virtual void Tick(std::chrono::milliseconds a_Dt, cChunk &a_Chunk) override
Definition: Pawn.cpp:49
const cUUID & GetUUID(void) const
Returns the UUID that has been read from the client, or nil if not available.
Definition: Player.h:521
void SetYaw(double a_Yaw)
Definition: Entity.cpp:2059
int StatValue
Definition: Statistics.h:120
double m_Stance
Definition: Player.h:637
bool IsGameModeSpectator(void) const
Returns true if the player is in Spectator mode, either explicitly, or by inheriting from current wor...
Definition: Player.cpp:1287
void StopBurning(void)
Stops the entity from burning, resets all burning timers.
Definition: Entity.cpp:1836
void SetPosX(double a_PosX)
Definition: Entity.h:223
cItemGrid m_EnderChestContents
An item grid that stores the player specific enderchest contents.
Definition: Player.h:643
eGameMode GetEffectiveGameMode(void) const
Returns the current effective gamemode (inherited gamemode is resolved before returning) ...
Definition: Player.h:179
bool m_CanFly
Definition: Player.h:692
virtual float GetExplosionExposureRate(Vector3d a_ExplosionPosition, float a_ExlosionPower)
a lightweight calculation approach to get explosion exposure rate
Definition: Entity.cpp:2259
cItem m_DraggingItem
The item being dragged by the cursor while in a UI window.
Definition: Player.h:658
void SaveToJson(Json::Value &a_Value)
Definition: Inventory.cpp:622
virtual void KilledBy(TakeDamageInfo &a_TDI) override
Called when the health drops below zero.
Definition: Pawn.cpp:129
AString m_PlayerName
Definition: Player.h:611
cItemGrid & GetHotbarGrid(void)
Returns the cItemGrid object representing the hotbar slots.
Definition: Inventory.h:109
AStringVectorVector m_SplitPermissions
All the permissions that this player has, based on their rank, split into individual dot-delimited pa...
Definition: Player.h:600
AString StrToLower(const AString &s)
Returns a lower-cased copy of the string.
std::enable_if< std::is_arithmetic< T >::value, C >::type FloorC(T a_Value)
Floors a value, then casts it to C (an int by default)
Definition: Globals.h:362
cInventory & GetInventory(void)
Definition: Player.h:136
bool m_IsSprinting
Definition: Player.h:688
void ReceiveNearbyFightInfo(const cUUID &a_PlayerUUID, cPawn *a_Opponent, bool a_IsPlayerInvolved)
Notfies the wolf of a nearby fight.
Definition: Wolf.cpp:117
void Close(void)
Definition: File.cpp:100
void SetPosZ(double a_PosZ)
Definition: Entity.h:225
eDurabilityLostAction
Actions that may cause durability of an item may be lost, where the magnitude of the loss depends on ...
Definition: ItemHandler.h:27
Definition: Item.h:36
const cItem & GetEquippedChestplate(void) const
Definition: Inventory.h:164
#define UNREACHABLE(x)
Use to mark code that should be impossible to reach.
Definition: Globals.h:344
cItemHandler * ItemHandler(int a_ItemType)
Definition: ItemHandler.h:174
void AddFoodExhaustion(double a_Exhaustion)
Adds the specified exhaustion to m_FoodExhaustion.
Definition: Player.cpp:672
void AddPlayerScore(const AString &a_Name, cObjective::eType a_Type, cObjective::Score a_Value=1)
Definition: Scoreboard.cpp:546
cEntity * Attacker
Definition: Entity.h:60
AString GetUUIDFileName(const cUUID &a_UUID)
Returns the filename for the player data based on the UUID given.
Definition: Player.cpp:2934
std::vector< sSetBlock > sSetBlockVector
Definition: ChunkDef.h:564
#define PREPARE_REL_AND_CHUNK(Position, OriginalChunk)
Definition: Chunk.h:43
std::shared_ptr< cClientHandle > cClientHandlePtr
Definition: ClientHandle.h:39
UInt32 GetUniqueID(void) const
Definition: Entity.h:261
cInventory m_Inventory
Stores the player&#39;s inventory, consisting of crafting grid, hotbar, and main slots.
Definition: Player.h:640
void OpenWindow(cWindow &a_Window)
Opens the specified window; closes the current one first using CloseWindow()
Definition: Player.cpp:1349
virtual void SendBlockTo(int a_X, int a_Y, int a_Z, cPlayer &a_Player) override
Sends the block on those coords to the player.
Definition: World.cpp:2224
std::array< Byte, 16 > ToRaw() const
Converts UUID to raw memory representation, respecting UUID variant.
Definition: UUID.cpp:214
cUUID m_UUID
The UUID of the player, as read from the ClientHandle.
Definition: Player.h:728
virtual void BroadcastChat(const AString &a_Message, const cClientHandle *a_Exclude=nullptr, eMessageType a_ChatPrefix=mtCustom) override
bool RemovePlayer(const AString &a_Name)
Removes a player from the team.
Definition: Scoreboard.cpp:222
cWorld * GetWorld(void) const
Definition: Entity.h:201
This class bridges a vector of cItem for safe access via Lua.
Definition: Item.h:234
cClientHandle * GetClientHandle(void) const
Returns the raw client handle associated with the player.
Definition: Player.h:254
virtual bool EatItem(cPlayer *a_Player, cItem *a_Item)
Lets the player eat a selected item.
cPluginManager * GetPluginManager(void)
Definition: Root.h:114
std::vector< int > cSlotNums
List of slot numbers, used for inventory-painting.
Definition: Defines.h:9
void SetEquippedSlotNum(int a_SlotNum)
Sets equiped item to the a_SlotNum slot number.
Definition: Inventory.cpp:395
void SetDraggingItem(const cItem &a_Item)
In UI windows, set the item that the player is dragging.
Definition: Player.cpp:1910
static float GetHardness(BLOCKTYPE a_Type)
Definition: BlockInfo.h:53
virtual void BroadcastMovementUpdate(const cClientHandle *a_Exclude=nullptr)
Updates clients of changes in the entity.
Definition: Entity.cpp:1878
AStringVector m_Restrictions
All the restrictions that this player has, based on their rank.
Definition: Player.h:596
double GetSpawnX(void) const
Definition: World.h:691
static const AString & GetName(const eStatistic a_Type)
Type -> Name.
Definition: Statistics.cpp:102
virtual bool Initialize(OwnedEntity a_Self, cWorld &a_World) override
Spawns the entity in the world; returns true if spawned, false if not (plugin disallowed).
Definition: Player.cpp:187
bool IsInsideWater()
Checks if the player is inside of water.
Definition: Player.cpp:2998