Cuberite
A lightweight, fast and extensible game server for Minecraft
ItemLilypad.h
Go to the documentation of this file.
1 
2 #pragma once
3 
4 #include "ItemHandler.h"
5 #include "../Entities/Player.h"
6 #include "../LineBlockTracer.h"
7 
8 
9 
10 
11 
12 class cItemLilypadHandler final:
13  public cItemHandler
14 {
16 
17 public:
18 
19  constexpr cItemLilypadHandler(int a_ItemType):
20  Super(a_ItemType)
21  {
22 
23  }
24 
25 
26 
27 
28 
29  virtual bool IsPlaceable(void) const override
30  {
31  return false; // Set as not placeable so OnItemUse is called
32  }
33 
34 
35 
36 
37 
38  virtual bool OnItemUse(
39  cWorld * a_World,
40  cPlayer * a_Player,
41  cBlockPluginInterface & a_PluginInterface,
42  const cItem & a_HeldItem,
43  const Vector3i a_ClickedBlockPos,
44  eBlockFace a_ClickedBlockFace
45  ) const override
46  {
47  // The client sends BLOCK_FACE_NONE when it determines it should do a tracing-based placement.
48  // Otherwise, a normal block face is sent.
49 
50  if (a_ClickedBlockFace != BLOCK_FACE_NONE)
51  {
52  // The position the client wants the lilypad placed.
53  const auto PlacePos = AddFaceDirection(a_ClickedBlockPos, a_ClickedBlockFace);
54 
55  // Lilypad should not replace non air and non water blocks:
56  if (
57  const auto BlockToReplace = a_World->GetBlock(PlacePos);
58  (BlockToReplace != E_BLOCK_AIR) &&
59  (BlockToReplace != E_BLOCK_WATER) &&
60  (BlockToReplace != E_BLOCK_STATIONARY_WATER)
61  )
62  {
63  return false;
64  }
65 
66  const auto Below = PlacePos.addedY(-1);
67  if (Below.y < 0)
68  {
69  return false;
70  }
71 
72  // Lilypad should be placed only if there is a water block below:
73  if (
74  const auto BlockBelow = a_World->GetBlock(Below);
75  (BlockBelow != E_BLOCK_WATER) &&
76  (BlockBelow != E_BLOCK_STATIONARY_WATER)
77  )
78  {
79  return false;
80  }
81 
82  a_World->SetBlock(PlacePos, E_BLOCK_LILY_PAD, 0);
83  if (!a_Player->IsGameModeCreative())
84  {
85  a_Player->GetInventory().RemoveOneEquippedItem();
86  }
87 
88  return true;
89  }
90 
91  class cCallbacks:
92  public cBlockTracer::cCallbacks
93  {
94  public:
95 
96  virtual bool OnNextBlock(Vector3i a_CBBlockPos, BLOCKTYPE a_CBBlockType, NIBBLETYPE a_CBBlockMeta, eBlockFace a_CBEntryFace) override
97  {
98  if (
99  !IsBlockWater(a_CBBlockType) ||
100  (a_CBBlockMeta != 0) // The hit block should be a source
101  )
102  {
103  // TODO: Vanilla stops the trace. However, we need to continue the trace, to work around our lack of block bounding box support
104  // which would otherwise mean we misbehave when clicking through the voxel a (e.g.) button occupies. Now, however, we misbehave
105  // when clicking on a block near water... Nonetheless, the former would cause ghost blocks, so continue for now.
106 
107  // Ignore and continue trace:
108  return false;
109  }
110 
111  Position = AddFaceDirection(a_CBBlockPos, BLOCK_FACE_YP); // Always place pad at top of water block
112  return true;
113  }
114 
115  Vector3i Position;
116 
117  } Callbacks;
118 
119  const auto EyePosition = a_Player->GetEyePosition();
120  const auto End = EyePosition + a_Player->GetLookVector() * 5;
121  if (cLineBlockTracer::Trace(*a_Player->GetWorld(), Callbacks, EyePosition, End))
122  {
123  // The line traced to completion; no suitable water was found:
124  return false;
125  }
126 
127  const auto BlockToReplace = a_World->GetBlock(Callbacks.Position);
128  if (BlockToReplace != E_BLOCK_AIR)
129  {
130  // Lilypad should not replace non air blocks:
131  return false;
132  }
133 
134  a_World->SetBlock(Callbacks.Position, E_BLOCK_LILY_PAD, 0);
135  if (!a_Player->IsGameModeCreative())
136  {
137  a_Player->GetInventory().RemoveOneEquippedItem();
138  }
139 
140  return true;
141  }
142 };
bool IsBlockWater(BLOCKTYPE a_BlockType)
Definition: BlockInfo.cpp:10
@ E_BLOCK_WATER
Definition: BlockType.h:18
@ E_BLOCK_AIR
Definition: BlockType.h:10
@ E_BLOCK_LILY_PAD
Definition: BlockType.h:126
@ E_BLOCK_STATIONARY_WATER
Definition: BlockType.h:19
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_YP
Definition: Defines.h:43
@ BLOCK_FACE_NONE
Definition: Defines.h:39
This interface is used to decouple block handlers from the cPluginManager dependency through cWorld.
Vector3d GetLookVector(void) const
Definition: Entity.cpp:2267
cWorld * GetWorld(void) const
Definition: Entity.h:190
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
cInventory & GetInventory(void)
Definition: Player.h:156
Vector3d GetEyePosition(void) const
Definition: Player.cpp:1001
bool RemoveOneEquippedItem(void)
Removes one item out of the currently equipped item stack, returns true if successful,...
Definition: Inventory.cpp:232
Definition: Item.h:37
constexpr cItemHandler(int a_ItemType)
Definition: ItemHandler.h:37
constexpr cItemLilypadHandler(int a_ItemType)
Definition: ItemLilypad.h:19
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: ItemLilypad.h:38
virtual bool IsPlaceable(void) const override
Blocks simply get placed.
Definition: ItemLilypad.h:29
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...
Definition: World.h:53
BLOCKTYPE GetBlock(Vector3i a_BlockPos) const
Returns the block type at the specified position.
Definition: World.h:363
void SetBlock(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
Sets the block at the specified coords to the specified value.
Definition: World.cpp:1743