Cuberite
A lightweight, fast and extensible game server for Minecraft
BrewingstandEntity.cpp
Go to the documentation of this file.
1 
2 #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
3 
4 #include "BrewingstandEntity.h"
5 #include "../Bindings/PluginManager.h"
6 #include "../UI/BrewingstandWindow.h"
7 #include "../Entities/Player.h"
8 #include "../Chunk.h"
9 
10 
11 
12 
13 
14 cBrewingstandEntity::cBrewingstandEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld * a_World):
15  Super(a_BlockType, a_BlockMeta, a_Pos, ContentsWidth, ContentsHeight, a_World),
16  m_IsBrewing(false),
17  m_TimeBrewed(0),
18  m_RemainingFuel(0)
19 {
20  m_Contents.AddListener(*this);
21 }
22 
23 
24 
25 
26 
28 {
29  Super::CopyFrom(a_Src);
30  auto & src = static_cast<const cBrewingstandEntity &>(a_Src);
31  m_IsBrewing = src.m_IsBrewing;
32  m_CurrentBrewingRecipes = src.m_CurrentBrewingRecipes;
33  m_Results = src.m_Results;
34  m_TimeBrewed = src.m_TimeBrewed;
35  m_RemainingFuel = src.m_RemainingFuel;
36 }
37 
38 
39 
40 
41 
43 {
44  const auto Window = GetWindow();
45  if (Window != nullptr)
46  {
47  // Tell window its owner is destroyed:
48  Window->OwnerDestroyed();
49  }
50 }
51 
52 
53 
54 
55 
57 {
58  // Nothing needs to be sent
59  UNUSED(a_Client);
60 }
61 
62 
63 
64 
65 
66 bool cBrewingstandEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
67 {
68  UNUSED(a_Dt);
69 
70  if (!m_IsBrewing)
71  {
72  return false;
73  }
74 
75  // The necessary brewing time, has been reached
77  {
78  BroadcastProgress(0, 0);
79  m_IsBrewing = false;
80  m_TimeBrewed = 0;
81 
82  // Return if the hook has been cancelled
83  if (cPluginManager::Get()->CallHookBrewingCompleting(*m_World, *this))
84  {
85  return false;
86  }
87 
88  // Decrease item count, full stacks are allowed in the ingredient slot
89  cItem Ingredient = m_Contents.GetSlot(bsIngredient);
90  Ingredient.m_ItemCount -= 1;
91  m_Contents.SetSlot(bsIngredient, Ingredient);
92 
93  // Fuel slot
95  if (m_RemainingFuel <= 0)
96  {
98  {
100  Fuel.m_ItemCount -= 1;
101  m_Contents.SetSlot(bsFuel, Fuel);
102  m_RemainingFuel = 20;
104  }
105  }
106  else
107  {
109  }
110 
111 
112  // Loop over all bottle slots and update available bottles
113  const cBrewingRecipes::cRecipe * Recipe = nullptr;
114  for (std::size_t i = 0; i < 3; i++)
115  {
116  if (m_Contents.GetSlot(static_cast<int>(i)).IsEmpty() || (m_CurrentBrewingRecipes[i] == nullptr))
117  {
118  continue;
119  }
120 
121  Recipe = m_CurrentBrewingRecipes[i];
122  m_Contents.SetSlot(static_cast<int>(i), Recipe->Output.CopyOne());
123  }
124 
125  // Brewing process completed
126  m_World->BroadcastSoundEffect("block.brewing_stand.brew", m_Pos, 1.0f, 1.0f);
128  return true;
129  }
130 
131  m_TimeBrewed++;
132  UpdateProgressBars(false);
133  return false;
134 }
135 
136 
137 
138 
139 
141 {
143 
144  cWindow * Window = GetWindow();
145  if (Window == nullptr)
146  {
147  OpenWindow(new cBrewingstandWindow(this));
148  Window = GetWindow();
149  }
150 
151  if (Window != nullptr)
152  {
153  if (a_Player->GetWindow() != Window)
154  {
155  a_Player->OpenWindow(*Window);
156  }
157  }
158 
159  if (m_IsBrewing)
160  {
162  }
163  else
164  {
165  BroadcastProgress(0, 0);
166  }
168  return true;
169 }
170 
171 
172 
173 
174 
175 void cBrewingstandEntity::BroadcastProgress(size_t a_ProgressbarID, short a_Value)
176 {
177  cWindow * Window = GetWindow();
178  if (Window != nullptr)
179  {
180  Window->SetProperty(a_ProgressbarID, a_Value);
181  }
182 }
183 
184 
185 
186 
187 
188 void cBrewingstandEntity::OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum)
189 {
190  Super::OnSlotChanged(a_ItemGrid, a_SlotNum);
191 
192  ASSERT(a_ItemGrid == &m_Contents);
193 
194  // Check for fuel
195  if (m_RemainingFuel <= 0)
196  {
197  if (GetSlot(bsFuel).IsEmpty())
198  {
199  // No remaining fuel stop brewing and bail out
200  m_IsBrewing = false;
201  return;
202  }
203  else
204  {
205  // Fuel is available, refill
206  m_RemainingFuel = 20;
208  cItem Fuel = m_Contents.GetSlot(bsFuel);
209  Fuel.m_ItemCount -= 1;
210  m_Contents.SetSlot(bsFuel, Fuel);
211  }
212  }
213 
214  // Check if still a item is in the ingredient slot
215  if (GetSlot(bsIngredient).IsEmpty())
216  {
217  if (m_IsBrewing)
218  {
219  // Cancel brewing
220  BroadcastProgress(0, 0);
221  m_IsBrewing = false;
222  m_TimeBrewed = 0;
223  }
224  return;
225  }
226 
227  // Recheck the bottles
229  const cBrewingRecipes::cRecipe * Recipe = nullptr;
230  bool Stop = true;
231  for (std::size_t i = 0; i < 3; i++)
232  {
233  if (GetSlot(static_cast<int>(i)).IsEmpty())
234  {
235  m_CurrentBrewingRecipes[i] = nullptr;
236  m_Results[i].Clear();
237  continue;
238  }
239 
240  if (m_CurrentBrewingRecipes[i] != nullptr)
241  {
242  Recipe = m_CurrentBrewingRecipes[i];
243  if (Recipe->Ingredient.IsEqual(GetSlot(bsIngredient)) && Recipe->Input.IsEqual(GetSlot(static_cast<int>(i))))
244  {
245  Stop = false;
246  continue;
247  }
248  }
249 
250  Recipe = BR->GetRecipeFrom(m_Contents.GetSlot(static_cast<int>(i)), m_Contents.GetSlot(bsIngredient));
251  if (Recipe != nullptr)
252  {
253  // Found a brewing recipe for the items
254  m_CurrentBrewingRecipes[i] = Recipe;
255  m_Results[i] = Recipe->Output.CopyOne();
256  Stop = false;
257  }
258  }
259 
260  if (Stop)
261  {
262  if (m_IsBrewing)
263  {
264  // Cancel brewing
265  BroadcastProgress(0, 0);
266  m_IsBrewing = false;
267  m_TimeBrewed = 0;
268  }
269  return;
270  }
271 
272  // Start brewing process, if not running
273  if (!m_IsBrewing)
274  {
275  m_IsBrewing = true;
276  }
277 }
278 
279 
280 
281 
282 
284 {
285  // Send an update every 3rd tick, using a higher value makes the progressbar look ugly:
286  if (!a_ForceUpdate && ((m_World->GetWorldTickAge() % 3_tick) != 0_tick))
287  {
288  return;
289  }
290 
292 }
293 
294 
295 
296 
297 
299 {
300  // Continue brewing if number is greater than 0
301  if ((m_TimeBrewed > 0) && (m_RemainingFuel > 0))
302  {
303  m_IsBrewing = true;
304  }
305 }
306 
307 
308 
309 
310 
312 {
313  if (GetSlot(bsIngredient).IsEmpty())
314  {
315  return;
316  }
317 
319  const cBrewingRecipes::cRecipe * Recipe = nullptr;
320  for (std::size_t i = 0; i < 3; i++)
321  {
322  if (GetSlot(static_cast<int>(i)).IsEmpty())
323  {
324  continue;
325  }
326  Recipe = BR->GetRecipeFrom(GetSlot(static_cast<int>(i)), GetSlot(bsIngredient));
327  if (Recipe != nullptr)
328  {
329  m_CurrentBrewingRecipes[i] = Recipe;
330  m_Results[i] = Recipe->Output.CopyOne();
331  }
332  }
333 }
334 
335 
336 
337 
338 
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
#define ASSERT(x)
Definition: Globals.h:276
#define UNUSED
Definition: Globals.h:72
static cPluginManager * Get(void)
Returns the instance of the Plugin Manager (there is only ever one)
bool CallHookBrewingCompleted(cWorld &a_World, cBrewingstandEntity &a_Brewingstand)
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.
const cItem & GetSlot(int a_SlotNum) const
virtual void OnSlotChanged(cItemGrid *a_Grid, int a_SlotNum) override
Called whenever a slot changes.
bool m_IsBrewing
Set to true if the brewing stand is brewing an item.
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.
short m_RemainingFuel
The remaining fuel for the brewing stand.
virtual void OnSlotChanged(cItemGrid *a_ItemGrid, int a_SlotNum) override
Called whenever a slot changes.
void ContinueBrewing(void)
Starts the brewing proccess.
virtual void SendTo(cClientHandle &a_Client) override
Sends the packet defining the block entity to the client specified.
void LoadRecipes(void)
Gets the recipes.
virtual void OnRemoveFromWorld() override
Called when the block entity object is removed from a world.
virtual bool UsedBy(cPlayer *a_Player) override
Called when a player uses this entity; should open the UI window.
std::array< const cBrewingRecipes::cRecipe *, 3 > m_CurrentBrewingRecipes
Store the current brewing recipes.
void BroadcastProgress(size_t a_ProgressbarID, short a_Value)
Sends the specified progressbar value to all clients of the window.
void UpdateProgressBars(bool a_ForceUpdate=false)
std::array< cItem, 3 > m_Results
Result items for the bottle inputs.
const short m_NeedBrewingTime
Brewing time is 400 ticks.
cBrewingstandEntity(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, Vector3i a_Pos, cWorld *a_World)
Constructor used for normal operation.
virtual void CopyFrom(const cBlockEntity &a_Src) override
Copies all properties of a_Src into this entity, except for its m_World and location.
short m_TimeBrewed
Amount of ticks that the current item has been brewed.
const cRecipe * GetRecipeFrom(const cItem &a_Input, const cItem &a_Ingredient) const
Returns a recipe for the specified input, nullptr if no recipe found.
Definition: Chunk.h:36
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
Definition: Item.h:37
char m_ItemCount
Definition: Item.h:164
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
bool IsEqual(const cItem &a_Item) const
Definition: Item.h:76
cItem CopyOne(void) const
Returns a copy of this item with m_ItemCount set to 1.
Definition: Item.cpp:93
void SetSlot(int a_X, int a_Y, const cItem &a_Item)
Definition: ItemGrid.cpp:121
const cItem & GetSlot(int a_X, int a_Y) const
Definition: ItemGrid.cpp:96
void AddListener(cListener &a_Listener)
Adds a callback that gets called whenever a slot changes.
Definition: ItemGrid.cpp:809
static cRoot * Get()
Definition: Root.h:52
cBrewingRecipes * GetBrewingRecipes(void)
Definition: Root.h:95
std::unordered_map< CustomStatistic, StatValue > Custom
Represents a UI window.
Definition: Window.h:54
virtual void SetProperty(size_t a_Property, short a_Value)
Updates a numerical property associated with the window.
Definition: Window.cpp:406
cWindow * GetWindow(void) const
Definition: WindowOwner.h:40
void OpenWindow(cWindow *a_Window)
Definition: WindowOwner.h:34
Definition: World.h:53
cTickTimeLong GetWorldTickAge() const
Definition: World.cpp:509
virtual void BroadcastSoundEffect(const AString &a_SoundName, Vector3d a_Position, float a_Volume, float a_Pitch, const cClientHandle *a_Exclude=nullptr) override