Cuberite
A lightweight, fast and extensible game server for Minecraft
DropSpenserEntity.cpp
Go to the documentation of this file.
1 
2 // DropSpenserEntity.cpp
3 
4 // Declares the cDropSpenserEntity class representing a common ancestor to the cDispenserEntity and cDropperEntity
5 // The dropper and dispenser only needs to override the DropSpenseFromSlot() function to provide the specific item behavior
6 
7 #include "Globals.h"
8 #include "DropSpenserEntity.h"
9 #include "../EffectID.h"
10 #include "../Entities/Player.h"
11 #include "../Chunk.h"
12 #include "../UI/DropSpenserWindow.h"
13 
14 
15 
16 
17 
18 cDropSpenserEntity::cDropSpenserEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World):
19  super(a_BlockType, a_BlockMeta, a_Pos, ContentsWidth, ContentsHeight, a_World),
20  m_ShouldDropSpense(false)
21 {
22 }
23 
24 
25 
26 
27 
29 {
30  // Tell window its owner is destroyed
31  cWindow * Window = GetWindow();
32  if (Window != nullptr)
33  {
34  Window->OwnerDestroyed();
35  }
36 }
37 
38 
39 
40 
41 
43 {
44  switch (a_Direction & E_META_DROPSPENSER_FACING_MASK)
45  {
46  case E_META_DROPSPENSER_FACING_YM: a_RelCoord.y--; return;
47  case E_META_DROPSPENSER_FACING_YP: a_RelCoord.y++; return;
48  case E_META_DROPSPENSER_FACING_ZM: a_RelCoord.z--; return;
49  case E_META_DROPSPENSER_FACING_ZP: a_RelCoord.z++; return;
50  case E_META_DROPSPENSER_FACING_XM: a_RelCoord.x--; return;
51  case E_META_DROPSPENSER_FACING_XP: a_RelCoord.x++; return;
52  }
53  LOGWARNING("%s: Unhandled direction: %d", __FUNCTION__, a_Direction);
54  return;
55 }
56 
57 
58 
59 
60 
62 {
63  // Pick one of the occupied slots:
64  int OccupiedSlots[9];
65  int SlotsCnt = 0;
66  for (int i = m_Contents.GetNumSlots() - 1; i >= 0; i--)
67  {
68  if (!m_Contents.GetSlot(i).IsEmpty())
69  {
70  OccupiedSlots[SlotsCnt] = i;
71  SlotsCnt++;
72  }
73  } // for i - m_Contents[]
74 
75  if (SlotsCnt == 0)
76  {
77  // Nothing in the dropspenser, play the click sound
78  m_World->BroadcastSoundEffect("block.dispenser.fail", m_Pos, 1.0f, 1.2f);
79  return;
80  }
81 
82  int RandomSlot = m_World->GetTickRandomNumber(SlotsCnt - 1);
83 
84  // DropSpense the item, using the specialized behavior in the subclasses:
85  DropSpenseFromSlot(a_Chunk, OccupiedSlots[RandomSlot]);
86 
87  // Broadcast a smoke and click effects:
88  NIBBLETYPE Meta = a_Chunk.GetMeta(GetRelPos());
89  int SmokeDir = 0;
90  switch (Meta & E_META_DROPSPENSER_FACING_MASK)
91  {
92  case E_META_DROPSPENSER_FACING_YP: SmokeDir = static_cast<int>(SmokeDirection::CENTRE); break; // YP & YM don't have associated smoke dirs, just do 4 (centre of block)
93  case E_META_DROPSPENSER_FACING_YM: SmokeDir = static_cast<int>(SmokeDirection::CENTRE); break;
94  case E_META_DROPSPENSER_FACING_XM: SmokeDir = static_cast<int>(SmokeDirection::EAST); break;
95  case E_META_DROPSPENSER_FACING_XP: SmokeDir = static_cast<int>(SmokeDirection::WEST); break;
96  case E_META_DROPSPENSER_FACING_ZM: SmokeDir = static_cast<int>(SmokeDirection::SOUTH); break;
97  case E_META_DROPSPENSER_FACING_ZP: SmokeDir = static_cast<int>(SmokeDirection::NORTH); break;
98  }
100  m_World->BroadcastSoundEffect("block.dispenser.dispense", m_Pos, 1.0f, 1.0f);
101 }
102 
103 
104 
105 
106 
108 {
109  m_ShouldDropSpense = true;
110 }
111 
112 
113 
114 
115 
117 {
118  super::CopyFrom(a_Src);
119  auto & src = static_cast<const cDropSpenserEntity &>(a_Src);
120  m_Contents.CopyFrom(src.m_Contents);
121  m_ShouldDropSpense = src.m_ShouldDropSpense;
122 }
123 
124 
125 
126 
127 
128 bool cDropSpenserEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
129 {
130  UNUSED(a_Dt);
131  if (!m_ShouldDropSpense)
132  {
133  return false;
134  }
135 
136  m_ShouldDropSpense = false;
137  DropSpense(a_Chunk);
138  return true;
139 }
140 
141 
142 
143 
144 
146 {
147  // Nothing needs to be sent
148  UNUSED(a_Client);
149 }
150 
151 
152 
153 
154 
156 {
157  cWindow * Window = GetWindow();
158  if (Window == nullptr)
159  {
160  OpenWindow(new cDropSpenserWindow(this));
161  Window = GetWindow();
162  }
163 
164  if (Window != nullptr)
165  {
166  if (a_Player->GetWindow() != Window)
167  {
168  a_Player->OpenWindow(*Window);
169  }
170  }
171  return true;
172 }
173 
174 
175 
176 
177 
178 void cDropSpenserEntity::DropFromSlot(cChunk & a_Chunk, int a_SlotNum)
179 {
180  Vector3i dispCoord(m_Pos);
181  auto Meta = a_Chunk.GetMeta(GetRelPos());
182  AddDropSpenserDir(dispCoord, Meta);
183 
184  cItems Pickups;
185  Pickups.push_back(m_Contents.RemoveOneItem(a_SlotNum));
186 
187  const int PickupSpeed = GetRandomProvider().RandInt(2, 6); // At least 2, at most 6
188  int PickupSpeedX = 0, PickupSpeedY = 0, PickupSpeedZ = 0;
189  switch (Meta & E_META_DROPSPENSER_FACING_MASK)
190  {
191  case E_META_DROPSPENSER_FACING_YP: PickupSpeedY = PickupSpeed; break;
192  case E_META_DROPSPENSER_FACING_YM: PickupSpeedY = -PickupSpeed; break;
193  case E_META_DROPSPENSER_FACING_XM: PickupSpeedX = -PickupSpeed; break;
194  case E_META_DROPSPENSER_FACING_XP: PickupSpeedX = PickupSpeed; break;
195  case E_META_DROPSPENSER_FACING_ZM: PickupSpeedZ = -PickupSpeed; break;
196  case E_META_DROPSPENSER_FACING_ZP: PickupSpeedZ = PickupSpeed; break;
197  }
198 
199  double MicroX, MicroY, MicroZ;
200  MicroX = dispCoord.x + 0.5;
201  MicroY = dispCoord.y + 0.4; // Slightly less than half, to accomodate actual texture hole on DropSpenser
202  MicroZ = dispCoord.z + 0.5;
203 
204 
205  m_World->SpawnItemPickups(Pickups, MicroX, MicroY, MicroZ, PickupSpeedX, PickupSpeedY, PickupSpeedZ);
206 }
207 
208 
209 
210 
void AddDropSpenserDir(Vector3i &a_RelCoord, NIBBLETYPE a_Direction)
Modifies the block coords to match the dropspenser direction given (where the dropspensed pickups sho...
T x
Definition: Vector3.h:17
void CopyFrom(const cItemGrid &a_Src)
Copies all items from a_Src to this grid.
Definition: ItemGrid.cpp:83
unsigned char BLOCKTYPE
The datatype used by blockdata.
Definition: ChunkDef.h:42
MTRand & GetRandomProvider()
Returns the current thread&#39;s random number source.
Definition: FastRandom.cpp:20
virtual void DropSpenseFromSlot(cChunk &a_Chunk, int a_SlotNum)=0
Override this function to provide the specific behavior for item dropspensing (drop / shoot / pour / ...
cWindow * GetWindow(void)
Definition: Player.h:239
Definition: Player.h:27
virtual void CopyFrom(const cBlockEntity &a_Src) override
Copies all properties of a_Src into this entity, except for its m_World and location.
bool IsEmpty(void) const
Definition: Item.h:116
void OpenWindow(cWindow *a_Window)
Definition: WindowOwner.h:34
void OwnerDestroyed(void)
Definition: Window.cpp:352
void DropSpense(cChunk &a_Chunk)
Does the actual work on dropspensing an item.
void DropFromSlot(cChunk &a_Chunk, int a_SlotNum)
Helper function, drops one item from the specified slot (like a dropper)
cItem RemoveOneItem(int a_SlotNum)
Removes one item from the stack in the specified slot, and returns it.
Definition: ItemGrid.cpp:492
unsigned char NIBBLETYPE
The datatype used by nibbledata (meta, light, skylight)
Definition: ChunkDef.h:45
Definition: Chunk.h:49
void SpawnItemPickups(const cItems &a_Pickups, Vector3i a_BlockPos, double a_FlyAwaySpeed=1.0, bool a_IsPlayerCreated=false)
Spawns item pickups for each item in the list.
Definition: World.cpp:1936
T y
Definition: Vector3.h:17
cWorld * m_World
Definition: BlockEntity.h:155
T z
Definition: Vector3.h:17
virtual void BroadcastSoundEffect(const AString &a_SoundName, Vector3d a_Position, float a_Volume, float a_Pitch, const cClientHandle *a_Exclude=nullptr) override
int GetTickRandomNumber(int a_Range)
Returns a random number in range [0 .
Definition: World.cpp:3271
cWindow * GetWindow(void) const
Definition: WindowOwner.h:40
virtual bool UsedBy(cPlayer *a_Player) override
Called when a player uses this entity; should open the UI window.
IntType RandInt(IntType a_Min, IntType a_Max)
Return a random IntType in the range [a_Min, a_Max].
Definition: FastRandom.h:78
Vector3i GetPos() const
Definition: BlockEntity.h:104
Vector3i GetRelPos() const
Definition: BlockEntity.h:109
virtual void BroadcastSoundParticleEffect(const EffectID a_EffectID, Vector3i a_SrcPos, int a_Data, const cClientHandle *a_Exclude=nullptr) override
Definition: World.h:65
NIBBLETYPE GetMeta(int a_RelX, int a_RelY, int a_RelZ) const
Definition: Chunk.h:380
virtual void SendTo(cClientHandle &a_Client) override
Sends the packet defining the block entity to the client specified.
void Activate(void)
Sets the dropspenser to dropspense an item in the next tick.
void LOGWARNING(const char *a_Format, fmt::ArgList a_ArgList)
Definition: Logger.cpp:174
Vector3i m_Pos
Position in absolute block coordinates.
Definition: BlockEntity.h:142
bool m_ShouldDropSpense
If true, the dropspenser will dropspense an item in the next tick.
#define UNUSED
Definition: Globals.h:152
virtual void CopyFrom(const cBlockEntity &a_Src) override
Copies all properties of a_Src into this entity, except for its m_World and location.
Represents a UI window.
Definition: Window.h:53
virtual bool Tick(std::chrono::milliseconds a_Dt, cChunk &a_Chunk) override
Ticks the entity; returns true if the chunk should be marked as dirty as a result of this ticking...
const cItem & GetSlot(int a_X, int a_Y) const
Definition: ItemGrid.cpp:96
int GetNumSlots(void) const
Definition: ItemGrid.h:40
void OpenWindow(cWindow &a_Window)
Opens the specified window; closes the current one first using CloseWindow()
Definition: Player.cpp:1349
This class bridges a vector of cItem for safe access via Lua.
Definition: Item.h:234
cDropSpenserEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld *a_World)
virtual ~cDropSpenserEntity() override