summaryrefslogtreecommitdiffstats
path: root/src/BlockEntities
diff options
context:
space:
mode:
Diffstat (limited to 'src/BlockEntities')
-rw-r--r--src/BlockEntities/BlockEntity.cpp2
-rw-r--r--src/BlockEntities/BrewingstandEntity.cpp309
-rw-r--r--src/BlockEntities/BrewingstandEntity.h136
-rw-r--r--src/BlockEntities/CMakeLists.txt2
4 files changed, 449 insertions, 0 deletions
diff --git a/src/BlockEntities/BlockEntity.cpp b/src/BlockEntities/BlockEntity.cpp
index c59198e79..0b69830f6 100644
--- a/src/BlockEntities/BlockEntity.cpp
+++ b/src/BlockEntities/BlockEntity.cpp
@@ -6,6 +6,7 @@
#include "Globals.h"
#include "BeaconEntity.h"
#include "BlockEntity.h"
+#include "BrewingstandEntity.h"
#include "ChestEntity.h"
#include "CommandBlockEntity.h"
#include "DispenserEntity.h"
@@ -36,6 +37,7 @@ cBlockEntity * cBlockEntity::CreateByBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE
case E_BLOCK_ENDER_CHEST: return new cEnderChestEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
case E_BLOCK_FLOWER_POT: return new cFlowerPotEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
case E_BLOCK_FURNACE: return new cFurnaceEntity (a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, a_World);
+ case E_BLOCK_BREWING_STAND: return new cBrewingstandEntity(a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, a_World);
case E_BLOCK_HEAD: return new cMobHeadEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
case E_BLOCK_HOPPER: return new cHopperEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
case E_BLOCK_MOB_SPAWNER: return new cMobSpawnerEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
diff --git a/src/BlockEntities/BrewingstandEntity.cpp b/src/BlockEntities/BrewingstandEntity.cpp
new file mode 100644
index 000000000..e34297393
--- /dev/null
+++ b/src/BlockEntities/BrewingstandEntity.cpp
@@ -0,0 +1,309 @@
+
+#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
+
+#include "BrewingstandEntity.h"
+#include "../Bindings/PluginManager.h"
+#include "../UI/BrewingstandWindow.h"
+#include "../Entities/Player.h"
+#include "../Root.h"
+#include "../Chunk.h"
+
+
+
+
+
+
+
+
+
+
+
+
+cBrewingstandEntity::cBrewingstandEntity(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, cWorld * a_World) :
+ super(a_BlockType, a_BlockX, a_BlockY, a_BlockZ, ContentsWidth, ContentsHeight, a_World),
+ m_BlockMeta(a_BlockMeta),
+ m_IsDestroyed(false),
+ m_IsBrewing(false),
+ m_TimeBrewed(0)
+{
+ m_Contents.AddListener(*this);
+ for (int i = 0; i < 3; i++)
+ {
+ m_Results[i] = *(new cItem());
+ }
+}
+
+
+
+
+
+cBrewingstandEntity::~cBrewingstandEntity()
+{
+ // Tell window its owner is destroyed
+ cWindow * Window = GetWindow();
+ if (Window != nullptr)
+ {
+ Window->OwnerDestroyed();
+ }
+}
+
+
+
+
+
+void cBrewingstandEntity::UsedBy(cPlayer * a_Player)
+{
+ cWindow * Window = GetWindow();
+ if (Window == nullptr)
+ {
+ OpenWindow(new cBrewingstandWindow(m_PosX, m_PosY, m_PosZ, this));
+ Window = GetWindow();
+ }
+
+ if (Window != nullptr)
+ {
+ if (a_Player->GetWindow() != Window)
+ {
+ a_Player->OpenWindow(Window);
+ }
+ }
+
+ if (m_IsBrewing)
+ {
+ BroadcastProgress(0, m_NeedBrewingTime - m_TimeBrewed);
+ }
+ else
+ {
+ BroadcastProgress(0, 0);
+ }
+}
+
+
+
+
+
+bool cBrewingstandEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
+{
+ UNUSED(a_Dt);
+
+ if (!m_IsBrewing)
+ {
+ return false;
+ }
+
+ const cBrewingRecipes::cRecipe * Recipe = nullptr;
+ // The necessary brewing time, has been reached
+ if (m_TimeBrewed >= m_NeedBrewingTime)
+ {
+ BroadcastProgress(0, 0);
+ m_IsBrewing = false;
+ m_TimeBrewed = 0;
+
+ // Return if the hook has been canceled
+ if (cPluginManager::Get()->CallHookBrewingCompleting(*m_World, *this))
+ {
+ return false;
+ }
+
+ // Decrease item count, full stacks are allowed in the ingredient slot
+ cItem Ingredient = m_Contents.GetSlot(bsIngredient);
+ Ingredient.m_ItemCount -= 1;
+ m_Contents.SetSlot(bsIngredient, Ingredient);
+
+ // Loop over all bottle slots and update available bottles
+ for (int i = 0; i < 3; i++)
+ {
+ if (m_Contents.GetSlot(i).IsEmpty() || (m_CurrentBrewingRecipes[i] == nullptr))
+ {
+ continue;
+ }
+
+ Recipe = m_CurrentBrewingRecipes[i];
+ m_Contents.SetSlot(i, Recipe->Output->CopyOne());
+ }
+
+ // Brewing process completed
+ cPluginManager::Get()->CallHookBrewingCompleted(*m_World, *this);
+
+ return true;
+ }
+
+ m_TimeBrewed++;
+ UpdateProgressBars(false);
+ return false;
+}
+
+
+
+
+
+
+void cBrewingstandEntity::SendTo(cClientHandle & a_Client)
+{
+ // Nothing needs to be sent
+ UNUSED(a_Client);
+}
+
+
+
+
+
+void cBrewingstandEntity::BroadcastProgress(short a_ProgressbarID, short a_Value)
+{
+ cWindow * Window = GetWindow();
+ if (Window != nullptr)
+ {
+ Window->SetProperty(a_ProgressbarID, a_Value);
+ }
+}
+
+
+
+
+
+
+void cBrewingstandEntity::OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum)
+{
+ super::OnSlotChanged(a_ItemGrid, a_SlotNum);
+
+ if (m_IsDestroyed)
+ {
+ return;
+ }
+
+ ASSERT(a_ItemGrid == &m_Contents);
+
+ // Check if still a item is in the ingredient slot
+ if (GetSlot(bsIngredient).IsEmpty())
+ {
+ if (m_IsBrewing)
+ {
+ // Cancel brewing
+ BroadcastProgress(0, 0);
+ m_IsBrewing = false;
+ m_TimeBrewed = 0;
+ }
+ return;
+ }
+
+ // Recheck the bottles
+ cBrewingRecipes * BR = cRoot::Get()->GetBrewingRecipes();
+ const cBrewingRecipes::cRecipe * Recipe = nullptr;
+ bool Stop = true;
+ for (int i = 0; i < 3; i++)
+ {
+ if (GetSlot(i).IsEmpty())
+ {
+ m_CurrentBrewingRecipes[i] = nullptr;
+ m_Results[i].Clear();
+ continue;
+ }
+
+ if (m_CurrentBrewingRecipes[i] != nullptr)
+ {
+ Recipe = m_CurrentBrewingRecipes[i];
+ if (Recipe->Ingredient->IsEqual(GetSlot(bsIngredient)) && Recipe->Input->IsEqual(GetSlot(i)))
+ {
+ Stop = false;
+ continue;
+ }
+ }
+
+ Recipe = BR->GetRecipeFrom(m_Contents.GetSlot(i), m_Contents.GetSlot(bsIngredient));
+ if (Recipe != nullptr)
+ {
+ // Found a brewing recipe for the items
+ m_CurrentBrewingRecipes[i] = Recipe;
+ m_Results[i] = Recipe->Output->CopyOne();
+ Stop = false;
+ }
+ }
+
+ if (Stop)
+ {
+ if (m_IsBrewing)
+ {
+ // Cancel brewing
+ BroadcastProgress(0, 0);
+ m_IsBrewing = false;
+ m_TimeBrewed = 0;
+ }
+ return;
+ }
+
+ // Start brewing process, if not running
+ if (!m_IsBrewing)
+ {
+ m_IsBrewing = true;
+ }
+}
+
+
+
+
+
+void cBrewingstandEntity::UpdateProgressBars(bool a_ForceUpdate)
+{
+ /** Sending an update every 3th tick, using a higher value lets look the progressbar ugly */
+ if (!a_ForceUpdate && (m_World->GetWorldAge() % 3 != 0))
+ {
+ return;
+ }
+
+ BroadcastProgress(0, m_NeedBrewingTime - m_TimeBrewed);
+}
+
+
+
+
+
+void cBrewingstandEntity::setTimeBrewed(short a_TimeBrewed)
+{
+ m_TimeBrewed = a_TimeBrewed;
+}
+
+
+
+
+
+void cBrewingstandEntity::ContinueBrewing(void)
+{
+ // Continue brewing if number is greater than 0
+ if (m_TimeBrewed > 0)
+ {
+ m_IsBrewing = true;
+ }
+}
+
+
+
+
+
+void cBrewingstandEntity::GetRecipes(void)
+{
+ if (GetSlot(3).IsEmpty())
+ {
+ return;
+ }
+
+ cBrewingRecipes * BR = cRoot::Get()->GetBrewingRecipes();
+ const cBrewingRecipes::cRecipe * Recipe = nullptr;
+ for (int i = 0; i < 3; i++)
+ {
+ if (GetSlot(i).IsEmpty())
+ {
+ continue;
+ }
+ Recipe = BR->GetRecipeFrom(GetSlot(i), GetSlot(bsIngredient));
+ if (Recipe != nullptr)
+ {
+ m_CurrentBrewingRecipes[i] = Recipe;
+ m_Results[i] = Recipe->Output->CopyOne();
+ }
+ }
+}
+
+
+
+
+
diff --git a/src/BlockEntities/BrewingstandEntity.h b/src/BlockEntities/BrewingstandEntity.h
new file mode 100644
index 000000000..a895c4bde
--- /dev/null
+++ b/src/BlockEntities/BrewingstandEntity.h
@@ -0,0 +1,136 @@
+
+#pragma once
+
+#include "BlockEntityWithItems.h"
+#include "../BrewingRecipes.h"
+#include "../Root.h"
+
+
+
+
+class cClientHandle;
+
+
+
+
+
+// tolua_begin
+class cBrewingstandEntity :
+ public cBlockEntityWithItems
+{
+ typedef cBlockEntityWithItems super;
+
+public:
+ enum
+ {
+ bsLeftBottle = 0, // Left bottle slot number
+ bsMiddleBottle = 1, // Middle bottle slot number
+ bsRightBottle = 2, // Right bottle slot number
+ bsIngredient = 3, // Top ingredient slot number
+
+ ContentsWidth = 4,
+ ContentsHeight = 1,
+ };
+
+ // tolua_end
+
+ BLOCKENTITY_PROTODEF(cBrewingstandEntity)
+
+ /** Constructor used for normal operation */
+ cBrewingstandEntity(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, cWorld * a_World);
+
+ virtual ~cBrewingstandEntity();
+
+ // cBlockEntity overrides:
+ virtual void SendTo(cClientHandle & a_Client) override;
+ virtual bool Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
+ virtual void UsedBy(cPlayer * a_Player) override;
+ virtual void Destroy() override
+ {
+ m_IsDestroyed = true;
+ super::Destroy();
+ }
+
+ // tolua_begin
+
+ /** Returns the time until the current items finishes brewing, in ticks */
+ short GetBrewingTimeLeft(void) const { return m_NeedBrewingTime - m_TimeBrewed; }
+
+ /** Returns the time that the current items has been brewing, in ticks */
+ short GetTimeBrewed(void) { return m_TimeBrewed; }
+
+ /** Returns the item in the left bottle slot */
+ const cItem & GetLeftBottleSlot(void) const { return GetSlot(bsLeftBottle); }
+
+ /** Returns the item in the middle bottle slot */
+ const cItem & GetMiddleBottleSlot(void) const { return GetSlot(bsMiddleBottle); }
+
+ /** Returns the item in the right bottle slot */
+ const cItem & GetRightBottleSlot(void) const { return GetSlot(bsRightBottle); }
+
+ /** Returns the item in the ingredient slot */
+ const cItem & GetIndgredientSlot(void) const { return GetSlot(bsIngredient); }
+
+ /** Get the expected result item for the given slot number */
+ const cItem & GetResultItem(int a_SlotNumber) { return m_Results[a_SlotNumber]; }
+
+ /** Sets the item in the left bottle slot */
+ void SetLeftBottleSlot(const cItem & a_Item) { SetSlot(bsLeftBottle, a_Item); }
+
+ /** Sets the item in the middle bottle slot */
+ void SetMiddleBottleSlot(const cItem & a_Item) { SetSlot(bsMiddleBottle, a_Item); }
+
+ /** Sets the item in the right bottle slot */
+ void SetRightBottleSlot(const cItem & a_Item) { SetSlot(bsRightBottle, a_Item); }
+
+ /** Sets the item in the ingredient slot */
+ void SetIngredientSlot(const cItem & a_Item) { SetSlot(bsIngredient, a_Item); }
+
+ // tolua_end
+
+ /** Sets the current brewing time. Will be called if the brewing stand gets loaded from the world. */
+ void setTimeBrewed(short a_TimeBrewed);
+
+ /** Starts the brewing proccess. Will be called if the brewing stand gets loaded from the world. */
+ void ContinueBrewing(void);
+
+ /** Gets the recipes. Will be called if the brewing stand gets loaded from the world. */
+ void GetRecipes(void);
+protected:
+
+ /** Block meta of the block currently represented by this entity */
+ NIBBLETYPE m_BlockMeta;
+
+ /** Set to true when the brewing stand entity has been destroyed to prevent the block being set again */
+ bool m_IsDestroyed;
+
+ /** Set to true if the brewing stand is brewing an item */
+ bool m_IsBrewing;
+
+ /** Brewing time is 400 ticks */
+ const short m_NeedBrewingTime = 400;
+
+ /** Store the current brewing recipes */
+ const cBrewingRecipes::cRecipe * m_CurrentBrewingRecipes[3] = {};
+
+ /** Result items for the bottle inputs */
+ cItem m_Results[3] = {};
+
+ /** Amount of ticks that the current item has been brewed */
+ short m_TimeBrewed;
+
+ /** Sends the specified progressbar value to all clients of the window */
+ void BroadcastProgress(short a_ProgressbarID, short a_Value);
+
+ // /** Broadcasts progressbar updates, if needed */
+ void UpdateProgressBars(bool a_ForceUpdate = false);
+
+ // cItemGrid::cListener overrides:
+ virtual void OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum) override;
+
+} ; // tolua_export
+
+
+
+
+
diff --git a/src/BlockEntities/CMakeLists.txt b/src/BlockEntities/CMakeLists.txt
index 0d1776eb5..931484be0 100644
--- a/src/BlockEntities/CMakeLists.txt
+++ b/src/BlockEntities/CMakeLists.txt
@@ -7,6 +7,7 @@ include_directories ("${PROJECT_SOURCE_DIR}/../")
SET (SRCS
BeaconEntity.cpp
BlockEntity.cpp
+ BrewingstandEntity.cpp
ChestEntity.cpp
CommandBlockEntity.cpp
DispenserEntity.cpp
@@ -27,6 +28,7 @@ SET (HDRS
BeaconEntity.h
BlockEntity.h
BlockEntityWithItems.h
+ BrewingstandEntity.h
ChestEntity.h
CommandBlockEntity.h
DispenserEntity.h