Corrected brewingstand and added support for fuel
This commit is contained in:
parent
dffbf0b510
commit
41bfb22834
@ -441,6 +441,26 @@ return
|
||||
},
|
||||
Notes = "Returns the item in the right bottle slot",
|
||||
},
|
||||
GetFuelSlot =
|
||||
{
|
||||
Returns =
|
||||
{
|
||||
{
|
||||
Type = "cItem",
|
||||
},
|
||||
},
|
||||
Notes = "Returns the item in the top left fuel slot",
|
||||
},
|
||||
GetRemainingFuel =
|
||||
{
|
||||
Returns =
|
||||
{
|
||||
{
|
||||
Type = "number",
|
||||
},
|
||||
},
|
||||
Notes = "Returns the remaining fuel that is left. It's the amount of brewing operations that can be done (20 for one blaze powder).",
|
||||
},
|
||||
GetTimeBrewed =
|
||||
{
|
||||
Returns =
|
||||
@ -495,6 +515,17 @@ return
|
||||
},
|
||||
Notes = "Sets the item in the right bottle slot",
|
||||
},
|
||||
SetFuelSlot =
|
||||
{
|
||||
Params =
|
||||
{
|
||||
{
|
||||
Name = "FuelSlot",
|
||||
Type = "cItem",
|
||||
},
|
||||
},
|
||||
Notes = "Sets the item in the top left fuel slot",
|
||||
},
|
||||
},
|
||||
Constants =
|
||||
{
|
||||
@ -514,6 +545,10 @@ return
|
||||
{
|
||||
Notes = "Index of the right bottle slot",
|
||||
},
|
||||
bsFuel =
|
||||
{
|
||||
Notes = "Index of the top left fuel slot",
|
||||
},
|
||||
ContentsHeight =
|
||||
{
|
||||
Notes = "Height (Y) of the {{cItemGrid|cItemGrid}} representing the contents",
|
||||
|
@ -24,7 +24,8 @@ cBrewingstandEntity::cBrewingstandEntity(int a_BlockX, int a_BlockY, int a_Block
|
||||
m_BlockMeta(a_BlockMeta),
|
||||
m_IsDestroyed(false),
|
||||
m_IsBrewing(false),
|
||||
m_TimeBrewed(0)
|
||||
m_TimeBrewed(0),
|
||||
m_RemainingFuel(0)
|
||||
{
|
||||
m_Contents.AddListener(*this);
|
||||
for (int i = 0; i < 3; i++)
|
||||
@ -76,6 +77,7 @@ bool cBrewingstandEntity::UsedBy(cPlayer * a_Player)
|
||||
{
|
||||
BroadcastProgress(0, 0);
|
||||
}
|
||||
BroadcastProgress(1, m_RemainingFuel);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -95,12 +97,11 @@ bool cBrewingstandEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
||||
// The necessary brewing time, has been reached
|
||||
if (m_TimeBrewed >= m_NeedBrewingTime)
|
||||
{
|
||||
const cBrewingRecipes::cRecipe * Recipe = nullptr;
|
||||
BroadcastProgress(0, 0);
|
||||
m_IsBrewing = false;
|
||||
m_TimeBrewed = 0;
|
||||
|
||||
// Return if the hook has been canceled
|
||||
// Return if the hook has been cancelled
|
||||
if (cPluginManager::Get()->CallHookBrewingCompleting(*m_World, *this))
|
||||
{
|
||||
return false;
|
||||
@ -111,7 +112,27 @@ bool cBrewingstandEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
||||
Ingredient.m_ItemCount -= 1;
|
||||
m_Contents.SetSlot(bsIngredient, Ingredient);
|
||||
|
||||
// Fuel slot
|
||||
m_RemainingFuel--;
|
||||
if (m_RemainingFuel <= 0)
|
||||
{
|
||||
if (!m_Contents.GetSlot(bsFuel).IsEmpty())
|
||||
{
|
||||
cItem Fuel = m_Contents.GetSlot(bsFuel);
|
||||
Fuel.m_ItemCount -= 1;
|
||||
m_Contents.SetSlot(bsFuel, Fuel);
|
||||
m_RemainingFuel = 20;
|
||||
BroadcastProgress(1, m_RemainingFuel);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BroadcastProgress(1, m_RemainingFuel);
|
||||
}
|
||||
|
||||
|
||||
// Loop over all bottle slots and update available bottles
|
||||
const cBrewingRecipes::cRecipe * Recipe = nullptr;
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
if (m_Contents.GetSlot(i).IsEmpty() || (m_CurrentBrewingRecipes[i] == nullptr))
|
||||
@ -125,7 +146,6 @@ bool cBrewingstandEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
|
||||
|
||||
// Brewing process completed
|
||||
cPluginManager::Get()->CallHookBrewingCompleted(*m_World, *this);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -174,6 +194,26 @@ void cBrewingstandEntity::OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum)
|
||||
|
||||
ASSERT(a_ItemGrid == &m_Contents);
|
||||
|
||||
// Check for fuel
|
||||
if (m_RemainingFuel <= 0)
|
||||
{
|
||||
if (GetSlot(bsFuel).IsEmpty())
|
||||
{
|
||||
// No remaining fuel stop brewing and bail out
|
||||
m_IsBrewing = false;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fuel is available, refill
|
||||
m_RemainingFuel = 20;
|
||||
BroadcastProgress(1, m_RemainingFuel);
|
||||
cItem Fuel = m_Contents.GetSlot(bsFuel);
|
||||
Fuel.m_ItemCount -= 1;
|
||||
m_Contents.SetSlot(bsFuel, Fuel);
|
||||
}
|
||||
}
|
||||
|
||||
// Check if still a item is in the ingredient slot
|
||||
if (GetSlot(bsIngredient).IsEmpty())
|
||||
{
|
||||
@ -258,19 +298,10 @@ void cBrewingstandEntity::UpdateProgressBars(bool a_ForceUpdate)
|
||||
|
||||
|
||||
|
||||
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)
|
||||
if ((m_TimeBrewed > 0) && (m_RemainingFuel > 0))
|
||||
{
|
||||
m_IsBrewing = true;
|
||||
}
|
||||
@ -280,9 +311,9 @@ void cBrewingstandEntity::ContinueBrewing(void)
|
||||
|
||||
|
||||
|
||||
void cBrewingstandEntity::GetRecipes(void)
|
||||
void cBrewingstandEntity::LoadRecipes(void)
|
||||
{
|
||||
if (GetSlot(3).IsEmpty())
|
||||
if (GetSlot(bsIngredient).IsEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -27,8 +27,9 @@ public:
|
||||
bsMiddleBottle = 1, // Middle bottle slot number
|
||||
bsRightBottle = 2, // Right bottle slot number
|
||||
bsIngredient = 3, // Top ingredient slot number
|
||||
bsFuel = 4, // Top left fuel slot number
|
||||
|
||||
ContentsWidth = 4,
|
||||
ContentsWidth = 5,
|
||||
ContentsHeight = 1,
|
||||
};
|
||||
|
||||
@ -59,6 +60,9 @@ public:
|
||||
/** Returns the time that the current items has been brewing, in ticks */
|
||||
short GetTimeBrewed(void) { return m_TimeBrewed; }
|
||||
|
||||
/** Returns the remaining fuel that is left. */
|
||||
short GetRemainingFuel(void) { return m_RemainingFuel; }
|
||||
|
||||
/** Returns the item in the left bottle slot */
|
||||
const cItem & GetLeftBottleSlot(void) const { return GetSlot(bsLeftBottle); }
|
||||
|
||||
@ -71,6 +75,9 @@ public:
|
||||
/** Returns the item in the ingredient slot */
|
||||
const cItem & GetIndgredientSlot(void) const { return GetSlot(bsIngredient); }
|
||||
|
||||
/** Returns the item in the fuel slot. */
|
||||
const cItem & GetFuelSlot(void) const { return GetSlot(bsFuel); }
|
||||
|
||||
/** Get the expected result item for the given slot number */
|
||||
const cItem & GetResultItem(int a_SlotNumber) { return m_Results[a_SlotNumber]; }
|
||||
|
||||
@ -86,16 +93,22 @@ public:
|
||||
/** Sets the item in the ingredient slot */
|
||||
void SetIngredientSlot(const cItem & a_Item) { SetSlot(bsIngredient, a_Item); }
|
||||
|
||||
/** Sets the item in the fuel slot */
|
||||
void SetFuelSlot(const cItem & a_Item) { SetSlot(bsFuel, 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);
|
||||
void SetTimeBrewed(short a_TimeBrewed) { m_TimeBrewed = a_TimeBrewed; }
|
||||
|
||||
/** Sets the remaining fuel. Will be called if the brewing stand gets loaded from the world. */
|
||||
void SetRemainingFuel(short a_RemainingFuel) { m_RemainingFuel = a_RemainingFuel; }
|
||||
|
||||
/** 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);
|
||||
void LoadRecipes(void);
|
||||
protected:
|
||||
|
||||
/** Block meta of the block currently represented by this entity */
|
||||
@ -119,6 +132,9 @@ protected:
|
||||
/** Amount of ticks that the current item has been brewed */
|
||||
short m_TimeBrewed;
|
||||
|
||||
/** The remaining fuel for the brewing stand. It's the amount of brewing operations that can be done. */
|
||||
short m_RemainingFuel;
|
||||
|
||||
/** Sends the specified progressbar value to all clients of the window */
|
||||
void BroadcastProgress(short a_ProgressbarID, short a_Value);
|
||||
|
||||
|
@ -285,3 +285,11 @@ bool cBrewingRecipes::IsBottle(const cItem & a_Item) const
|
||||
|
||||
|
||||
|
||||
bool cBrewingRecipes::IsFuel(const cItem & a_Item) const
|
||||
{
|
||||
return (a_Item.m_ItemType == E_ITEM_BLAZE_POWDER);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -39,7 +39,10 @@ public:
|
||||
bool IsIngredient(const cItem & a_Ingredient) const;
|
||||
|
||||
/** Returns true if the item is a bottle / potion, false if not. */
|
||||
bool IsBottle(const cItem & a_Bottle) const;
|
||||
bool IsBottle(const cItem & a_Item) const;
|
||||
|
||||
/** Returns true if the item is the fuel, false if not. */
|
||||
bool IsFuel(const cItem & a_Item) const;
|
||||
private:
|
||||
void ClearRecipes(void);
|
||||
|
||||
|
@ -31,17 +31,15 @@ void cBrewingstandWindow::DistributeStack(cItem & a_ItemStack, int a_Slot, cPlay
|
||||
|
||||
if (a_ClickedArea == m_SlotAreas[0])
|
||||
{
|
||||
// Brewing stand Area
|
||||
if ((a_Slot >= 0) && (a_Slot < 3))
|
||||
if ((a_Slot >= 0) && (a_Slot <= 4))
|
||||
{
|
||||
// Bottle slots
|
||||
// Brewing stand Area
|
||||
AreasInOrder.push_back(m_SlotAreas[2]); /* Hotbar */
|
||||
AreasInOrder.push_back(m_SlotAreas[1]); /* Inventory */
|
||||
super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Ingredient slot
|
||||
AreasInOrder.push_back(m_SlotAreas[1]); /* Inventory */
|
||||
AreasInOrder.push_back(m_SlotAreas[2]); /* Hotbar */
|
||||
super::DistributeStackToAreas(a_ItemStack, a_Player, AreasInOrder, a_ShouldApply, false);
|
||||
@ -50,7 +48,7 @@ void cBrewingstandWindow::DistributeStack(cItem & a_ItemStack, int a_Slot, cPlay
|
||||
else
|
||||
{
|
||||
cBrewingRecipes * BR = cRoot::Get()->GetBrewingRecipes();
|
||||
if ((BR->IsBottle(a_ItemStack)) || (BR->IsIngredient(a_ItemStack)))
|
||||
if ((BR->IsBottle(a_ItemStack)) || (BR->IsIngredient(a_ItemStack)) || BR->IsFuel(a_ItemStack))
|
||||
{
|
||||
AreasInOrder.push_back(m_SlotAreas[0]); /* brewing stand Area */
|
||||
}
|
||||
|
@ -1947,7 +1947,7 @@ void cSlotAreaFurnace::HandleSmeltItem(const cItem & a_Result, cPlayer & a_Playe
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// cSlotAreaBrewingstand:
|
||||
cSlotAreaBrewingstand::cSlotAreaBrewingstand(cBrewingstandEntity * a_Brewingstand, cWindow & a_ParentWindow) :
|
||||
cSlotArea(4, a_ParentWindow),
|
||||
cSlotArea(5, a_ParentWindow),
|
||||
m_Brewingstand(a_Brewingstand)
|
||||
{
|
||||
m_Brewingstand->GetContents().AddListener(*this);
|
||||
@ -1975,100 +1975,101 @@ void cSlotAreaBrewingstand::Clicked(cPlayer & a_Player, int a_SlotNum, eClickAct
|
||||
return;
|
||||
}
|
||||
|
||||
if ((a_SlotNum >= 0) && (a_SlotNum < 3))
|
||||
if (GetSlot(a_SlotNum, a_Player) == nullptr)
|
||||
{
|
||||
bool bAsync = false;
|
||||
if (GetSlot(a_SlotNum, a_Player) == nullptr)
|
||||
{
|
||||
LOGWARNING("GetSlot(%d) returned nullptr! Ignoring click", a_SlotNum);
|
||||
return;
|
||||
}
|
||||
LOGWARNING("GetSlot(%d) returned nullptr! Ignoring click", a_SlotNum);
|
||||
return;
|
||||
}
|
||||
|
||||
cItem Slot(*GetSlot(a_SlotNum, a_Player));
|
||||
if (!Slot.IsSameType(a_ClickedItem))
|
||||
{
|
||||
LOGWARNING("*** Window lost sync at item %d in SlotArea with %d items ***", a_SlotNum, m_NumSlots);
|
||||
LOGWARNING("My item: %s", ItemToFullString(Slot).c_str());
|
||||
LOGWARNING("Their item: %s", ItemToFullString(a_ClickedItem).c_str());
|
||||
bAsync = true;
|
||||
}
|
||||
cItem Slot(*GetSlot(a_SlotNum, a_Player));
|
||||
cItem & DraggingItem = a_Player.GetDraggingItem();
|
||||
cBrewingRecipes * BR = cRoot::Get()->GetBrewingRecipes();
|
||||
|
||||
if ((a_SlotNum >= 0) && (a_SlotNum <= 2))
|
||||
{
|
||||
// Bottle slots
|
||||
switch (a_ClickAction)
|
||||
{
|
||||
case caLeftClick:
|
||||
case caRightClick:
|
||||
{
|
||||
if (BR->IsBottle(Slot))
|
||||
{
|
||||
HandleBrewedItem(a_Player, Slot);
|
||||
}
|
||||
if (!DraggingItem.IsEmpty() && !BR->IsBottle(DraggingItem))
|
||||
{
|
||||
// Deny placing a invalid item into the bottle slot
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case caShiftLeftClick:
|
||||
case caShiftRightClick:
|
||||
{
|
||||
if (BR->IsBottle(Slot))
|
||||
{
|
||||
HandleBrewedItem(a_Player, Slot);
|
||||
}
|
||||
super::ShiftClicked(a_Player, a_SlotNum, Slot);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
if (!DraggingItem.IsEmpty() && !BR->IsBottle(DraggingItem))
|
||||
{
|
||||
// Deny placing a invalid item into the bottle slot
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((a_SlotNum == 3) && !DraggingItem.IsEmpty())
|
||||
{
|
||||
// Ingredient slot
|
||||
switch (a_ClickAction)
|
||||
{
|
||||
case caShiftLeftClick:
|
||||
case caShiftRightClick:
|
||||
{
|
||||
HandleBrewedItem(a_Player);
|
||||
ShiftClicked(a_Player, a_SlotNum, Slot);
|
||||
return;
|
||||
}
|
||||
case caMiddleClick:
|
||||
{
|
||||
MiddleClicked(a_Player, a_SlotNum);
|
||||
return;
|
||||
}
|
||||
case caDropKey:
|
||||
case caCtrlDropKey:
|
||||
{
|
||||
DropClicked(a_Player, a_SlotNum, (a_SlotNum == caCtrlDropKey));
|
||||
Slot.m_ItemCount = Slot.m_ItemCount - GetSlot(a_SlotNum, a_Player)->m_ItemCount;
|
||||
HandleBrewedItem(a_Player);
|
||||
return;
|
||||
super::ShiftClicked(a_Player, a_SlotNum, Slot);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
if (!BR->IsIngredient(DraggingItem))
|
||||
{
|
||||
// Deny placing a invalid item into the ingredient slot
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cItem & DraggingItem = a_Player.GetDraggingItem();
|
||||
if (!DraggingItem.IsEmpty())
|
||||
if ((a_SlotNum == 4) && !DraggingItem.IsEmpty())
|
||||
{
|
||||
// Fuel slot
|
||||
switch (a_ClickAction)
|
||||
{
|
||||
super::Clicked(a_Player, a_SlotNum, a_ClickAction, a_ClickedItem);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (a_ClickAction)
|
||||
case caShiftLeftClick:
|
||||
case caShiftRightClick:
|
||||
{
|
||||
case caDblClick:
|
||||
super::ShiftClicked(a_Player, a_SlotNum, Slot);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
if (!BR->IsFuel(DraggingItem))
|
||||
{
|
||||
DblClicked(a_Player, a_SlotNum);
|
||||
// Deny placing a invalid item into the fuel slot
|
||||
return;
|
||||
}
|
||||
case caLeftClick:
|
||||
{
|
||||
DraggingItem = Slot;
|
||||
HandleBrewedItem(a_Player);
|
||||
Slot.Empty();
|
||||
break;
|
||||
}
|
||||
case caRightClick:
|
||||
{
|
||||
DraggingItem = Slot.CopyOne();
|
||||
DraggingItem.m_ItemCount = static_cast<char>(static_cast<float>(Slot.m_ItemCount) / 2.f + 0.5f);
|
||||
Slot.m_ItemCount -= DraggingItem.m_ItemCount;
|
||||
|
||||
if (Slot.m_ItemCount <= 0)
|
||||
{
|
||||
Slot.Empty();
|
||||
}
|
||||
HandleBrewedItem(a_Player);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
ASSERT(!"Unhandled click type!");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
SetSlot(a_SlotNum, a_Player, Slot);
|
||||
if (bAsync)
|
||||
{
|
||||
m_ParentWindow.BroadcastWholeWindow();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
super::Clicked(a_Player, a_SlotNum, a_ClickAction, a_ClickedItem);
|
||||
@ -2078,9 +2079,13 @@ void cSlotAreaBrewingstand::Clicked(cPlayer & a_Player, int a_SlotNum, eClickAct
|
||||
|
||||
|
||||
|
||||
void cSlotAreaBrewingstand::HandleBrewedItem(cPlayer & a_Player)
|
||||
void cSlotAreaBrewingstand::HandleBrewedItem(cPlayer & a_Player, const cItem & a_ClickedItem)
|
||||
{
|
||||
a_Player.AwardAchievement(achBrewPotion);
|
||||
// Award an achievement if the item is not a water bottle (is a real brewed potion)
|
||||
if (a_ClickedItem.m_ItemDamage > 0)
|
||||
{
|
||||
a_Player.AwardAchievement(achBrewPotion);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -479,7 +479,7 @@ protected:
|
||||
virtual void OnSlotChanged(cItemGrid * a_ItemGrid, int a_SlotNum) override;
|
||||
|
||||
/** Called after an item has been brewed to handle statistics etc. */
|
||||
void HandleBrewedItem(cPlayer & a_Player);
|
||||
void HandleBrewedItem(cPlayer & a_Player, const cItem & a_ClickedItem);
|
||||
} ;
|
||||
|
||||
|
||||
|
@ -205,6 +205,7 @@ void cNBTChunkSerializer::AddBrewingstandEntity(cBrewingstandEntity * a_Brewings
|
||||
AddItemGrid(a_Brewingstand->GetContents());
|
||||
m_Writer.EndList();
|
||||
m_Writer.AddShort("BrewTime", a_Brewingstand->GetTimeBrewed());
|
||||
m_Writer.AddShort("Fuel", a_Brewingstand->GetRemainingFuel());
|
||||
m_Writer.EndCompound();
|
||||
}
|
||||
|
||||
|
@ -944,6 +944,14 @@ cBlockEntity * cWSSAnvil::LoadBrewingstandFromNBT(const cParsedNBT & a_NBT, int
|
||||
|
||||
std::unique_ptr<cBrewingstandEntity> Brewingstand(new cBrewingstandEntity(a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, m_World));
|
||||
|
||||
// Fuel has to be loaded at first, because of slot events:
|
||||
int Fuel = a_NBT.FindChildByName(a_TagIdx, "Fuel");
|
||||
if (Fuel >= 0)
|
||||
{
|
||||
Int16 tb = a_NBT.GetShort(Fuel);
|
||||
Brewingstand->SetRemainingFuel(tb);
|
||||
}
|
||||
|
||||
// Load slots:
|
||||
for (int Child = a_NBT.GetFirstChild(Items); Child != -1; Child = a_NBT.GetNextSibling(Child))
|
||||
{
|
||||
@ -964,11 +972,11 @@ cBlockEntity * cWSSAnvil::LoadBrewingstandFromNBT(const cParsedNBT & a_NBT, int
|
||||
if (BrewTime >= 0)
|
||||
{
|
||||
Int16 tb = a_NBT.GetShort(BrewTime);
|
||||
Brewingstand->setTimeBrewed(tb);
|
||||
Brewingstand->SetTimeBrewed(tb);
|
||||
}
|
||||
|
||||
// Restart brewing:
|
||||
Brewingstand->GetRecipes();
|
||||
Brewingstand->LoadRecipes();
|
||||
Brewingstand->ContinueBrewing();
|
||||
return Brewingstand.release();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user