Cuberite
A lightweight, fast and extensible game server for Minecraft
BlockFence.h
Go to the documentation of this file.
1 
2 #pragma once
3 
4 #include "BlockHandler.h"
5 #include "../BoundingBox.h"
6 #include "../EffectID.h"
7 #include "../Entities/LeashKnot.h"
8 #include "../BoundingBox.h"
9 #include "../Mobs/PassiveMonster.h"
10 
11 
12 
13 class cBlockFenceHandler final :
14  public cBlockHandler
15 {
17 
18 public:
19 
20  using Super::Super;
21 
22 private:
23 
24  // These are the min and max coordinates (X and Z) for a straight fence.
25  // 0.4 and 0.6 are really just guesses, but they seem pretty good.
26  // (0.4 to 0.6 is a fence that's 0.2 wide, down the center of the block)
27  static constexpr double MIN_COORD = 0.4;
28  static constexpr double MAX_COORD = 0.6;
29 
30  virtual cBoundingBox GetPlacementCollisionBox(BLOCKTYPE a_XM, BLOCKTYPE a_XP, BLOCKTYPE a_YM, BLOCKTYPE a_YP, BLOCKTYPE a_ZM, BLOCKTYPE a_ZP) const override
31  {
32  bool XMSolid = cBlockInfo::IsSolid(a_XM);
33  bool XPSolid = cBlockInfo::IsSolid(a_XP);
34  bool ZMSolid = cBlockInfo::IsSolid(a_ZM);
35  bool ZPSolid = cBlockInfo::IsSolid(a_ZP);
36 
37  double FENCE_HEIGHT = cBlockInfo::GetBlockHeight(m_BlockType);
38 
39  // Entities can never be in the center
40  cBoundingBox PlacementBox(MIN_COORD, MAX_COORD, 0, FENCE_HEIGHT, MIN_COORD, MAX_COORD);
41 
42  // For each solid neighbor, the hitbox extends that way
43  if (XMSolid)
44  {
45  PlacementBox = PlacementBox.Union(cBoundingBox(0, 0.5, 0, FENCE_HEIGHT, MIN_COORD, MAX_COORD));
46  }
47  if (XPSolid)
48  {
49  PlacementBox = PlacementBox.Union(cBoundingBox(0.5, 1.0, 0, FENCE_HEIGHT, MIN_COORD, MAX_COORD));
50  }
51  if (ZMSolid)
52  {
53  PlacementBox = PlacementBox.Union(cBoundingBox(MIN_COORD, MAX_COORD, 0, FENCE_HEIGHT, 0.0, 0.5));
54  }
55  if (ZPSolid)
56  {
57  PlacementBox = PlacementBox.Union(cBoundingBox(MIN_COORD, MAX_COORD, 0, FENCE_HEIGHT, 0.5, 1.0));
58  }
59 
60  // For each corner, fill in the corner
61  if (XMSolid && ZMSolid)
62  {
63  PlacementBox = PlacementBox.Union(cBoundingBox(0, 0.5, 0, FENCE_HEIGHT, 0, 0.5));
64  }
65  if (XPSolid && ZMSolid)
66  {
67  PlacementBox = PlacementBox.Union(cBoundingBox(0.5, 1.0, 0, FENCE_HEIGHT, 0, 0.5));
68  }
69  if (XPSolid && ZPSolid)
70  {
71  PlacementBox = PlacementBox.Union(cBoundingBox(0.5, 1.0, 0, FENCE_HEIGHT, 0.5, 1.0));
72  }
73  if (XMSolid && ZPSolid)
74  {
75  PlacementBox = PlacementBox.Union(cBoundingBox(0, 0.5, 0, FENCE_HEIGHT, 0.5, 1.0));
76  }
77 
78  return PlacementBox;
79  }
80 
81 
82 
83 
84 
85  virtual bool OnUse(
86  cChunkInterface & a_ChunkInterface,
87  cWorldInterface & a_WorldInterface,
88  cPlayer & a_Player,
89  const Vector3i a_BlockPos,
90  eBlockFace a_BlockFace,
91  const Vector3i a_CursorPos
92  ) const override
93  {
94  auto LeashKnot = cLeashKnot::FindKnotAtPos(*a_Player.GetWorld(), a_BlockPos);
95  auto KnotAlreadyExists = (LeashKnot != nullptr);
96 
97  if (KnotAlreadyExists)
98  {
99  // Check leashed nearby mobs to leash them to the knot
100  LeashKnot->TiePlayersLeashedMobs(a_Player, KnotAlreadyExists);
101  }
102  // New knot? needs to init and produce sound effect
103  else
104  {
105  auto NewLeashKnot = std::make_unique<cLeashKnot>(a_BlockFace, a_BlockPos);
106  auto NewLeashKnotPtr = NewLeashKnot.get();
107 
108  NewLeashKnotPtr->TiePlayersLeashedMobs(a_Player, KnotAlreadyExists);
109 
110  // Only put the knot in the world if any mob has been leashed to
111  if (NewLeashKnotPtr->HasAnyMobLeashed())
112  {
113  if (!NewLeashKnotPtr->Initialize(std::move(NewLeashKnot), *a_Player.GetWorld()))
114  {
115  return false;
116  }
117  a_Player.GetWorld()->BroadcastSoundEffect("entity.leashknot.place", a_Player.GetPosition(), 1, 1);
118  }
119  else
120  {
121  return false;
122  }
123  }
124 
125  return true;
126  }
127 
128 
129 
130 
131 
132  virtual void OnCancelRightClick(
133  cChunkInterface & a_ChunkInterface,
134  cWorldInterface & a_WorldInterface,
135  cPlayer & a_Player,
136  const Vector3i a_BlockPos,
137  eBlockFace a_BlockFace
138  ) const override
139  {
140  a_WorldInterface.SendBlockTo(a_BlockPos, a_Player);
141  }
142 
143 
144 
145 
146 
147  virtual bool IsUseable(void) const override
148  {
149  return true;
150  }
151 
152 
153 
154 
155 
156  virtual void OnBroken(
157  cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface,
158  Vector3i a_BlockPos,
159  BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta,
160  const cEntity * a_Digger
161  ) const override
162  {
163  UNUSED(a_Digger);
164  // Destroy any leash knot tied to the fence:
165  auto leashKnot = cLeashKnot::FindKnotAtPos(a_WorldInterface, a_BlockPos);
166  if (leashKnot != nullptr)
167  {
168  leashKnot->SetShouldSelfDestroy();
169  }
170  }
171 };
172 
173 
174 
175 
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
eBlockFace
Block face constants, used in PlayerDigging and PlayerBlockPlacement packets and bbox collision calc.
Definition: Defines.h:38
#define UNUSED
Definition: Globals.h:72
static float GetBlockHeight(BLOCKTYPE Block)
Block's height.
Definition: BlockInfo.cpp:1153
static bool IsSolid(BLOCKTYPE Block)
Is this block solid (player cannot walk through)?
Definition: BlockInfo.cpp:892
virtual void OnBroken(cChunkInterface &a_ChunkInterface, cWorldInterface &a_WorldInterface, Vector3i a_BlockPos, BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta, const cEntity *a_Digger) const override
Called after a block gets broken (replaced with air), by natural means.
Definition: BlockFence.h:156
virtual cBoundingBox GetPlacementCollisionBox(BLOCKTYPE a_XM, BLOCKTYPE a_XP, BLOCKTYPE a_YM, BLOCKTYPE a_YP, BLOCKTYPE a_ZM, BLOCKTYPE a_ZP) const override
Returns the relative bounding box that must be entity-free in order for the block to be placed.
Definition: BlockFence.h:30
static constexpr double MAX_COORD
Definition: BlockFence.h:28
virtual void OnCancelRightClick(cChunkInterface &a_ChunkInterface, cWorldInterface &a_WorldInterface, cPlayer &a_Player, const Vector3i a_BlockPos, eBlockFace a_BlockFace) const override
Called when a right click to this block is cancelled.
Definition: BlockFence.h:132
static constexpr double MIN_COORD
Definition: BlockFence.h:27
virtual bool OnUse(cChunkInterface &a_ChunkInterface, cWorldInterface &a_WorldInterface, cPlayer &a_Player, const Vector3i a_BlockPos, eBlockFace a_BlockFace, const Vector3i a_CursorPos) const override
Called when the user right clicks the block and the block is useable.
Definition: BlockFence.h:85
virtual bool IsUseable(void) const override
Called to check whether this block supports a rclk action.
Definition: BlockFence.h:147
constexpr cBlockHandler(BLOCKTYPE a_BlockType)
Definition: BlockHandler.h:29
const BLOCKTYPE m_BlockType
Definition: BlockHandler.h:205
virtual void SendBlockTo(int a_BlockX, int a_BlockY, int a_BlockZ, const cPlayer &a_Player)=0
Sends the block on those coords to the player.
Represents two sets of coords, minimum and maximum for each direction.
Definition: BoundingBox.h:24
cBoundingBox Union(const cBoundingBox &a_Other)
Returns the union of the two bounding boxes.
Definition: Entity.h:76
const Vector3d & GetPosition(void) const
Exported in ManualBindings.
Definition: Entity.h:297
cWorld * GetWorld(void) const
Definition: Entity.h:190
static cLeashKnot * FindKnotAtPos(cWorldInterface &a_WorldInterface, Vector3i a_BlockPos)
Returns the leash knot entity representing the knot at the specified position.
Definition: LeashKnot.cpp:142
Definition: Player.h:29
virtual void BroadcastSoundEffect(const AString &a_SoundName, Vector3d a_Position, float a_Volume, float a_Pitch, const cClientHandle *a_Exclude=nullptr) override