Cuberite
A lightweight, fast and extensible game server for Minecraft
ItemBucket.h
Go to the documentation of this file.
1 
2 #pragma once
3 
4 #include "ItemHandler.h"
5 #include "../BlockInfo.h"
6 #include "../World.h"
7 #include "../Simulator/FluidSimulator.h"
8 #include "../Blocks/BlockHandler.h"
9 #include "../LineBlockTracer.h"
10 #include "../Blocks/ChunkInterface.h"
11 
12 
13 
14 
15 
16 class cItemBucketHandler final :
17  public cItemHandler
18 {
20 
21 public:
22 
23  constexpr cItemBucketHandler(int a_ItemType):
24  Super(a_ItemType)
25  {
26 
27  }
28 
29 
30 
31 
32 
33  virtual bool OnItemUse(
34  cWorld * a_World,
35  cPlayer * a_Player,
36  cBlockPluginInterface & a_PluginInterface,
37  const cItem & a_HeldItem,
38  const Vector3i a_ClickedBlockPos,
39  eBlockFace a_ClickedBlockFace
40  ) const override
41  {
42  switch (m_ItemType)
43  {
44  case E_ITEM_BUCKET: return ScoopUpFluid(a_World, a_Player, a_HeldItem, a_ClickedBlockPos, a_ClickedBlockFace);
45  case E_ITEM_LAVA_BUCKET: return PlaceFluid (a_World, a_Player, a_PluginInterface, a_HeldItem, a_ClickedBlockPos, a_ClickedBlockFace, E_BLOCK_LAVA);
46  case E_ITEM_WATER_BUCKET: return PlaceFluid (a_World, a_Player, a_PluginInterface, a_HeldItem, a_ClickedBlockPos, a_ClickedBlockFace, E_BLOCK_WATER);
47  default:
48  {
49  ASSERT(!"Unhandled ItemType");
50  return false;
51  }
52  }
53  }
54 
55 
56 
57 
58 
59  bool ScoopUpFluid(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, const Vector3i a_ClickedBlockPos, eBlockFace a_ClickedBlockFace) const
60  {
61  // Players can't pick up fluid while in adventure mode.
62  if (a_Player->IsGameModeAdventure())
63  {
64  return false;
65  }
66 
67  // Needs a valid clicked block:
68  if (a_ClickedBlockFace != BLOCK_FACE_NONE)
69  {
70  return false;
71  }
72 
73  Vector3i BlockPos;
74  if (!GetBlockFromTrace(a_World, a_Player, BlockPos))
75  {
76  return false; // Nothing in range.
77  }
78 
79  if (a_World->GetBlockMeta(BlockPos) != 0)
80  {
81  // Not a source block
82  return false;
83  }
84 
85  BLOCKTYPE Block = a_World->GetBlock(BlockPos);
86  ENUM_ITEM_TYPE NewItemType;
87 
88  if (IsBlockWater(Block))
89  {
90  NewItemType = E_ITEM_WATER_BUCKET;
91  }
92  else if (IsBlockLava(Block))
93  {
94  NewItemType = E_ITEM_LAVA_BUCKET;
95  }
96  else
97  {
98  return false;
99  }
100 
101  // Check to see if destination block is too far away
102  // Reach Distance Multiplayer = 5 Blocks
103  if ((BlockPos.x - a_Player->GetPosX() > 5) || (BlockPos.z - a_Player->GetPosZ() > 5))
104  {
105  return false;
106  }
107 
108  // Remove water / lava block (unless plugins disagree):
109  if (!a_Player->PlaceBlock(BlockPos, E_BLOCK_AIR, 0))
110  {
111  return false;
112  }
113 
114  // Give new bucket, filled with fluid when the gamemode is not creative:
115  if (!a_Player->IsGameModeCreative())
116  {
117  a_Player->ReplaceOneEquippedItemTossRest(cItem(NewItemType));
118  }
119 
120  return true;
121  }
122 
123 
124 
125 
126 
128  cWorld * a_World, cPlayer * a_Player, cBlockPluginInterface & a_PluginInterface, const cItem & a_Item,
129  const Vector3i a_BlockPos, eBlockFace a_BlockFace, BLOCKTYPE a_FluidBlock
130  ) const
131  {
132  // Players can't place fluid while in adventure mode.
133  if (a_Player->IsGameModeAdventure())
134  {
135  return false;
136  }
137 
138  if (a_BlockFace != BLOCK_FACE_NONE)
139  {
140  return false;
141  }
142 
143  BLOCKTYPE CurrentBlockType;
144  NIBBLETYPE CurrentBlockMeta;
145  eBlockFace EntryFace;
146  Vector3i BlockPos;
147  if (!GetPlacementCoordsFromTrace(a_World, a_Player, BlockPos, CurrentBlockType, CurrentBlockMeta, EntryFace))
148  {
149  return false;
150  }
151 
152  // Check to see if destination block is too far away
153  // Reach Distance Multiplayer = 5 Blocks
154  if ((BlockPos.x - a_Player->GetPosX() > 5) || (BlockPos.z - a_Player->GetPosZ() > 5))
155  {
156  return false;
157  }
158 
159  // Give back an empty bucket if the gamemode is not creative:
160  if (!a_Player->IsGameModeCreative())
161  {
163  }
164 
165  // Wash away anything that was there prior to placing:
166  if (cFluidSimulator::CanWashAway(CurrentBlockType))
167  {
168  if (a_PluginInterface.CallHookPlayerBreakingBlock(*a_Player, BlockPos, EntryFace, CurrentBlockType, CurrentBlockMeta))
169  {
170  // Plugin disagrees with the washing-away
171  return false;
172  }
173  a_World->DropBlockAsPickups(BlockPos, a_Player, nullptr);
174  a_PluginInterface.CallHookPlayerBrokenBlock(*a_Player, BlockPos, EntryFace, CurrentBlockType, CurrentBlockMeta);
175  }
176 
177  // Place the actual fluid block:
178  return a_Player->PlaceBlock(BlockPos, a_FluidBlock, 0);
179  }
180 
181 
182 
183 
184 
185  bool GetBlockFromTrace(cWorld * a_World, cPlayer * a_Player, Vector3i & a_BlockPos) const
186  {
187  class cCallbacks :
188  public cBlockTracer::cCallbacks
189  {
190  public:
191  Vector3i m_Pos;
192  bool m_HasHitFluid;
193 
194 
195  cCallbacks(void) :
196  m_HasHitFluid(false)
197  {
198  }
199 
200  virtual bool OnNextBlock(Vector3i a_BlockPosition, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, eBlockFace a_EntryFace) override
201  {
202  if (IsBlockWater(a_BlockType) || IsBlockLava(a_BlockType))
203  {
204  if (a_BlockMeta != 0) // GetBlockFromTrace is called for scooping up fluids; the hit block should be a source
205  {
206  return false;
207  }
208  m_HasHitFluid = true;
209  m_Pos = a_BlockPosition;
210  return true;
211  }
212  return false;
213  }
214  } Callbacks;
215 
216  cLineBlockTracer Tracer(*a_World, Callbacks);
217  Vector3d Start(a_Player->GetEyePosition() + a_Player->GetLookVector());
218  Vector3d End(a_Player->GetEyePosition() + a_Player->GetLookVector() * 5);
219 
220  Tracer.Trace(Start, End);
221 
222  if (!Callbacks.m_HasHitFluid)
223  {
224  return false;
225  }
226 
227 
228  a_BlockPos = Callbacks.m_Pos;
229  return true;
230  }
231 
232 
233 
234 
235 
236  bool GetPlacementCoordsFromTrace(cWorld * a_World, cPlayer * a_Player, Vector3i & a_BlockPos, BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta, eBlockFace & a_BlockFace) const
237  {
238  class cCallbacks :
239  public cBlockTracer::cCallbacks
240  {
241  public:
242  Vector3i m_Pos;
243  BLOCKTYPE m_ReplacedBlockType;
244  NIBBLETYPE m_ReplacedBlockMeta;
245  eBlockFace m_EntryFace;
246 
247  virtual bool OnNextBlock(Vector3i a_CBBlockPos, BLOCKTYPE a_CBBlockType, NIBBLETYPE a_CBBlockMeta, eBlockFace a_CBEntryFace) override
248  {
249  if ((a_CBBlockType != E_BLOCK_AIR) && !IsBlockLiquid(a_CBBlockType))
250  {
251  m_ReplacedBlockType = a_CBBlockType;
252  m_ReplacedBlockMeta = a_CBBlockMeta;
253  m_EntryFace = static_cast<eBlockFace>(a_CBEntryFace);
254  if (!cFluidSimulator::CanWashAway(a_CBBlockType))
255  {
256  a_CBBlockPos = AddFaceDirection(a_CBBlockPos, a_CBEntryFace); // Was an unwashawayable block, can't overwrite it!
257  }
258  m_Pos = a_CBBlockPos; // (Block could be washed away, replace it)
259  return true; // Abort tracing
260  }
261  return false;
262  }
263  } Callbacks;
264 
265  cLineBlockTracer Tracer(*a_World, Callbacks);
266  Vector3d Start(a_Player->GetEyePosition());
267  Vector3d End(a_Player->GetEyePosition() + a_Player->GetLookVector() * 5);
268 
269  // cLineBlockTracer::Trace() returns true when whole line was traversed. By returning true from the callback when we hit something,
270  // we ensure that this never happens if liquid could be placed
271  // Use this to judge whether the position is valid
272  if (!Tracer.Trace(Start, End))
273  {
274  a_BlockPos = Callbacks.m_Pos;
275  a_BlockType = Callbacks.m_ReplacedBlockType;
276  a_BlockMeta = Callbacks.m_ReplacedBlockMeta;
277  a_BlockFace = Callbacks.m_EntryFace;
278  return true;
279  }
280 
281  return false;
282  }
283 };
bool IsBlockWater(BLOCKTYPE a_BlockType)
Definition: BlockInfo.cpp:10
bool IsBlockLiquid(BLOCKTYPE a_BlockType)
Definition: BlockInfo.cpp:58
bool IsBlockLava(BLOCKTYPE a_BlockType)
Definition: BlockInfo.cpp:49
@ E_BLOCK_WATER
Definition: BlockType.h:18
@ E_BLOCK_AIR
Definition: BlockType.h:10
@ E_BLOCK_LAVA
Definition: BlockType.h:20
ENUM_ITEM_TYPE
Definition: BlockType.h:295
@ E_ITEM_LAVA_BUCKET
Definition: BlockType.h:371
@ E_ITEM_WATER_BUCKET
Definition: BlockType.h:370
@ E_ITEM_BUCKET
Definition: BlockType.h:369
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
void AddFaceDirection(int &a_BlockX, int &a_BlockY, int &a_BlockZ, eBlockFace a_BlockFace, bool a_bInverse)
Modifies the specified coords so that they point to the block adjacent to the one specified through i...
Definition: Defines.cpp:378
eBlockFace
Block face constants, used in PlayerDigging and PlayerBlockPlacement packets and bbox collision calc.
Definition: Defines.h:38
@ BLOCK_FACE_NONE
Definition: Defines.h:39
#define ASSERT(x)
Definition: Globals.h:276
This interface is used to decouple block handlers from the cPluginManager dependency through cWorld.
virtual bool CallHookPlayerBreakingBlock(cPlayer &a_Player, Vector3i a_BlockPos, eBlockFace a_BlockFace, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)=0
virtual bool CallHookPlayerBrokenBlock(cPlayer &a_Player, Vector3i a_BlockPos, eBlockFace a_BlockFace, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)=0
double GetPosX(void) const
Definition: Entity.h:195
double GetPosZ(void) const
Definition: Entity.h:197
Vector3d GetLookVector(void) const
Definition: Entity.cpp:2267
Definition: Player.h:29
bool IsGameModeCreative(void) const
Returns true if the player is in Creative mode, either explicitly, or by inheriting from current worl...
Definition: Player.cpp:1025
Vector3d GetEyePosition(void) const
Definition: Player.cpp:1001
void ReplaceOneEquippedItemTossRest(const cItem &)
Removes one item from the the current equipped item stack, and attempts to add the specified item sta...
Definition: Player.cpp:1745
bool IsGameModeAdventure(void) const
Returns true if the player is in Adventure mode, either explicitly, or by inheriting from current wor...
Definition: Player.cpp:1043
bool PlaceBlock(Vector3i a_Position, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
Attempts to place the block in the world with a call to PlaceBlocks.
Definition: Player.cpp:2440
Definition: Item.h:37
constexpr cItemBucketHandler(int a_ItemType)
Definition: ItemBucket.h:23
virtual bool OnItemUse(cWorld *a_World, cPlayer *a_Player, cBlockPluginInterface &a_PluginInterface, const cItem &a_HeldItem, const Vector3i a_ClickedBlockPos, eBlockFace a_ClickedBlockFace) const override
Called when the player tries to use the item (right mouse button).
Definition: ItemBucket.h:33
bool ScoopUpFluid(cWorld *a_World, cPlayer *a_Player, const cItem &a_Item, const Vector3i a_ClickedBlockPos, eBlockFace a_ClickedBlockFace) const
Definition: ItemBucket.h:59
bool GetBlockFromTrace(cWorld *a_World, cPlayer *a_Player, Vector3i &a_BlockPos) const
Definition: ItemBucket.h:185
bool GetPlacementCoordsFromTrace(cWorld *a_World, cPlayer *a_Player, Vector3i &a_BlockPos, BLOCKTYPE &a_BlockType, NIBBLETYPE &a_BlockMeta, eBlockFace &a_BlockFace) const
Definition: ItemBucket.h:236
bool PlaceFluid(cWorld *a_World, cPlayer *a_Player, cBlockPluginInterface &a_PluginInterface, const cItem &a_Item, const Vector3i a_BlockPos, eBlockFace a_BlockFace, BLOCKTYPE a_FluidBlock) const
Definition: ItemBucket.h:127
const int m_ItemType
Definition: ItemHandler.h:141
constexpr cItemHandler(int a_ItemType)
Definition: ItemHandler.h:37
friend class cItem
Definition: ItemHandler.h:25
bool Trace(Vector3d a_Start, Vector3d a_End)
Traces one line between Start and End; returns true if the entire line was traced (until OnNoMoreHits...
static bool CanWashAway(BLOCKTYPE a_BlockType)
T x
Definition: Vector3.h:17
T z
Definition: Vector3.h:17
Definition: World.h:53
bool DropBlockAsPickups(Vector3i a_BlockPos, const cEntity *a_Digger=nullptr, const cItem *a_Tool=nullptr)
Digs the specified block, and spawns the appropriate pickups for it.
Definition: World.cpp:2090
BLOCKTYPE GetBlock(Vector3i a_BlockPos) const
Returns the block type at the specified position.
Definition: World.h:363
NIBBLETYPE GetBlockMeta(Vector3i a_BlockPos) const
Returns the block meta at the specified position.
Definition: World.h:370