Cuberite
A lightweight, fast and extensible game server for Minecraft
FallingBlock.cpp
Go to the documentation of this file.
1 #include "Globals.h"
2 
3 #include "FallingBlock.h"
4 #include "../BlockInfo.h"
5 #include "../World.h"
6 #include "../ClientHandle.h"
7 #include "../Simulator/SandSimulator.h"
8 #include "../Chunk.h"
9 
10 
11 
12 
13 
14 cFallingBlock::cFallingBlock(Vector3d a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta):
15  Super(etFallingBlock, a_Position, 0.98f, 0.98f),
16  m_BlockType(a_BlockType),
17  m_BlockMeta(a_BlockMeta)
18 {
19  SetGravity(-16.0f);
20  SetAirDrag(0.02f);
21 }
22 
23 
24 
25 
26 
27 void cFallingBlock::SpawnOn(cClientHandle & a_ClientHandle)
28 {
29  a_ClientHandle.SendSpawnEntity(*this);
30 }
31 
32 
33 
34 
35 
36 void cFallingBlock::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
37 {
38  // GetWorld()->BroadcastTeleportEntity(*this); // Test position
39 
40  int BlockX = POSX_TOINT;
41  int BlockY = static_cast<int>(GetPosY() - 0.5);
42  int BlockZ = POSZ_TOINT;
43 
44  if (BlockY < 0)
45  {
46  // Fallen out of this world, just continue falling until out of sight, then destroy:
47  if (BlockY < VOID_BOUNDARY)
48  {
49  Destroy();
50  }
51  return;
52  }
53 
54  if (BlockY >= cChunkDef::Height)
55  {
56  // Above the world, just wait for it to fall back down
57  return;
58  }
59 
60  BLOCKTYPE BlockBelow = a_Chunk.GetBlock(BlockX - a_Chunk.GetPosX() * cChunkDef::Width, BlockY, BlockZ - a_Chunk.GetPosZ() * cChunkDef::Width);
61  NIBBLETYPE BelowMeta = a_Chunk.GetMeta(BlockX - a_Chunk.GetPosX() * cChunkDef::Width, BlockY, BlockZ - a_Chunk.GetPosZ() * cChunkDef::Width);
62  if (cSandSimulator::DoesBreakFallingThrough(BlockBelow, BelowMeta))
63  {
64  // Fallen onto a block that breaks this into pickups (e. g. half-slab)
65  // Must finish the fall with coords one below the block:
67  Destroy();
68  return;
69  }
70  else if (!cSandSimulator::CanContinueFallThrough(BlockBelow))
71  {
72  // Fallen onto a solid block
73  /*
74  FLOGD(
75  "Sand: Checked below at {0} (rel {1}), it's {2}, finishing the fall.",
76  Vector3i{BlockX, BlockY, BlockZ},
77  cChunkDef::AbsoluteToRelative({BlockX, BlockY, BlockZ}, {a_Chunk.GetPosX(), a_Chunk.GetPosZ()}),
78  ItemTypeToString(BlockBelow)
79  );
80  */
81 
82  if (BlockY < cChunkDef::Height - 1)
83  {
84  cSandSimulator::FinishFalling(m_World, BlockX, BlockY + 1, BlockZ, m_BlockType, m_BlockMeta);
85  }
86  Destroy();
87  return;
88  }
89  else if ((m_BlockType == E_BLOCK_CONCRETE_POWDER) && IsBlockWater(BlockBelow))
90  {
91  // Concrete powder falling into water solidifies on the first water it touches
93  Destroy();
94  return;
95  }
96 
97  float MilliDt = a_Dt.count() * 0.001f;
98  AddSpeedY(MilliDt * -9.8f);
99  AddPosition(GetSpeed() * MilliDt);
100 
101  // If not static (one billionth precision) broadcast movement
102  if ((fabs(GetSpeedX()) > std::numeric_limits<double>::epsilon()) || (fabs(GetSpeedZ()) > std::numeric_limits<double>::epsilon()))
103  {
105  }
106 }
107 
108 
109 
110 
bool IsBlockWater(BLOCKTYPE a_BlockType)
Definition: BlockInfo.cpp:10
@ E_BLOCK_CONCRETE
Definition: BlockType.h:270
@ E_BLOCK_CONCRETE_POWDER
Definition: BlockType.h:271
unsigned char NIBBLETYPE
The datatype used by nibbledata (meta, light, skylight)
Definition: ChunkDef.h:44
unsigned char BLOCKTYPE
The datatype used by blockdata.
Definition: ChunkDef.h:41
#define POSX_TOINT
Definition: Entity.h:31
#define POSZ_TOINT
Definition: Entity.h:33
Definition: Chunk.h:36
NIBBLETYPE GetMeta(int a_RelX, int a_RelY, int a_RelZ) const
Definition: Chunk.h:279
int GetPosX(void) const
Definition: Chunk.h:131
BLOCKTYPE GetBlock(int a_RelX, int a_RelY, int a_RelZ) const
Definition: Chunk.h:146
int GetPosZ(void) const
Definition: Chunk.h:132
static const int Width
Definition: ChunkDef.h:124
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
double GetSpeedZ(void) const
Definition: Entity.h:204
static const int VOID_BOUNDARY
Y position to begin applying void damage.
Definition: Entity.h:124
void SetGravity(float a_Gravity)
Definition: Entity.h:282
cWorld * m_World
Definition: Entity.h:624
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 AddPosition(double a_AddPosX, double a_AddPosY, double a_AddPosZ)
Definition: Entity.h:242
void SetAirDrag(float a_AirDrag)
Definition: Entity.h:286
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
cFallingBlock(Vector3d a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
Creates a new falling block.
virtual void SpawnOn(cClientHandle &a_ClientHandle) override
Descendants override this function to send a command to the specified client to spawn the entity on t...
virtual void Tick(std::chrono::milliseconds a_Dt, cChunk &a_Chunk) override
BLOCKTYPE m_BlockType
Definition: FallingBlock.h:38
NIBBLETYPE m_BlockMeta
Definition: FallingBlock.h:39
static bool CanContinueFallThrough(BLOCKTYPE a_BlockType)
Returns true if an already-falling block can pass through the specified block type (e.
static void FinishFalling(cWorld *a_World, int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_FallingBlockType, NIBBLETYPE a_FallingBlockMeta)
Called when a block finishes falling at the specified coords, either by insta-fall,...
static bool DoesBreakFallingThrough(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
Returns true if the specified block breaks falling blocks while they fall through it (e.