[Recipe|SmeltingRecipe] Added. [BlockFurnace] Now supports SmeltingRecipe.
This commit is contained in:
parent
dbb6fb5736
commit
7df693e4af
@ -19,7 +19,7 @@
|
||||
|
||||
#include "Block.hpp"
|
||||
#include "Item.hpp"
|
||||
#include "CraftingRecipe.hpp"
|
||||
#include "Recipe.hpp"
|
||||
|
||||
class Registry {
|
||||
public:
|
||||
@ -33,6 +33,11 @@ class Registry {
|
||||
return *m_items.emplace_back(std::make_unique<T>(std::forward<Args>(args)...)).get();
|
||||
}
|
||||
|
||||
template<typename T, typename... Args>
|
||||
auto registerRecipe(Args &&...args) -> typename std::enable_if<std::is_base_of<Recipe, T>::value, Recipe&>::type {
|
||||
return *m_recipes.emplace_back(std::make_unique<T>(std::forward<Args>(args)...)).get();
|
||||
}
|
||||
|
||||
void registerBlocks();
|
||||
void registerItems();
|
||||
void registerRecipes();
|
||||
@ -40,7 +45,7 @@ class Registry {
|
||||
const Block &getBlock(std::size_t id) const { return *m_blocks.at(id).get(); }
|
||||
const Item &getItem(std::size_t id) const { return *m_items.at(id).get(); }
|
||||
|
||||
const CraftingRecipe *getRecipe(const Inventory &inventory) const;
|
||||
const Recipe *getRecipe(const Inventory &inventory) const;
|
||||
|
||||
static Registry &getInstance() { return *s_instance; }
|
||||
static void setInstance(Registry &instance) { s_instance = &instance; }
|
||||
@ -50,7 +55,7 @@ class Registry {
|
||||
|
||||
std::vector<std::unique_ptr<Block>> m_blocks;
|
||||
std::vector<std::unique_ptr<Item>> m_items;
|
||||
std::vector<CraftingRecipe> m_recipes;
|
||||
std::vector<std::unique_ptr<Recipe>> m_recipes;
|
||||
};
|
||||
|
||||
#endif // REGISTRY_HPP_
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
#include "InventoryWidget.hpp"
|
||||
|
||||
class CraftingRecipe;
|
||||
class Recipe;
|
||||
|
||||
class CraftingWidget : public Widget {
|
||||
public:
|
||||
@ -41,7 +41,7 @@ class CraftingWidget : public Widget {
|
||||
private:
|
||||
void draw(RenderTarget &target, RenderStates states) const override;
|
||||
|
||||
const CraftingRecipe *m_recipe = nullptr;
|
||||
const Recipe *m_recipe = nullptr;
|
||||
};
|
||||
|
||||
#endif // CRAFTINGWIDGET_HPP_
|
||||
|
@ -17,22 +17,19 @@
|
||||
#include <array>
|
||||
#include <map>
|
||||
|
||||
#include "Inventory.hpp"
|
||||
#include "Recipe.hpp"
|
||||
|
||||
class CraftingRecipe {
|
||||
class CraftingRecipe : public Recipe {
|
||||
public:
|
||||
CraftingRecipe(const std::vector<std::string> &pattern, const std::map<char, std::vector<u32>> &keys, const ItemStack &result, bool isShapeless = false);
|
||||
|
||||
bool isMatching(const Inventory &inventory) const;
|
||||
|
||||
const ItemStack &result() const { return m_result; }
|
||||
bool isMatching(const Inventory &inventory) const override;
|
||||
|
||||
private:
|
||||
bool checkMatch(const Inventory &inventory, int offsetX, int offsetY) const;
|
||||
|
||||
std::vector<std::string> m_pattern;
|
||||
std::map<char, std::vector<u32>> m_keys;
|
||||
ItemStack m_result;
|
||||
|
||||
bool m_isShapeless;
|
||||
};
|
||||
|
35
include/inventory/Recipe.hpp
Normal file
35
include/inventory/Recipe.hpp
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* =====================================================================================
|
||||
*
|
||||
* Filename: Recipe.hpp
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Created: 30/06/2018 03:01:44
|
||||
*
|
||||
* Author: Quentin Bazin, <quent42340@gmail.com>
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
#ifndef RECIPE_HPP_
|
||||
#define RECIPE_HPP_
|
||||
|
||||
#include "Inventory.hpp"
|
||||
|
||||
class Recipe {
|
||||
public:
|
||||
Recipe(const std::string &type, const ItemStack &result) : m_type(type), m_result(result) {}
|
||||
|
||||
virtual bool isMatching(const Inventory &inventory) const = 0;
|
||||
|
||||
const std::string &type() const { return m_type; }
|
||||
|
||||
const ItemStack &result() const { return m_result; }
|
||||
|
||||
protected:
|
||||
std::string m_type;
|
||||
|
||||
ItemStack m_result;
|
||||
};
|
||||
|
||||
#endif // RECIPE_HPP_
|
29
include/inventory/SmeltingRecipe.hpp
Normal file
29
include/inventory/SmeltingRecipe.hpp
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* =====================================================================================
|
||||
*
|
||||
* Filename: SmeltingRecipe.hpp
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Created: 30/06/2018 03:04:02
|
||||
*
|
||||
* Author: Quentin Bazin, <quent42340@gmail.com>
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
#ifndef SMELTINGRECIPE_HPP_
|
||||
#define SMELTINGRECIPE_HPP_
|
||||
|
||||
#include "Recipe.hpp"
|
||||
|
||||
class SmeltingRecipe : public Recipe {
|
||||
public:
|
||||
SmeltingRecipe(const ItemStack &input, const ItemStack &output);
|
||||
|
||||
bool isMatching(const Inventory &inventory) const override;
|
||||
|
||||
private:
|
||||
ItemStack m_input;
|
||||
};
|
||||
|
||||
#endif // SMELTINGRECIPE_HPP_
|
@ -21,6 +21,6 @@
|
||||
<item id="19" name="Stone Pickaxe" textureID="327" miningSpeed="4" harvestCapability="1" />
|
||||
<item id="20" name="Stone Shovel" textureID="328" miningSpeed="4" harvestCapability="2" />
|
||||
<item id="21" name="Stone Sword" textureID="329" />
|
||||
<item id="22" name="Coal" textureID="111" />
|
||||
<item id="22" name="Coal" textureID="111" burnTime="1600" />
|
||||
<item id="23" name="Iron Ingot" textureID="232" />
|
||||
</items>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<recipes>
|
||||
<recipe>
|
||||
<recipe type="craft">
|
||||
<pattern string="##" />
|
||||
<pattern string="#|" />
|
||||
<pattern string=" |" />
|
||||
@ -10,7 +10,7 @@
|
||||
<result item="17" amount="1" />
|
||||
</recipe>
|
||||
|
||||
<recipe>
|
||||
<recipe type="craft">
|
||||
<pattern string="##" />
|
||||
<pattern string=" |" />
|
||||
<pattern string=" |" />
|
||||
@ -21,7 +21,7 @@
|
||||
<result item="18" amount="1" />
|
||||
</recipe>
|
||||
|
||||
<recipe>
|
||||
<recipe type="craft">
|
||||
<pattern string="###" />
|
||||
<pattern string=" | " />
|
||||
<pattern string=" | " />
|
||||
@ -32,7 +32,7 @@
|
||||
<result item="19" amount="1" />
|
||||
</recipe>
|
||||
|
||||
<recipe>
|
||||
<recipe type="craft">
|
||||
<pattern string="#" />
|
||||
<pattern string="|" />
|
||||
<pattern string="|" />
|
||||
@ -43,7 +43,7 @@
|
||||
<result item="20" amount="1" />
|
||||
</recipe>
|
||||
|
||||
<recipe>
|
||||
<recipe type="craft">
|
||||
<pattern string="#" />
|
||||
<pattern string="#" />
|
||||
<pattern string="|" />
|
||||
@ -54,7 +54,7 @@
|
||||
<result item="21" amount="1" />
|
||||
</recipe>
|
||||
|
||||
<recipe>
|
||||
<recipe type="craft">
|
||||
<pattern string="#" />
|
||||
<pattern string="#" />
|
||||
|
||||
@ -63,7 +63,7 @@
|
||||
<result item="16" amount="4" />
|
||||
</recipe>
|
||||
|
||||
<recipe>
|
||||
<recipe type="craft">
|
||||
<pattern string="#" />
|
||||
|
||||
<key char="#" item="5" />
|
||||
@ -71,7 +71,7 @@
|
||||
<result item="11" amount="4" />
|
||||
</recipe>
|
||||
|
||||
<recipe>
|
||||
<recipe type="craft">
|
||||
<pattern string="##" />
|
||||
<pattern string="##" />
|
||||
|
||||
@ -80,7 +80,7 @@
|
||||
<result item="13" amount="1" />
|
||||
</recipe>
|
||||
|
||||
<recipe>
|
||||
<recipe type="craft">
|
||||
<pattern string="###" />
|
||||
<pattern string="# #" />
|
||||
<pattern string="###" />
|
||||
@ -89,4 +89,19 @@
|
||||
|
||||
<result item="14" amount="1" />
|
||||
</recipe>
|
||||
|
||||
<recipe type="smelt">
|
||||
<input id="15" amount="1" />
|
||||
<output id="23" amount="1" />
|
||||
</recipe>
|
||||
|
||||
<recipe type="smelt">
|
||||
<input id="2" amount="1" />
|
||||
<output id="6" amount="1" />
|
||||
</recipe>
|
||||
|
||||
<recipe type="smelt">
|
||||
<input id="7" amount="1" />
|
||||
<output id="9" amount="1" />
|
||||
</recipe>
|
||||
</recipes>
|
||||
|
@ -11,8 +11,10 @@
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
#include "CraftingRecipe.hpp"
|
||||
#include "ItemBlock.hpp"
|
||||
#include "Registry.hpp"
|
||||
#include "SmeltingRecipe.hpp"
|
||||
|
||||
#include "BlockFurnace.hpp"
|
||||
#include "BlockWater.hpp"
|
||||
@ -69,6 +71,12 @@ void Registry::registerItems() {
|
||||
unsigned int harvestCapability = 0;
|
||||
if (itemElement->QueryUnsignedAttribute("harvestCapability", &harvestCapability) == tinyxml2::XMLError::XML_SUCCESS)
|
||||
item.setHarvestCapability(harvestCapability);
|
||||
|
||||
unsigned int burnTime = 0;
|
||||
if (itemElement->QueryUnsignedAttribute("burnTime", &burnTime) == tinyxml2::XMLError::XML_SUCCESS) {
|
||||
item.setIsFuel(true);
|
||||
item.setBurnTime(burnTime);
|
||||
}
|
||||
}
|
||||
else {
|
||||
registerItem<ItemBlock>(id, id, name);
|
||||
@ -83,46 +91,62 @@ void Registry::registerRecipes() {
|
||||
|
||||
tinyxml2::XMLElement *recipeElement = doc.FirstChildElement("recipes").FirstChildElement("recipe").ToElement();
|
||||
while (recipeElement) {
|
||||
std::vector<std::string> pattern;
|
||||
std::map<char, std::vector<u32>> keys;
|
||||
ItemStack result;
|
||||
bool isShapeless = false;
|
||||
std::string type = recipeElement->Attribute("type");
|
||||
if (type == "craft") {
|
||||
std::vector<std::string> pattern;
|
||||
std::map<char, std::vector<u32>> keys;
|
||||
ItemStack result;
|
||||
bool isShapeless = false;
|
||||
|
||||
tinyxml2::XMLElement *patternElement = recipeElement->FirstChildElement("pattern");
|
||||
while (patternElement) {
|
||||
pattern.emplace_back(patternElement->Attribute("string"));
|
||||
patternElement = patternElement->NextSiblingElement("pattern");
|
||||
tinyxml2::XMLElement *patternElement = recipeElement->FirstChildElement("pattern");
|
||||
while (patternElement) {
|
||||
pattern.emplace_back(patternElement->Attribute("string"));
|
||||
patternElement = patternElement->NextSiblingElement("pattern");
|
||||
}
|
||||
|
||||
tinyxml2::XMLElement *keyElement = recipeElement->FirstChildElement("key");
|
||||
while (keyElement) {
|
||||
char ch = keyElement->Attribute("char")[0];
|
||||
u32 item = keyElement->UnsignedAttribute("item");
|
||||
|
||||
std::vector<u32> items;
|
||||
items.emplace_back(item);
|
||||
keys.emplace(ch, items);
|
||||
|
||||
keyElement = keyElement->NextSiblingElement("key");
|
||||
}
|
||||
|
||||
tinyxml2::XMLElement *resultElement = recipeElement->FirstChildElement("result");
|
||||
if (resultElement) {
|
||||
u16 item = resultElement->UnsignedAttribute("item");
|
||||
u16 amount = resultElement->UnsignedAttribute("amount");
|
||||
result = ItemStack{item, amount};
|
||||
}
|
||||
|
||||
registerRecipe<CraftingRecipe>(pattern, keys, result, isShapeless);
|
||||
}
|
||||
else if (type == "smelt") {
|
||||
tinyxml2::XMLElement *inputElement = recipeElement->FirstChildElement("input");
|
||||
u16 inputItem = inputElement->UnsignedAttribute("id");
|
||||
u16 inputAmount = inputElement->UnsignedAttribute("amount");
|
||||
ItemStack input{inputItem, inputAmount};
|
||||
|
||||
tinyxml2::XMLElement *keyElement = recipeElement->FirstChildElement("key");
|
||||
while (keyElement) {
|
||||
char ch = keyElement->Attribute("char")[0];
|
||||
u32 item = keyElement->UnsignedAttribute("item");
|
||||
tinyxml2::XMLElement *outputElement = recipeElement->FirstChildElement("output");
|
||||
u16 outputItem = outputElement->UnsignedAttribute("id");
|
||||
u16 outputAmount = outputElement->UnsignedAttribute("amount");
|
||||
ItemStack output{outputItem, outputAmount};
|
||||
|
||||
std::vector<u32> items;
|
||||
items.emplace_back(item);
|
||||
keys.emplace(ch, items);
|
||||
|
||||
keyElement = keyElement->NextSiblingElement("key");
|
||||
registerRecipe<SmeltingRecipe>(input, output);
|
||||
}
|
||||
|
||||
tinyxml2::XMLElement *resultElement = recipeElement->FirstChildElement("result");
|
||||
if (resultElement) {
|
||||
u16 item = resultElement->UnsignedAttribute("item");
|
||||
u16 amount = resultElement->UnsignedAttribute("amount");
|
||||
result = ItemStack{item, amount};
|
||||
}
|
||||
|
||||
m_recipes.emplace_back(pattern, keys, result, isShapeless);
|
||||
|
||||
recipeElement = recipeElement->NextSiblingElement("recipe");
|
||||
}
|
||||
}
|
||||
|
||||
const CraftingRecipe *Registry::getRecipe(const Inventory &inventory) const {
|
||||
for (const CraftingRecipe &recipe : m_recipes) {
|
||||
if (recipe.isMatching(inventory))
|
||||
return &recipe;
|
||||
const Recipe *Registry::getRecipe(const Inventory &inventory) const {
|
||||
for (auto &recipe : m_recipes) {
|
||||
if (recipe->isMatching(inventory))
|
||||
return recipe.get();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -43,8 +43,8 @@ void CraftingWidget::onMouseEvent(const SDL_Event &event, MouseItemWidget &mouse
|
||||
}
|
||||
|
||||
void CraftingWidget::update() {
|
||||
const CraftingRecipe *recipe = Registry::getInstance().getRecipe(m_craftingInventory);
|
||||
if (!m_recipe || m_recipe != recipe) {
|
||||
const Recipe *recipe = Registry::getInstance().getRecipe(m_craftingInventory);
|
||||
if (!m_recipe || (m_recipe != recipe && recipe->type() == "craft")) {
|
||||
m_recipe = recipe;
|
||||
|
||||
if (m_recipe)
|
||||
|
@ -42,7 +42,9 @@ void FurnaceWidget::onEvent(const SDL_Event &event) {
|
||||
|
||||
m_inputInventoryWidget.onMouseEvent(event, m_mouseItemWidget);
|
||||
m_outputInventoryWidget.onMouseEvent(event, m_mouseItemWidget);
|
||||
m_fuelInventoryWidget.onMouseEvent(event, m_mouseItemWidget);
|
||||
|
||||
if (!m_mouseItemWidget.stack().item().id() || m_mouseItemWidget.stack().item().isFuel())
|
||||
m_fuelInventoryWidget.onMouseEvent(event, m_mouseItemWidget);
|
||||
|
||||
m_mouseItemWidget.onEvent(event);
|
||||
}
|
||||
|
@ -20,10 +20,9 @@
|
||||
// - Pattern section | char[3][3]
|
||||
// - Key section | map<char, vector<ItemType>>
|
||||
// - Result section | ItemStack
|
||||
CraftingRecipe::CraftingRecipe(const std::vector<std::string> &pattern, const std::map<char, std::vector<u32>> &keys, const ItemStack &result, bool isShapeless) {
|
||||
CraftingRecipe::CraftingRecipe(const std::vector<std::string> &pattern, const std::map<char, std::vector<u32>> &keys, const ItemStack &result, bool isShapeless) : Recipe("craft", result) {
|
||||
m_pattern = pattern;
|
||||
m_keys = keys;
|
||||
m_result = result;
|
||||
|
||||
m_isShapeless = isShapeless;
|
||||
}
|
||||
|
24
source/inventory/SmeltingRecipe.cpp
Normal file
24
source/inventory/SmeltingRecipe.cpp
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* =====================================================================================
|
||||
*
|
||||
* Filename: SmeltingRecipe.cpp
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Created: 30/06/2018 03:04:30
|
||||
*
|
||||
* Author: Quentin Bazin, <quent42340@gmail.com>
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
#include "SmeltingRecipe.hpp"
|
||||
|
||||
SmeltingRecipe::SmeltingRecipe(const ItemStack &input, const ItemStack &output) : Recipe("smelt", output) {
|
||||
m_input = input;
|
||||
}
|
||||
|
||||
bool SmeltingRecipe::isMatching(const Inventory &inventory) const {
|
||||
return (inventory.getStack(0, 0).item().id() == m_input.item().id()
|
||||
&& inventory.getStack(0, 0).amount() >= m_input.amount());
|
||||
}
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "FurnaceWidget.hpp"
|
||||
#include "InventoryState.hpp"
|
||||
#include "Player.hpp"
|
||||
#include "Registry.hpp"
|
||||
#include "World.hpp"
|
||||
|
||||
BlockFurnace::BlockFurnace() : Block(BlockType::Furnace, 164) {
|
||||
@ -57,15 +58,19 @@ void BlockFurnace::onTick(const glm::ivec3 &blockPosition, Player &, Chunk &, Wo
|
||||
u16 currentBurnTime = (data->data >> 16) & 0xffff;
|
||||
u16 itemProgress = (data->data >> 32) & 0xffff;
|
||||
|
||||
if (ticksRemaining == 0 && fuelStack.amount() && inputStack.amount() && inputStack.item().id() == ItemType::IronOre) {
|
||||
const Recipe *recipe = Registry::getInstance().getRecipe(data->inventory);
|
||||
if (recipe && recipe->type() != "smelt")
|
||||
recipe = nullptr;
|
||||
|
||||
if (ticksRemaining == 0 && recipe && fuelStack.amount() && (!outputStack.item().id() || !outputStack.amount() || outputStack.item().id() == recipe->result().item().id())) {
|
||||
data->inventory.setStack(2, 0, fuelStack.item().id(), fuelStack.amount() - 1);
|
||||
ticksRemaining = fuelStack.item().burnTime();
|
||||
currentBurnTime = fuelStack.item().burnTime();
|
||||
world.setData(blockPosition.x, blockPosition.y, blockPosition.z, 1);
|
||||
}
|
||||
else if (ticksRemaining > 0 && (!outputStack.amount() || !outputStack.item().id() || outputStack.item().id() == ItemType::IronIngot)) { // FIXME
|
||||
else if (ticksRemaining > 0) {
|
||||
--ticksRemaining;
|
||||
if (inputStack.amount())
|
||||
if (recipe && (!outputStack.item().id() || !outputStack.amount() || outputStack.item().id() == recipe->result().item().id()))
|
||||
++itemProgress;
|
||||
else
|
||||
itemProgress = 0;
|
||||
@ -75,12 +80,10 @@ void BlockFurnace::onTick(const glm::ivec3 &blockPosition, Player &, Chunk &, Wo
|
||||
world.setData(blockPosition.x, blockPosition.y, blockPosition.z, 0);
|
||||
}
|
||||
|
||||
if (itemProgress >= 200) {
|
||||
if (itemProgress >= 200 && recipe) {
|
||||
itemProgress = 0;
|
||||
if (inputStack.item().id() == ItemType::IronOre && inputStack.amount()) {
|
||||
data->inventory.setStack(0, 0, inputStack.item().id(), inputStack.amount() - 1);
|
||||
data->inventory.setStack(1, 0, ItemType::IronIngot, outputStack.amount() + 1);
|
||||
}
|
||||
data->inventory.setStack(0, 0, (inputStack.amount() - 1 > 0) ? inputStack.item().id() : 0, inputStack.amount() - 1);
|
||||
data->inventory.setStack(1, 0, recipe->result().item().id(), outputStack.amount() + recipe->result().amount());
|
||||
}
|
||||
|
||||
data->data = ticksRemaining | (currentBurnTime << 16) | ((u32)itemProgress << 32);
|
||||
|
Loading…
x
Reference in New Issue
Block a user