Cuberite
A lightweight, fast and extensible game server for Minecraft
BlockBed.cpp
Go to the documentation of this file.
1 
2 // BlockBed.cpp
3 
4 #include "Globals.h"
5 #include "BlockBed.h"
6 
7 #include "BroadcastInterface.h"
8 #include "../Entities/Player.h"
9 #include "../World.h"
10 #include "../BoundingBox.h"
11 #include "../Mobs/Monster.h"
12 
13 
14 
15 
16 
18  cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface,
19  const Vector3i a_BlockPos,
20  BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta,
21  const cEntity * a_Digger
22 ) const
23 {
24  UNUSED(a_Digger);
25  auto Direction = MetaDataToDirection(a_OldBlockMeta & 0x03);
26  if ((a_OldBlockMeta & 0x08) != 0)
27  {
28  // Was pillow
29  Vector3i FootPos(a_BlockPos - Direction);
30  if (a_ChunkInterface.GetBlock(FootPos) == E_BLOCK_BED)
31  {
32  // First replace the bed with air
33  a_ChunkInterface.FastSetBlock(FootPos, E_BLOCK_AIR, 0);
34 
35  // Then destroy the bed entity
36  a_ChunkInterface.SetBlock(FootPos, E_BLOCK_AIR, 0);
37  }
38  }
39  else
40  {
41  // Was foot end
42  Vector3i PillowPos(a_BlockPos + Direction);
43  if (a_ChunkInterface.GetBlock(PillowPos) == E_BLOCK_BED)
44  {
45  // First replace the bed with air
46  a_ChunkInterface.FastSetBlock(PillowPos, E_BLOCK_AIR, 0);
47 
48  // Then destroy the bed entity
49  a_ChunkInterface.SetBlock(PillowPos, E_BLOCK_AIR, 0);
50  }
51  }
52 }
53 
54 
55 
56 
57 
59  cChunkInterface & a_ChunkInterface,
60  cWorldInterface & a_WorldInterface,
61  cPlayer & a_Player,
62  Vector3i a_BlockPos,
63  eBlockFace a_BlockFace,
64  const Vector3i a_CursorPos
65 ) const
66 {
67  // Source: https://minecraft.wiki/w/Bed#Sleeping
68 
69  // Sleeping in bed only allowed in Overworld, beds explode elsewhere:
70  if (a_WorldInterface.GetDimension() != dimOverworld)
71  {
72  auto PosCopy = a_BlockPos;
73  a_WorldInterface.DoExplosionAt(5, a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, true, esBed, &PosCopy);
74  return true;
75  }
76 
77  auto Meta = a_ChunkInterface.GetBlockMeta(a_BlockPos);
78 
79  if ((Meta & 0x8) == 0)
80  {
81  // Clicked on the foot of the bed, adjust to the head:
82  a_BlockPos += MetaDataToDirection(Meta & 0x03);
83 
85  a_ChunkInterface.GetBlockTypeMeta(a_BlockPos, Type, Meta);
86  if (Type != E_BLOCK_BED)
87  {
88  // Bed was incomplete, bail:
89  return true;
90  }
91  }
92 
93  // Set the bed position to the pillow block:
94  a_Player.SetBedPos(a_BlockPos);
95 
96  // Sleeping is allowed only during night and thunderstorms:
97  if (
98  !(((a_WorldInterface.GetTimeOfDay() > 12541_tick) && (a_WorldInterface.GetTimeOfDay() < 23458_tick)) ||
99  (a_Player.GetWorld()->GetWeather() == wThunderstorm))
100  )
101  {
102  a_Player.SendAboveActionBarMessage("You can only sleep at night and during thunderstorms");
103  return true;
104  }
105 
106  // Check if the bed is occupied:
107  if ((Meta & 0x04) == 0x04)
108  {
109  a_Player.SendAboveActionBarMessage("This bed is occupied");
110  return true;
111  }
112 
113  // Cannot sleep if there are hostile mobs nearby:
114  if (
115  !a_Player.GetWorld()->ForEachEntityInBox({ a_Player.GetPosition().addedY(-5), 8, 10 }, [](cEntity & a_Entity)
116  {
117  return a_Entity.IsMob() && (static_cast<cMonster&>(a_Entity).GetMobFamily() == cMonster::mfHostile);
118  })
119  )
120  {
121  a_Player.SendAboveActionBarMessage("You may not rest now, there are monsters nearby");
122  return true;
123  }
124 
125  // This will broadcast "use bed" for the pillow block, if the player can sleep:
126  a_Player.SetIsInBed(true);
127 
128  // Check sleeping was successful, if not, bail:
129  if (!a_Player.IsInBed())
130  {
131  return true;
132  }
133 
134  // Occupy the bed, where 0x4 = occupied bit:
135  a_ChunkInterface.SetBlockMeta(a_BlockPos, Meta | 0x04);
137 
138  // When sleeping, the player's bounding box moves to approximately where his head is.
139  // Set the player's position to somewhere close to the edge of the pillow block:
140  a_Player.SetPosition(Vector3f(0.4f, 1, 0.4f) * MetaDataToDirection(Meta & 0x03) + Vector3f(0.5f, 0.6875, 0.5f) + a_BlockPos);
141 
142  // Fast-forward the time if all players in the world are in their beds:
143  if (a_WorldInterface.ForEachPlayer([](cPlayer & a_OtherPlayer) { return !a_OtherPlayer.IsInBed(); }))
144  {
145  a_WorldInterface.ForEachPlayer([&a_ChunkInterface](cPlayer & a_OtherPlayer)
146  {
147  VacateBed(a_ChunkInterface, a_OtherPlayer);
148  return false;
149  });
150  a_WorldInterface.SetTimeOfDay(0_tick);
151  }
152 
153  return true;
154 }
155 
156 
157 
158 
159 
160 cItems cBlockBedHandler::ConvertToPickups(const NIBBLETYPE a_BlockMeta, const cItem * const a_Tool) const
161 {
162  // Drops handled by the block entity:
163  return {};
164 }
@ E_BLOCK_AIR
Definition: BlockType.h:10
@ E_BLOCK_BED
Definition: BlockType.h:36
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
@ wThunderstorm
Definition: Defines.h:168
@ dimOverworld
Definition: Defines.h:233
@ esBed
Definition: Defines.h:310
eBlockFace
Block face constants, used in PlayerDigging and PlayerBlockPlacement packets and bbox collision calc.
Definition: Defines.h:38
#define UNUSED
Definition: Globals.h:72
Direction
Vector3< float > Vector3f
Definition: Vector3.h:486
static Vector3i MetaDataToDirection(NIBBLETYPE a_MetaData)
Definition: BlockBed.h:31
virtual void OnBroken(cChunkInterface &a_ChunkInterface, cWorldInterface &a_WorldInterface, const Vector3i a_BlockPos, BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta, const cEntity *a_Digger) const override
Definition: BlockBed.cpp:17
virtual bool OnUse(cChunkInterface &a_ChunkInterface, cWorldInterface &a_WorldInterface, cPlayer &a_Player, const Vector3i a_ClickedBlockPos, eBlockFace a_ClickedBlockFace, const Vector3i a_CursorPos) const override
Definition: BlockBed.cpp:58
static void VacateBed(cChunkInterface &a_ChunkInterface, cPlayer &a_Player)
Definition: BlockBed.h:43
virtual cItems ConvertToPickups(NIBBLETYPE a_BlockMeta, const cItem *a_Tool) const override
Definition: BlockBed.cpp:160
bool GetBlockTypeMeta(Vector3i a_Pos, BLOCKTYPE &a_BlockType, NIBBLETYPE &a_BlockMeta)
void SetBlockMeta(Vector3i a_BlockPos, NIBBLETYPE a_MetaData)
Sets the meta for the specified block, while keeping the blocktype.
void SetBlock(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
Sets the block at the specified coords to the specified value.
NIBBLETYPE GetBlockMeta(Vector3i a_Pos)
BLOCKTYPE GetBlock(Vector3i a_Pos)
void FastSetBlock(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
Sets the block at the specified coords to the specified value.
virtual cTickTime GetTimeOfDay(void) const =0
virtual void DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_BlockY, double a_BlockZ, bool a_CanCauseFire, eExplosionSource a_Source, void *a_SourceData)=0
virtual void SetTimeOfDay(cTickTime a_TimeOfDay)=0
virtual bool ForEachPlayer(cPlayerListCallback a_Callback)=0
Calls the callback for each player in the list; returns true if all players processed,...
virtual eDimension GetDimension(void) const =0
Definition: Entity.h:76
void SetPosition(double a_PosX, double a_PosY, double a_PosZ)
Definition: Entity.h:218
cWorld * GetWorld(void) const
Definition: Entity.h:190
Definition: Player.h:29
void SendAboveActionBarMessage(const AString &a_Message)
Definition: Player.cpp:1272
StatisticsManager & GetStatistics()
Return the associated statistic and achievement manager.
Definition: Player.h:237
void SetBedPos(Vector3i a_Position)
Sets the player's bed position to the specified position.
Definition: Player.cpp:786
bool IsInBed(void) const
Returns true if a player is sleeping in a bed.
Definition: Player.cpp:451
void SetIsInBed(bool a_IsInBed)
Sets a player's in-bed state.
Definition: Player.cpp:496
Definition: Item.h:37
This class bridges a vector of cItem for safe access via Lua.
Definition: Item.h:215
std::unordered_map< CustomStatistic, StatValue > Custom
T x
Definition: Vector3.h:17
T y
Definition: Vector3.h:17
T z
Definition: Vector3.h:17
virtual bool ForEachEntityInBox(const cBoundingBox &a_Box, cEntityCallback a_Callback) override
Calls the callback for each entity that has a nonempty intersection with the specified boundingbox.
Definition: World.cpp:2445
eWeather GetWeather(void) const
Returns the current weather.
Definition: World.h:808