Cuberite
A lightweight, fast and extensible game server for Minecraft
ItemChest.h
Go to the documentation of this file.
1 
2 #pragma once
3 
4 #include "ItemHandler.h"
5 #include "../Blocks/BlockChest.h"
6 
7 
8 
9 
10 
12  public cItemHandler
13 {
15 public:
16  cItemChestHandler(int a_ItemType):
17  super(a_ItemType)
18  {
19  }
20 
21 
24  virtual bool OnPlayerPlace(
25  cWorld & a_World, cPlayer & a_Player, const cItem & a_EquippedItem,
26  int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
27  int a_CursorX, int a_CursorY, int a_CursorZ
28  ) override
29  {
30  if (a_BlockFace < 0)
31  {
32  // Clicked in air
33  return false;
34  }
35 
36  if ((a_BlockY < 0) || (a_BlockY >= cChunkDef::Height))
37  {
38  // The clicked block is outside the world, ignore this call altogether (#128)
39  return false;
40  }
41 
42  // Check if the block ignores build collision (water, grass etc.):
43  BLOCKTYPE clickedBlock;
44  NIBBLETYPE clickedBlockMeta;
45  Vector3i blockPos(a_BlockX, a_BlockY, a_BlockZ);
46  a_World.GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, clickedBlock, clickedBlockMeta);
47  cChunkInterface ChunkInterface(a_World.GetChunkMap());
48  auto blockHandler = BlockHandler(clickedBlock);
49  if (blockHandler->DoesIgnoreBuildCollision(ChunkInterface, blockPos, a_Player, clickedBlockMeta))
50  {
51  blockHandler->OnPlayerBreakingBlock(ChunkInterface, a_World, a_Player, blockPos);
52  }
53  else
54  {
55  AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace);
56 
57  if ((a_BlockY < 0) || (a_BlockY >= cChunkDef::Height))
58  {
59  // The block is being placed outside the world, ignore this packet altogether (#128)
60  return false;
61  }
62 
63  NIBBLETYPE PlaceMeta;
64  BLOCKTYPE PlaceBlock;
65  a_World.GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, PlaceBlock, PlaceMeta);
66 
67  // Clicked on side of block, make sure that placement won't be cancelled if there is a slab able to be double slabbed.
68  // No need to do combinability (dblslab) checks, client will do that here.
69  if (blockHandler->DoesIgnoreBuildCollision(ChunkInterface, blockPos, a_Player, clickedBlockMeta))
70  {
71  // Tried to place a block into another?
72  // Happens when you place a block aiming at side of block with a torch on it or stem beside it
73  return false;
74  }
75  }
76 
77  // Check that there is at most one single neighbor of the same chest type:
78  static const Vector3i CrossCoords[] =
79  {
80  {-1, 0, 0},
81  { 0, 0, -1},
82  { 1, 0, 0},
83  { 0, 0, 1},
84  };
85  int NeighborIdx = -1;
86  for (size_t i = 0; i < ARRAYCOUNT(CrossCoords); i++)
87  {
88  if (a_World.GetBlock(a_BlockX + CrossCoords[i].x, a_BlockY, a_BlockZ + CrossCoords[i].z) != m_ItemType)
89  {
90  continue;
91  }
92  if (NeighborIdx >= 0)
93  {
94  // Can't place here, there are already two neighbors, this would form a 3-block chest
95  return false;
96  }
97  NeighborIdx = static_cast<int>(i);
98 
99  // Check that this neighbor is a single chest:
100  int bx = a_BlockX + CrossCoords[i].x;
101  int bz = a_BlockZ + CrossCoords[i].z;
102  for (size_t j = 0; j < ARRAYCOUNT(CrossCoords); j++)
103  {
104  if (a_World.GetBlock(bx + CrossCoords[j].x, a_BlockY, bz + CrossCoords[j].z) == m_ItemType)
105  {
106  return false;
107  }
108  } // for j
109  } // for i
110 
111  // Get the meta of the placed chest; take existing neighbors into account:
112  BLOCKTYPE ChestBlockType = static_cast<BLOCKTYPE>(m_ItemType);
113  NIBBLETYPE Meta;
114  auto yaw = a_Player.GetYaw();
115  switch (NeighborIdx)
116  {
117  case 0:
118  case 2:
119  {
120  // The neighbor is in the X axis, form a X-axis-aligned dblchest:
121  Meta = ((yaw >= -90) && (yaw < 90)) ? E_META_CHEST_FACING_ZM : E_META_CHEST_FACING_ZP;
122  break;
123  }
124  case 1:
125  case 3:
126  {
127  // The neighbor is in the Z axis, form a Z-axis-aligned dblchest:
128  Meta = (yaw < 0) ? E_META_CHEST_FACING_XM : E_META_CHEST_FACING_XP;
129  break;
130  }
131  default:
132  {
134  break;
135  }
136  } // switch (NeighborIdx)
137 
138  // Place the new chest:
139  if (!a_Player.PlaceBlock(a_BlockX, a_BlockY, a_BlockZ, ChestBlockType, Meta))
140  {
141  return false;
142  }
143 
144  // Adjust the existing chest, if any:
145  if (NeighborIdx != -1)
146  {
147  a_World.FastSetBlock(a_BlockX + CrossCoords[NeighborIdx].x, a_BlockY, a_BlockZ + CrossCoords[NeighborIdx].z, ChestBlockType, Meta);
148  }
149 
150  // Remove the "placed" item:
151  if (a_Player.IsGameModeSurvival())
152  {
153  a_Player.GetInventory().RemoveOneEquippedItem();
154  }
155  return true;
156  }
157 
158 private:
159  cItemChestHandler(const cItemChestHandler &) = delete;
160 };
static NIBBLETYPE PlayerYawToMetaData(double a_Yaw)
Translates player yaw when placing a chest into the chest block metadata.
Definition: BlockChest.h:160
BLOCKTYPE GetBlock(Vector3i a_BlockPos)
Returns the block type at the specified position.
Definition: World.h:416
T x
Definition: Vector3.h:17
unsigned char BLOCKTYPE
The datatype used by blockdata.
Definition: ChunkDef.h:42
bool RemoveOneEquippedItem(void)
Removes one item out of the currently equipped item stack, returns true if successful, false if empty-handed.
Definition: Inventory.cpp:207
Definition: Player.h:27
unsigned char NIBBLETYPE
The datatype used by nibbledata (meta, light, skylight)
Definition: ChunkDef.h:45
bool PlaceBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
Calls the block-placement hook and places the block in the world, unless refused by the hook...
Definition: Player.cpp:2671
T z
Definition: Vector3.h:17
static const int Height
Definition: ChunkDef.h:135
virtual bool OnPlayerPlace(cWorld &a_World, cPlayer &a_Player, const cItem &a_EquippedItem, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override
We need an OnPlayerPlace override because we&#39;re processing neighbor chests and changing their metas...
Definition: ItemChest.h:24
void AddFaceDirection(int &a_BlockX, int &a_BlockY, int &a_BlockZ, eBlockFace a_BlockFace, bool a_bInverse=false)
Definition: Defines.h:859
bool GetBlockTypeMeta(Vector3i a_BlockPos, BLOCKTYPE &a_BlockType, NIBBLETYPE &a_BlockMeta)
Retrieves the block type and meta at the specified coords.
Definition: World.cpp:1909
Definition: World.h:65
cItemChestHandler(int a_ItemType)
Definition: ItemChest.h:16
cBlockHandler * BlockHandler(BLOCKTYPE a_BlockType)
Definition: BlockInfo.h:159
cItemHandler super
Definition: ItemChest.h:14
double GetYaw(void) const
Definition: Entity.h:209
cChunkMap * GetChunkMap(void)
Definition: World.h:1044
eBlockFace
Block face constants, used in PlayerDigging and PlayerBlockPlacement packets and bbox collision calc...
Definition: Defines.h:29
bool IsGameModeSurvival(void) const
Returns true if the player is in Survival mode, either explicitly, or by inheriting from current worl...
Definition: Player.cpp:1269
void FastSetBlock(Vector3i a_BlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
Sets the block at the specified coords to the specified value.
Definition: World.h:400
cInventory & GetInventory(void)
Definition: Player.h:136
#define ARRAYCOUNT(X)
Evaluates to the number of elements in an array (compile-time!)
Definition: Globals.h:290
Definition: Item.h:36