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 "../Bindings/PluginManager.h"
10 #include "../EffectID.h"
11 #include "../Entities/Player.h"
12 #include "../Chunk.h"
13 #include "../UI/DropSpenserWindow.h"
14 
15 
16 
17 
18 
19 cDropSpenserEntity::cDropSpenserEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World):
20  Super(a_BlockType, a_BlockMeta, a_Pos, ContentsWidth, ContentsHeight, a_World),
21  m_ShouldDropSpense(false)
22 {
23 }
24 
25 
26 
27 
28 
30 {
31  switch (a_Direction & E_META_DROPSPENSER_FACING_MASK)
32  {
33  case E_META_DROPSPENSER_FACING_YM: a_RelCoord.y--; return;
34  case E_META_DROPSPENSER_FACING_YP: a_RelCoord.y++; return;
35  case E_META_DROPSPENSER_FACING_ZM: a_RelCoord.z--; return;
36  case E_META_DROPSPENSER_FACING_ZP: a_RelCoord.z++; return;
37  case E_META_DROPSPENSER_FACING_XM: a_RelCoord.x--; return;
38  case E_META_DROPSPENSER_FACING_XP: a_RelCoord.x++; return;
39  }
40  LOGWARNING("%s: Unhandled direction: %d", __FUNCTION__, a_Direction);
41 }
42 
43 
44 
45 
46 
48 {
49  // Pick one of the occupied slots:
50  std::array<int, 9> OccupiedSlots;
51  size_t SlotsCnt = 0;
52  for (int i = m_Contents.GetNumSlots() - 1; i >= 0; i--)
53  {
54  if (!m_Contents.GetSlot(i).IsEmpty())
55  {
56  OccupiedSlots[SlotsCnt] = i;
57  SlotsCnt++;
58  }
59  } // for i - m_Contents[]
60 
61  if (SlotsCnt == 0)
62  {
63  // Nothing in the dropspenser, play the click sound
64  m_World->BroadcastSoundEffect("block.dispenser.fail", m_Pos, 1.0f, 1.2f);
65  return;
66  }
67 
68  const size_t RandomSlot = GetRandomProvider().RandInt(SlotsCnt - 1);
69  const int SpenseSlot = OccupiedSlots[RandomSlot];
70 
71  if (cPluginManager::Get()->CallHookDropSpense(*m_World, *this, SpenseSlot))
72  {
73  // Plugin disagrees with the move
74  return;
75  }
76 
77  // DropSpense the item, using the specialized behavior in the subclasses:
78  DropSpenseFromSlot(a_Chunk, SpenseSlot);
79 
80  // Broadcast a smoke and click effects:
81  NIBBLETYPE Meta = a_Chunk.GetMeta(GetRelPos());
82  int SmokeDir = 0;
83  switch (Meta & E_META_DROPSPENSER_FACING_MASK)
84  {
85  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)
86  case E_META_DROPSPENSER_FACING_YM: SmokeDir = static_cast<int>(SmokeDirection::CENTRE); break;
87  case E_META_DROPSPENSER_FACING_XM: SmokeDir = static_cast<int>(SmokeDirection::EAST); break;
88  case E_META_DROPSPENSER_FACING_XP: SmokeDir = static_cast<int>(SmokeDirection::WEST); break;
89  case E_META_DROPSPENSER_FACING_ZM: SmokeDir = static_cast<int>(SmokeDirection::SOUTH); break;
90  case E_META_DROPSPENSER_FACING_ZP: SmokeDir = static_cast<int>(SmokeDirection::NORTH); break;
91  }
93  m_World->BroadcastSoundEffect("block.dispenser.dispense", m_Pos, 1.0f, 1.0f);
94 }
95 
96 
97 
98 
99 
101 {
102  m_ShouldDropSpense = true;
103 }
104 
105 
106 
107 
108 
110 {
111  Super::CopyFrom(a_Src);
112  auto & src = static_cast<const cDropSpenserEntity &>(a_Src);
113  m_Contents.CopyFrom(src.m_Contents);
114  m_ShouldDropSpense = src.m_ShouldDropSpense;
115 }
116 
117 
118 
119 
120 
122 {
123  const auto Window = GetWindow();
124  if (Window != nullptr)
125  {
126  // Tell window its owner is destroyed:
127  Window->OwnerDestroyed();
128  }
129 }
130 
131 
132 
133 
134 
135 bool cDropSpenserEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
136 {
137  UNUSED(a_Dt);
138  if (!m_ShouldDropSpense)
139  {
140  return false;
141  }
142 
143  m_ShouldDropSpense = false;
144  DropSpense(a_Chunk);
145  return true;
146 }
147 
148 
149 
150 
151 
153 {
154  // Nothing needs to be sent
155  UNUSED(a_Client);
156 }
157 
158 
159 
160 
161 
163 {
165  {
167  }
168  else // E_BLOCK_DROPPER
169  {
171  }
172 
173  cWindow * Window = GetWindow();
174  if (Window == nullptr)
175  {
176  OpenWindow(new cDropSpenserWindow(this));
177  Window = GetWindow();
178  }
179 
180  if (Window != nullptr)
181  {
182  if (a_Player->GetWindow() != Window)
183  {
184  a_Player->OpenWindow(*Window);
185  }
186  }
187  return true;
188 }
189 
190 
191 
192 
193 
194 void cDropSpenserEntity::DropFromSlot(cChunk & a_Chunk, int a_SlotNum)
195 {
196  Vector3i dispCoord(m_Pos);
197  auto Meta = a_Chunk.GetMeta(GetRelPos());
198  AddDropSpenserDir(dispCoord, Meta);
199 
200  cItems Pickups;
201  Pickups.push_back(m_Contents.RemoveOneItem(a_SlotNum));
202 
203  const int PickupSpeed = GetRandomProvider().RandInt(2, 6); // At least 2, at most 6
204  int PickupSpeedX = 0, PickupSpeedY = 0, PickupSpeedZ = 0;
205  switch (Meta & E_META_DROPSPENSER_FACING_MASK)
206  {
207  case E_META_DROPSPENSER_FACING_YP: PickupSpeedY = PickupSpeed; break;
208  case E_META_DROPSPENSER_FACING_YM: PickupSpeedY = -PickupSpeed; break;
209  case E_META_DROPSPENSER_FACING_XM: PickupSpeedX = -PickupSpeed; break;
210  case E_META_DROPSPENSER_FACING_XP: PickupSpeedX = PickupSpeed; break;
211  case E_META_DROPSPENSER_FACING_ZM: PickupSpeedZ = -PickupSpeed; break;
212  case E_META_DROPSPENSER_FACING_ZP: PickupSpeedZ = PickupSpeed; break;
213  }
214 
215  double MicroX, MicroY, MicroZ;
216  MicroX = dispCoord.x + 0.5;
217  MicroY = dispCoord.y + 0.4; // Slightly less than half, to accomodate actual texture hole on DropSpenser
218  MicroZ = dispCoord.z + 0.5;
219 
220 
221  m_World->SpawnItemPickups(Pickups, MicroX, MicroY, MicroZ, PickupSpeedX, PickupSpeedY, PickupSpeedZ);
222 }
223 
224 
225 
226 
@ E_META_DROPSPENSER_FACING_ZM
Definition: BlockType.h:647
@ E_META_DROPSPENSER_FACING_XM
Definition: BlockType.h:649
@ E_META_DROPSPENSER_FACING_YP
Definition: BlockType.h:646
@ E_META_DROPSPENSER_FACING_YM
Definition: BlockType.h:645
@ E_META_DROPSPENSER_FACING_ZP
Definition: BlockType.h:648
@ E_META_DROPSPENSER_FACING_XP
Definition: BlockType.h:650
@ E_META_DROPSPENSER_FACING_MASK
Definition: BlockType.h:651
@ E_BLOCK_DISPENSER
Definition: BlockType.h:33
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
@ PARTICLE_SMOKE
MTRand & GetRandomProvider()
Returns the current thread's random number source.
Definition: FastRandom.cpp:12
#define UNUSED
Definition: Globals.h:72
void LOGWARNING(std::string_view a_Format, const Args &... args)
Definition: LoggerSimple.h:67
static cPluginManager * Get(void)
Returns the instance of the Plugin Manager (there is only ever one)
BLOCKTYPE m_BlockType
The blocktype representing this particular instance in the world.
Definition: BlockEntity.h:120
Vector3i GetPos() const
Definition: BlockEntity.h:90
Vector3i GetRelPos() const
Definition: BlockEntity.h:95
Vector3i m_Pos
Position in absolute block coordinates.
Definition: BlockEntity.h:113
cWorld * m_World
Definition: BlockEntity.h:126
virtual void CopyFrom(const cBlockEntity &a_Src) override
Copies all properties of a_Src into this entity, except for its m_World and location.
virtual void DropSpenseFromSlot(cChunk &a_Chunk, int a_SlotNum)=0
Override this function to provide the specific behavior for item dropspensing (drop / shoot / pour / ...
virtual bool UsedBy(cPlayer *a_Player) override
Called when a player uses this entity; should open the UI window.
void DropFromSlot(cChunk &a_Chunk, int a_SlotNum)
Helper function, drops one item from the specified slot (like a dropper)
void DropSpense(cChunk &a_Chunk)
Does the actual work on dropspensing an item.
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.
cDropSpenserEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld *a_World)
bool m_ShouldDropSpense
If true, the dropspenser will dropspense an item in the next tick.
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.
virtual void CopyFrom(const cBlockEntity &a_Src) override
Copies all properties of a_Src into this entity, except for its m_World and location.
virtual void OnRemoveFromWorld() override
Called when the block entity object is removed from a world.
void AddDropSpenserDir(Vector3i &a_RelCoord, NIBBLETYPE a_Direction)
Modifies the block coords to match the dropspenser direction given (where the dropspensed pickups sho...
Definition: Chunk.h:36
NIBBLETYPE GetMeta(int a_RelX, int a_RelY, int a_RelZ) const
Definition: Chunk.h:279
Definition: Player.h:29
StatisticsManager & GetStatistics()
Return the associated statistic and achievement manager.
Definition: Player.h:237
void OpenWindow(cWindow &a_Window)
Opens the specified window; closes the current one first using CloseWindow()
Definition: Player.cpp:1123
cWindow * GetWindow(void)
Definition: Player.h:262
IntType RandInt(IntType a_Min, IntType a_Max)
Return a random IntType in the range [a_Min, a_Max].
Definition: FastRandom.h:78
bool IsEmpty(void) const
Returns true if the item represents an empty stack - either the type is invalid, or count is zero.
Definition: Item.h:69
This class bridges a vector of cItem for safe access via Lua.
Definition: Item.h:215
void CopyFrom(const cItemGrid &a_Src)
Copies all items from a_Src to this grid.
Definition: ItemGrid.cpp:83
const cItem & GetSlot(int a_X, int a_Y) const
Definition: ItemGrid.cpp:96
int GetNumSlots(void) const
Definition: ItemGrid.h:40
cItem RemoveOneItem(int a_SlotNum)
Removes one item from the stack in the specified slot, and returns it.
Definition: ItemGrid.cpp:516
std::unordered_map< CustomStatistic, StatValue > Custom
Represents a UI window.
Definition: Window.h:54
cWindow * GetWindow(void) const
Definition: WindowOwner.h:40
void OpenWindow(cWindow *a_Window)
Definition: WindowOwner.h:34
T x
Definition: Vector3.h:17
T y
Definition: Vector3.h:17
T z
Definition: Vector3.h:17
Definition: World.h:53
virtual void BroadcastSoundParticleEffect(const EffectID a_EffectID, Vector3i a_SrcPos, int a_Data, const cClientHandle *a_Exclude=nullptr) override
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:1806
virtual void BroadcastSoundEffect(const AString &a_SoundName, Vector3d a_Position, float a_Volume, float a_Pitch, const cClientHandle *a_Exclude=nullptr) override