2015-09-24 04:48:33 -04:00
|
|
|
|
|
|
|
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
|
|
|
|
|
|
|
|
#include "BrewingRecipes.h"
|
|
|
|
|
|
|
|
#include <fstream>
|
|
|
|
|
|
|
|
#define BREWING_RECIPE_FILE "brewing.txt"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cBrewingRecipes::cBrewingRecipes()
|
|
|
|
{
|
|
|
|
ReloadRecipes();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void cBrewingRecipes::ReloadRecipes(void)
|
|
|
|
{
|
|
|
|
ClearRecipes();
|
|
|
|
LOGD("Loading brewing recipes...");
|
|
|
|
|
|
|
|
std::ifstream f(BREWING_RECIPE_FILE, std::ios::in);
|
|
|
|
if (!f.good())
|
|
|
|
{
|
|
|
|
LOG("Could not open the brewing recipes file \"%s\". No brewing recipes are available.", BREWING_RECIPE_FILE);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int LineNum = 0;
|
|
|
|
AString ParsingLine;
|
|
|
|
|
|
|
|
while (std::getline(f, ParsingLine))
|
|
|
|
{
|
|
|
|
LineNum++;
|
|
|
|
// Remove comments from the line:
|
|
|
|
size_t FirstCommentSymbol = ParsingLine.find('#');
|
|
|
|
if (FirstCommentSymbol != AString::npos)
|
|
|
|
{
|
2017-05-28 14:08:23 -04:00
|
|
|
ParsingLine.erase(FirstCommentSymbol);
|
2015-09-24 04:48:33 -04:00
|
|
|
}
|
|
|
|
|
2019-06-11 08:39:44 -04:00
|
|
|
if (IsOnlyWhitespace(ParsingLine))
|
2015-09-24 04:48:33 -04:00
|
|
|
{
|
2019-06-11 08:39:44 -04:00
|
|
|
// Ignore empty and whitespace only lines
|
2015-09-24 04:48:33 -04:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
AddRecipeFromLine(ParsingLine, LineNum);
|
|
|
|
} // while (getline(ParsingLine))
|
|
|
|
|
2018-01-03 12:41:16 -05:00
|
|
|
LOG("Loaded %zu brewing recipes", m_Recipes.size());
|
2015-09-24 04:48:33 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-05-28 14:08:23 -04:00
|
|
|
void cBrewingRecipes::AddRecipeFromLine(AString a_Line, unsigned int a_LineNum)
|
2015-09-24 04:48:33 -04:00
|
|
|
{
|
2017-05-28 14:08:23 -04:00
|
|
|
a_Line.erase(std::remove_if(a_Line.begin(), a_Line.end(), isspace), a_Line.end());
|
2015-09-24 04:48:33 -04:00
|
|
|
|
2020-08-01 14:18:03 -04:00
|
|
|
auto Recipe = std::make_unique<cRecipe>();
|
2015-09-24 04:48:33 -04:00
|
|
|
|
2017-05-28 14:08:23 -04:00
|
|
|
const AStringVector & InputAndIngredient = StringSplit(a_Line, "+");
|
2015-09-24 04:48:33 -04:00
|
|
|
|
|
|
|
if (InputAndIngredient.size() != 2)
|
|
|
|
{
|
|
|
|
LOGWARNING("brewing.txt: line %d: A line with '+' was expected", a_LineNum);
|
|
|
|
LOGINFO("Offending line: \"%s\"", a_Line.c_str());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-05-14 18:15:35 -04:00
|
|
|
const AStringVector & IngredientAndOutput = StringSplit(InputAndIngredient[1], "=");
|
2015-09-24 04:48:33 -04:00
|
|
|
if (IngredientAndOutput.size() != 2)
|
|
|
|
{
|
|
|
|
LOGWARNING("brewing.txt: line %d: A line with '=' was expected", a_LineNum);
|
|
|
|
LOGINFO("Offending line: \"%s\"", a_Line.c_str());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-05-28 14:08:23 -04:00
|
|
|
if (!ParseItem(IngredientAndOutput[0], Recipe->Ingredient))
|
2015-09-24 04:48:33 -04:00
|
|
|
{
|
|
|
|
LOGWARNING("brewing.txt: Parsing of the item didn't worked.");
|
|
|
|
LOGINFO("Offending line: \"%s\"", a_Line.c_str());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-05-28 14:08:23 -04:00
|
|
|
if (!StringToInteger<short>(InputAndIngredient[0], Recipe->Input.m_ItemDamage))
|
2015-09-24 04:48:33 -04:00
|
|
|
{
|
|
|
|
LOGWARNING("brewing.txt: line %d: Cannot parse the damage value for the input item\"%s\".", a_LineNum, InputAndIngredient[0].c_str());
|
|
|
|
LOGINFO("Offending line: \"%s\"", a_Line.c_str());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-05-28 14:08:23 -04:00
|
|
|
if (!StringToInteger<short>(IngredientAndOutput[1], Recipe->Output.m_ItemDamage))
|
2015-09-24 04:48:33 -04:00
|
|
|
{
|
|
|
|
LOGWARNING("brewing.txt: line %d: Cannot parse the damage value for the output item\"%s\".", a_LineNum, IngredientAndOutput[1].c_str());
|
|
|
|
LOGINFO("Offending line: \"%s\"", a_Line.c_str());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-05-28 14:08:23 -04:00
|
|
|
m_Recipes.push_back(std::move(Recipe));
|
2015-09-24 04:48:33 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool cBrewingRecipes::ParseItem(const AString & a_String, cItem & a_Item)
|
|
|
|
{
|
|
|
|
return StringToItem(a_String, a_Item);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void cBrewingRecipes::ClearRecipes(void)
|
|
|
|
{
|
2017-05-28 14:08:23 -04:00
|
|
|
m_Recipes.clear();
|
2015-09-24 04:48:33 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const cBrewingRecipes::cRecipe * cBrewingRecipes::GetRecipeFrom(const cItem & a_Input, const cItem & a_Ingredient) const
|
|
|
|
{
|
2017-05-28 14:08:23 -04:00
|
|
|
for (const auto & Recipe : m_Recipes)
|
2015-09-24 04:48:33 -04:00
|
|
|
{
|
2017-05-28 14:08:23 -04:00
|
|
|
if ((Recipe->Input.IsEqual(a_Input)) && (Recipe->Ingredient.IsEqual(a_Ingredient)))
|
2015-09-24 04:48:33 -04:00
|
|
|
{
|
|
|
|
return Recipe.get();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check for gunpowder
|
|
|
|
if (a_Ingredient.m_ItemType == E_ITEM_GUNPOWDER)
|
|
|
|
{
|
|
|
|
if (a_Input.m_ItemDamage & 0x2000)
|
|
|
|
{
|
|
|
|
// Create new recipe and add it to list
|
2020-08-01 14:18:03 -04:00
|
|
|
auto Recipe = std::make_unique<cRecipe>();
|
2017-05-28 14:08:23 -04:00
|
|
|
|
|
|
|
Recipe->Input.m_ItemType = a_Input.m_ItemDamage;
|
|
|
|
Recipe->Output.m_ItemDamage = a_Input.m_ItemDamage + 8192;
|
|
|
|
Recipe->Ingredient.m_ItemType = E_ITEM_GUNPOWDER;
|
|
|
|
|
|
|
|
auto RecipePtr = Recipe.get();
|
|
|
|
m_Recipes.push_back(std::move(Recipe));
|
|
|
|
return RecipePtr;
|
2015-09-24 04:48:33 -04:00
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check for splash potion
|
|
|
|
if (a_Input.m_ItemDamage & 0x4000)
|
|
|
|
{
|
|
|
|
// Search for the drinkable potion, the ingredients are the same
|
|
|
|
short SplashItemDamage = a_Input.m_ItemDamage - 8192;
|
|
|
|
|
2017-05-28 14:08:23 -04:00
|
|
|
auto FoundRecipe = std::find_if(m_Recipes.cbegin(), m_Recipes.cend(), [&](const std::unique_ptr<cRecipe>& a_Recipe)
|
2015-09-24 04:48:33 -04:00
|
|
|
{
|
2017-05-28 14:08:23 -04:00
|
|
|
return (
|
|
|
|
(a_Recipe->Input.m_ItemDamage == SplashItemDamage) &&
|
|
|
|
(a_Recipe->Ingredient.IsEqual(a_Ingredient))
|
|
|
|
);
|
|
|
|
});
|
2015-09-24 04:48:33 -04:00
|
|
|
|
2017-05-28 14:08:23 -04:00
|
|
|
if (FoundRecipe == m_Recipes.cend())
|
2015-09-24 04:48:33 -04:00
|
|
|
{
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create new recipe and add it to list
|
2020-08-01 14:18:03 -04:00
|
|
|
auto Recipe = std::make_unique<cRecipe>();
|
2017-05-28 14:08:23 -04:00
|
|
|
|
|
|
|
Recipe->Input.m_ItemDamage = a_Input.m_ItemDamage;
|
|
|
|
Recipe->Output.m_ItemDamage = (*FoundRecipe)->Output.m_ItemDamage + 8192;
|
|
|
|
Recipe->Ingredient.m_ItemType = (*FoundRecipe)->Ingredient.m_ItemType;
|
|
|
|
|
|
|
|
auto RecipePtr = Recipe.get();
|
|
|
|
m_Recipes.push_back(std::move(Recipe));
|
|
|
|
return RecipePtr;
|
2015-09-24 04:48:33 -04:00
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool cBrewingRecipes::IsIngredient(const cItem & a_Ingredient) const
|
|
|
|
{
|
|
|
|
// Check for gunpowder
|
|
|
|
if (a_Ingredient.m_ItemType == E_ITEM_GUNPOWDER)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-05-28 14:08:23 -04:00
|
|
|
for (const auto & Recipe : m_Recipes)
|
2015-09-24 04:48:33 -04:00
|
|
|
{
|
2017-05-28 14:08:23 -04:00
|
|
|
if (Recipe->Ingredient.IsEqual(a_Ingredient))
|
2015-09-24 04:48:33 -04:00
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool cBrewingRecipes::IsBottle(const cItem & a_Item) const
|
|
|
|
{
|
|
|
|
return (a_Item.m_ItemType == E_ITEM_POTION);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-05-05 05:58:21 -04:00
|
|
|
bool cBrewingRecipes::IsFuel(const cItem & a_Item) const
|
|
|
|
{
|
|
|
|
return (a_Item.m_ItemType == E_ITEM_BLAZE_POWDER);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|