summaryrefslogtreecommitdiff
path: root/src/craftdef.cpp
diff options
context:
space:
mode:
authorPerttu Ahola <celeron55@gmail.com>2011-11-17 02:28:46 +0200
committerPerttu Ahola <celeron55@gmail.com>2011-11-29 19:13:48 +0200
commit9d5b458479a4eac14acb5af28f51ad23432264ab (patch)
tree76c90e2f88be617ca4fc8e1c0772f27207f8eacd /src/craftdef.cpp
parent8dd3622c6d3c85adbb293eacf61f76c1118c9255 (diff)
downloadminetest-9d5b458479a4eac14acb5af28f51ad23432264ab.tar.gz
minetest-9d5b458479a4eac14acb5af28f51ad23432264ab.tar.bz2
minetest-9d5b458479a4eac14acb5af28f51ad23432264ab.zip
Crafting definition in scripts
Diffstat (limited to 'src/craftdef.cpp')
-rw-r--r--src/craftdef.cpp229
1 files changed, 229 insertions, 0 deletions
diff --git a/src/craftdef.cpp b/src/craftdef.cpp
new file mode 100644
index 000000000..79761b857
--- /dev/null
+++ b/src/craftdef.cpp
@@ -0,0 +1,229 @@
+/*
+Minetest-c55
+Copyright (C) 2011 celeron55, Perttu Ahola <celeron55@gmail.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "craftdef.h"
+
+#include "irrlichttypes.h"
+#include "log.h"
+#include <sstream>
+#include "utility.h"
+#include "gamedef.h"
+#include "inventory.h"
+
+CraftPointerInput::~CraftPointerInput()
+{
+ for(u32 i=0; i<items.size(); i++)
+ delete items[i];
+}
+
+CraftPointerInput createPointerInput(const CraftInput &ci, IGameDef *gamedef)
+{
+ std::vector<InventoryItem*> items;
+ for(u32 i=0; i<ci.items.size(); i++){
+ InventoryItem *item = NULL;
+ if(ci.items[i] != ""){
+ std::istringstream iss(ci.items[i], std::ios::binary);
+ item = InventoryItem::deSerialize(iss, gamedef);
+ }
+ items.push_back(item);
+ }
+ return CraftPointerInput(ci.width, items);
+}
+
+CraftInput createInput(const CraftPointerInput &cpi)
+{
+ std::vector<std::string> items;
+ for(u32 i=0; i<cpi.items.size(); i++){
+ if(cpi.items[i] == NULL)
+ items.push_back("");
+ else{
+ std::ostringstream oss(std::ios::binary);
+ cpi.items[i]->serialize(oss);
+ items.push_back(oss.str());
+ }
+ }
+ return CraftInput(cpi.width, items);
+}
+
+std::string CraftInput::dump() const
+{
+ std::ostringstream os(std::ios::binary);
+ os<<"(width="<<width<<"){";
+ for(u32 i=0; i<items.size(); i++)
+ os<<"\""<<items[i]<<"\",";
+ os<<"}";
+ return os.str();
+}
+
+std::string CraftDefinition::dump() const
+{
+ std::ostringstream os(std::ios::binary);
+ os<<"{output=\""<<output<<"\", input={";
+ for(u32 i=0; i<input.items.size(); i++)
+ os<<"\""<<input.items[i]<<"\",";
+ os<<"}, (input.width="<<input.width<<")}";
+ return os.str();
+}
+
+void CraftDefinition::serialize(std::ostream &os) const
+{
+ writeU8(os, 0); // version
+ os<<serializeString(output);
+ writeU8(os, input.width);
+ writeU16(os, input.items.size());
+ for(u32 i=0; i<input.items.size(); i++)
+ os<<serializeString(input.items[i]);
+}
+
+void CraftDefinition::deSerialize(std::istream &is)
+{
+ int version = readU8(is);
+ if(version != 0) throw SerializationError(
+ "unsupported CraftDefinition version");
+ output = deSerializeString(is);
+ input.width = readU8(is);
+ u32 count = readU16(is);
+ for(u32 i=0; i<count; i++)
+ input.items.push_back(deSerializeString(is));
+}
+
+class CCraftDefManager: public IWritableCraftDefManager
+{
+public:
+ virtual ~CCraftDefManager()
+ {
+ clear();
+ }
+ virtual InventoryItem* getCraftResult(const CraftPointerInput &input_cpi,
+ IGameDef *gamedef) const
+ {
+ if(input_cpi.width > 3){
+ errorstream<<"getCraftResult: IGNORING ERROR: "
+ <<"input_cpi.width > 3"<<std::endl;
+ return NULL;
+ }
+ InventoryItem *input_items[9];
+ for(u32 y=0; y<3; y++)
+ for(u32 x=0; x<3; x++)
+ {
+ u32 i=y*3+x;
+ if(x >= input_cpi.width || y >= input_cpi.height())
+ input_items[i] = NULL;
+ else
+ input_items[i] = input_cpi.items[y*input_cpi.width+x];
+ }
+ for(core::list<CraftDefinition*>::ConstIterator
+ i = m_craft_definitions.begin();
+ i != m_craft_definitions.end(); i++)
+ {
+ CraftDefinition *def = *i;
+
+ infostream<<"Checking "<<createInput(input_cpi).dump()<<std::endl
+ <<" against "<<def->input.dump()
+ <<" (output=\""<<def->output<<"\")"<<std::endl;
+
+ CraftPointerInput spec_cpi = createPointerInput(def->input, gamedef);
+ if(spec_cpi.width > 3){
+ errorstream<<"getCraftResult: IGNORING ERROR: "
+ <<"spec_cpi.width > 3"<<std::endl;
+ continue;
+ }
+ InventoryItem *spec_items[9];
+ for(u32 y=0; y<3; y++)
+ for(u32 x=0; x<3; x++)
+ {
+ u32 i=y*3+x;
+ if(x >= spec_cpi.width || y >= spec_cpi.height())
+ spec_items[i] = NULL;
+ else
+ spec_items[i] = spec_cpi.items[y*spec_cpi.width+x];
+ infostream<<"spec_items["<<i<<"] = "<<spec_items[i]<<std::endl;
+ }
+
+ bool match = checkItemCombination(input_items, spec_items);
+
+ if(match){
+ std::istringstream iss(def->output, std::ios::binary);
+ return InventoryItem::deSerialize(iss, gamedef);
+ }
+ }
+ return NULL;
+ }
+ virtual void registerCraft(const CraftDefinition &def)
+ {
+ infostream<<"registerCraft: registering craft definition: "
+ <<def.dump()<<std::endl;
+ if(def.input.width > 3 || def.input.height() > 3){
+ errorstream<<"registerCraft: input size is larger than 3x3,"
+ <<" ignoring"<<std::endl;
+ return;
+ }
+ m_craft_definitions.push_back(new CraftDefinition(def));
+ }
+ virtual void clear()
+ {
+ for(core::list<CraftDefinition*>::Iterator
+ i = m_craft_definitions.begin();
+ i != m_craft_definitions.end(); i++){
+ delete *i;
+ }
+ m_craft_definitions.clear();
+ }
+ virtual void serialize(std::ostream &os)
+ {
+ writeU8(os, 0); // version
+ u16 count = m_craft_definitions.size();
+ writeU16(os, count);
+ for(core::list<CraftDefinition*>::Iterator
+ i = m_craft_definitions.begin();
+ i != m_craft_definitions.end(); i++){
+ CraftDefinition *def = *i;
+ // Serialize wrapped in a string
+ std::ostringstream tmp_os(std::ios::binary);
+ def->serialize(tmp_os);
+ os<<serializeString(tmp_os.str());
+ }
+ }
+ virtual void deSerialize(std::istream &is)
+ {
+ // Clear everything
+ clear();
+ // Deserialize
+ int version = readU8(is);
+ if(version != 0) throw SerializationError(
+ "unsupported CraftDefManager version");
+ u16 count = readU16(is);
+ for(u16 i=0; i<count; i++){
+ // Deserialize a string and grab a CraftDefinition from it
+ std::istringstream tmp_is(deSerializeString(is), std::ios::binary);
+ CraftDefinition def;
+ def.deSerialize(tmp_is);
+ // Register
+ registerCraft(def);
+ }
+ }
+private:
+ core::list<CraftDefinition*> m_craft_definitions;
+};
+
+IWritableCraftDefManager* createCraftDefManager()
+{
+ return new CCraftDefManager();
+}
+