Cuberite
A lightweight, fast and extensible game server for Minecraft
Floater.cpp
Go to the documentation of this file.
1 
2 #include "Globals.h"
3 
4 #include "../BlockInfo.h"
5 #include "../BoundingBox.h"
6 #include "../Chunk.h"
7 #include "Floater.h"
8 #include "Player.h"
9 #include "../ClientHandle.h"
10 
11 
12 
13 
15 // cFloaterEntityCollisionCallback
17 {
18 public:
19  cFloaterEntityCollisionCallback(cFloater * a_Floater, const Vector3d & a_Pos, const Vector3d & a_NextPos) :
20  m_Floater(a_Floater),
21  m_Pos(a_Pos),
22  m_NextPos(a_NextPos),
23  m_MinCoeff(1),
24  m_HitEntity(nullptr)
25  {
26  }
27  bool operator () (cEntity & a_Entity)
28  {
29  if (!a_Entity.IsMob()) // Floaters can only pull mobs not other entities.
30  {
31  return false;
32  }
33 
34  auto EntBox = a_Entity.GetBoundingBox();
35 
36  double LineCoeff;
38  EntBox.Expand(m_Floater->GetWidth() / 2, m_Floater->GetHeight() / 2, m_Floater->GetWidth() / 2);
39  if (!EntBox.CalcLineIntersection(m_Pos, m_NextPos, LineCoeff, Face))
40  {
41  // No intersection whatsoever
42  return false;
43  }
44 
45  if (LineCoeff < m_MinCoeff)
46  {
47  // The entity is closer than anything we've stored so far, replace it as the potential victim
48  m_MinCoeff = LineCoeff;
49  m_HitEntity = &a_Entity;
50  }
51 
52  // Don't break the enumeration, we want all the entities
53  return false;
54  }
55 
57  cEntity * GetHitEntity(void) const { return m_HitEntity; }
58 
60  bool HasHit(void) const { return (m_MinCoeff < 1); }
61 
62 protected:
64  const Vector3d & m_Pos;
66  double m_MinCoeff; // The coefficient of the nearest hit on the Pos line
67 
68  // Although it's bad(tm) to store entity ptrs from a callback, we can afford it here, because the entire callback
69  // is processed inside the tick thread, so the entities won't be removed in between the calls and the final processing
70  cEntity * m_HitEntity; // The nearest hit entity
71 } ;
72 
73 
74 
75 
76 
77 cFloater::cFloater(Vector3d a_Pos, Vector3d a_Speed, UInt32 a_PlayerID, int a_CountDownTime) :
78  Super(etFloater, a_Pos, 0.25f, 0.25f),
79  m_BitePos(a_Pos),
80  m_CanPickupItem(false),
81  m_PickupCountDown(0),
82  m_CountDownTime(a_CountDownTime),
83  m_PlayerID(a_PlayerID),
84  m_AttachedMobID(cEntity::INVALID_ID)
85 {
86  SetSpeed(a_Speed);
87 }
88 
89 
90 
91 
92 
94 {
95  a_Client.SendSpawnEntity(*this);
96 }
97 
98 
99 
100 
101 
102 void cFloater::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
103 {
104  HandlePhysics(a_Dt, a_Chunk);
105 
106  PREPARE_REL_AND_CHUNK(GetPosition().Floor(), a_Chunk);
107  if (!RelSuccess)
108  {
109  return;
110  }
111 
112  auto & Random = GetRandomProvider();
113  if (IsBlockWater(Chunk->GetBlock(Rel)) && (Chunk->GetMeta(Rel) == 0))
114  {
115  if (!m_CanPickupItem && (m_AttachedMobID == cEntity::INVALID_ID)) // Check if you can't already pickup a fish and if the floater isn't attached to a mob.
116  {
117  if (m_CountDownTime <= 0)
118  {
120  m_World->BroadcastSoundEffect("entity.bobber.splash", GetPosition(), 1, 1);
121  AddSpeedY(-10);
122  m_CanPickupItem = true;
123  m_PickupCountDown = 20;
124  m_CountDownTime = Random.RandInt(100, 900);
125  LOGD("Floater %i can be picked up", GetUniqueID());
126  }
127  else if (m_CountDownTime == 20) // Calculate the position where the particles should spawn and start producing them.
128  {
129  LOGD("Started producing particles for floater %i", GetUniqueID());
130  m_ParticlePos.Set(GetPosX() + Random.RandInt(-4, 4), GetPosY(), GetPosZ() + Random.RandInt(-4, 4));
131  m_World->BroadcastParticleEffect("splash", static_cast<Vector3f>(m_ParticlePos), Vector3f{}, 0, 15);
132  }
133  else if (m_CountDownTime < 20)
134  {
136  m_World->BroadcastParticleEffect("splash", static_cast<Vector3f>(m_ParticlePos), Vector3f{}, 0, 15);
137  }
138 
139  m_CountDownTime--;
140  if (Chunk->IsWeatherWetAt(Rel))
141  {
142  if (Random.RandBool(0.25)) // 25% chance of an extra countdown when being rained on.
143  {
144  m_CountDownTime--;
145  }
146  }
147  else // if the floater is underground it has a 50% chance of not decreasing the countdown.
148  {
149  if (Random.RandBool())
150  {
151  m_CountDownTime++;
152  }
153  }
154  }
155  }
156 
157  // Check water at the top of floater otherwise it floats into the air above the water
158  if (
159  const auto Above = Rel.addedY(FloorC(GetPosY() + GetHeight()));
160  (Above.y < cChunkDef::Height) && IsBlockWater(m_World->GetBlock(Above))
161  )
162  {
163  SetSpeedY(0.7);
164  }
165 
166  if (CanPickup()) // Make sure the floater "loses its fish"
167  {
169  if (m_PickupCountDown == 0)
170  {
171  m_CanPickupItem = false;
172  LOGD("The fish is gone. Floater %i can not pick an item up.", GetUniqueID());
173  }
174  }
175 
176  if ((GetSpeed().Length() > 4) && (m_AttachedMobID == cEntity::INVALID_ID))
177  {
178  cFloaterEntityCollisionCallback Callback(this, GetPosition(), GetPosition() + GetSpeed() / 20);
179 
180  a_Chunk.ForEachEntity(Callback);
181  if (Callback.HasHit())
182  {
183  AttachTo(*Callback.GetHitEntity());
184  Callback.GetHitEntity()->TakeDamage(*this); // TODO: the player attacked the mob not the floater.
185  m_AttachedMobID = Callback.GetHitEntity()->GetUniqueID();
186  }
187  }
188 
189  if (!m_World->DoWithEntityByID(m_PlayerID, [](cEntity &) { return true; })) // The owner doesn't exist anymore. Destroy the floater entity.
190  {
191  Destroy();
192  }
193 
195  {
196  if (!m_World->DoWithEntityByID(m_AttachedMobID, [](cEntity &) { return true; }))
197  {
198  // The mob the floater was attached to doesn't exist anymore.
200  }
201  }
202 
203  SetSpeedX(GetSpeedX() * 0.95);
204  SetSpeedZ(GetSpeedZ() * 0.95);
205 
207 }
bool IsBlockWater(BLOCKTYPE a_BlockType)
Definition: BlockInfo.cpp:10
#define PREPARE_REL_AND_CHUNK(Position, OriginalChunk)
Definition: Chunk.h:32
eBlockFace
Block face constants, used in PlayerDigging and PlayerBlockPlacement packets and bbox collision calc.
Definition: Defines.h:38
MTRand & GetRandomProvider()
Returns the current thread's random number source.
Definition: FastRandom.cpp:12
unsigned int UInt32
Definition: Globals.h:157
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:347
#define LOGD
Definition: LoggerSimple.h:83
Definition: Chunk.h:36
bool ForEachEntity(cEntityCallback a_Callback) const
Calls the callback for each entity; returns true if all entities processed, false if the callback abo...
Definition: Chunk.cpp:1657
static const int Height
Definition: ChunkDef.h:125
void SendSpawnEntity(const cEntity &a_Entity)
Definition: Entity.h:76
const Vector3d & GetSpeed(void) const
Exported in ManualBindings.
Definition: Entity.h:300
cBoundingBox GetBoundingBox() const
Definition: Entity.h:211
void SetSpeedX(double a_SpeedX)
Sets the speed in the X axis, leaving the other speed components intact.
Definition: Entity.cpp:2167
double GetSpeedZ(void) const
Definition: Entity.h:204
static const UInt32 INVALID_ID
Special ID that is considered an "invalid value", signifying no entity.
Definition: Entity.h:128
void SetSpeedY(double a_SpeedY)
Sets the speed in the Y axis, leaving the other speed components intact.
Definition: Entity.cpp:2176
void SetSpeedZ(double a_SpeedZ)
Sets the speed in the Z axis, leaving the other speed components intact.
Definition: Entity.cpp:2185
void SetSpeed(double a_SpeedX, double a_SpeedY, double a_SpeedZ)
Sets the speed of the entity, measured in m / sec.
Definition: Entity.cpp:2157
double GetPosX(void) const
Definition: Entity.h:195
float GetWidth(void) const
Definition: Entity.h:205
cWorld * m_World
Definition: Entity.h:624
double GetPosZ(void) const
Definition: Entity.h:197
UInt32 GetUniqueID(void) const
Definition: Entity.h:253
void Destroy()
Destroys the entity, schedules it for memory freeing and broadcasts the DestroyEntity packet.
Definition: Entity.cpp:243
void AddSpeedY(double a_AddSpeedY)
Definition: Entity.cpp:2212
double GetPosY(void) const
Definition: Entity.h:196
void TakeDamage(cEntity &a_Attacker)
Makes this pawn take damage from an attack by a_Attacker.
Definition: Entity.cpp:272
virtual void HandlePhysics(std::chrono::milliseconds a_Dt, cChunk &a_Chunk)
Handles the physics of the entity - updates position based on speed, updates speed based on environme...
Definition: Entity.cpp:1001
float GetHeight(void) const
Definition: Entity.h:193
const Vector3d & GetPosition(void) const
Exported in ManualBindings.
Definition: Entity.h:297
void AttachTo(cEntity &a_AttachTo)
Attaches to the specified entity; detaches from any previous one first.
Definition: Entity.cpp:2027
virtual void BroadcastMovementUpdate(const cClientHandle *a_Exclude=nullptr)
Updates clients of changes in the entity.
Definition: Entity.cpp:1966
double GetSpeedX(void) const
Definition: Entity.h:202
bool IsMob(void) const
Definition: Entity.h:162
bool operator()(cEntity &a_Entity)
Definition: Floater.cpp:27
const Vector3d & m_NextPos
Definition: Floater.cpp:65
cFloaterEntityCollisionCallback(cFloater *a_Floater, const Vector3d &a_Pos, const Vector3d &a_NextPos)
Definition: Floater.cpp:19
bool HasHit(void) const
Returns true if the callback has encountered a true hit.
Definition: Floater.cpp:60
cEntity * GetHitEntity(void) const
Returns the nearest entity that was hit, after the enumeration has been completed.
Definition: Floater.cpp:57
Vector3d m_ParticlePos
Definition: Floater.h:36
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: Floater.cpp:93
UInt32 m_AttachedMobID
Definition: Floater.h:50
virtual void Tick(std::chrono::milliseconds a_Dt, cChunk &a_Chunk) override
Definition: Floater.cpp:102
int m_CountDownTime
Definition: Floater.h:46
cFloater(Vector3d a_Pos, Vector3d a_Speed, UInt32 a_PlayerID, int a_CountDownTime)
Definition: Floater.cpp:77
Vector3d m_BitePos
Definition: Floater.h:39
int m_PickupCountDown
Definition: Floater.h:45
UInt32 m_PlayerID
Definition: Floater.h:49
bool m_CanPickupItem
Definition: Floater.h:42
bool CanPickup(void) const
Definition: Floater.h:28
void Set(T a_x, T a_y, T a_z)
Definition: Vector3.h:42
BLOCKTYPE GetBlock(Vector3i a_BlockPos) const
Returns the block type at the specified position.
Definition: World.h:363
bool DoWithEntityByID(UInt32 a_UniqueID, cEntityCallback a_Callback)
Calls the callback if the entity with the specified ID is found, with the entity object as the callba...
Definition: World.cpp:2464
virtual void BroadcastParticleEffect(const AString &a_ParticleName, Vector3f a_Src, Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, const cClientHandle *a_Exclude=nullptr) override
virtual void BroadcastSoundEffect(const AString &a_SoundName, Vector3d a_Position, float a_Volume, float a_Pitch, const cClientHandle *a_Exclude=nullptr) override