aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/mods/default/init.lua23
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/client.cpp5
-rw-r--r--src/client.h2
-rw-r--r--src/craftdef.cpp229
-rw-r--r--src/craftdef.h111
-rw-r--r--src/gamedef.h3
-rw-r--r--src/inventory.cpp80
-rw-r--r--src/inventory.h105
-rw-r--r--src/scriptapi.cpp97
-rw-r--r--src/server.cpp27
-rw-r--r--src/server.h6
12 files changed, 633 insertions, 56 deletions
diff --git a/data/mods/default/init.lua b/data/mods/default/init.lua
index c2e1d3300..a0b381fb1 100644
--- a/data/mods/default/init.lua
+++ b/data/mods/default/init.lua
@@ -321,6 +321,29 @@ minetest.register_node("somenode", {
inventory_image = "treeprop.png"
})
+minetest.register_node("TNT", {
+ tile_images = {"tnt_top.png", "tnt_bottom.png", "tnt_side.png", "tnt_side.png", "tnt_side.png", "tnt_side.png"},
+ inventory_image = "tnt_side.png"
+})
+
+minetest.register_craft({
+ output = 'ToolItem "STPick" 4',
+ recipe = {
+ {'NodeItem "cobble" 1', 'NodeItem "cobble" 1', 'NodeItem "cobble" 1'},
+ {'', 'CraftItem "Stick"', ''},
+ {'', 'CraftItem "Stick"', ''},
+ }
+})
+
+minetest.register_craft({
+ output = 'NodeItem "TNT" 4',
+ recipe = {
+ {'NodeItem "wood" 1'},
+ {'CraftItem "lump_of_coal" 1'},
+ {'NodeItem "wood" 1'}
+ }
+})
+
local TNT = {
-- Maybe handle gravity and collision this way? dunno
physical = true,
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 9c6419fcb..9d699e976 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -94,6 +94,7 @@ configure_file(
)
set(common_SRCS
+ craftdef.cpp
nameidmapping.cpp
tooldef.cpp
nodedef.cpp
diff --git a/src/client.cpp b/src/client.cpp
index 716dac931..2326ff35d 100644
--- a/src/client.cpp
+++ b/src/client.cpp
@@ -2317,6 +2317,11 @@ INodeDefManager* Client::getNodeDefManager()
{
return m_nodedef;
}
+ICraftDefManager* Client::getCraftDefManager()
+{
+ return NULL;
+ //return m_craftdef;
+}
ITextureSource* Client::getTextureSource()
{
return m_tsrc;
diff --git a/src/client.h b/src/client.h
index cd36c4858..e5368b17a 100644
--- a/src/client.h
+++ b/src/client.h
@@ -36,6 +36,7 @@ class IGameDef;
class IWritableTextureSource;
class IWritableToolDefManager;
class IWritableNodeDefManager;
+//class IWritableCraftDefManager;
class ClientNotReadyException : public BaseException
{
@@ -326,6 +327,7 @@ public:
// IGameDef interface
virtual IToolDefManager* getToolDefManager();
virtual INodeDefManager* getNodeDefManager();
+ virtual ICraftDefManager* getCraftDefManager();
virtual ITextureSource* getTextureSource();
virtual u16 allocateUnknownNodeId(const std::string &name);
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();
+}
+
diff --git a/src/craftdef.h b/src/craftdef.h
new file mode 100644
index 000000000..cfd58ad10
--- /dev/null
+++ b/src/craftdef.h
@@ -0,0 +1,111 @@
+/*
+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.
+*/
+
+#ifndef CRAFTDEF_HEADER
+#define CRAFTDEF_HEADER
+
+#include <string>
+#include <iostream>
+#include <vector>
+class IGameDef;
+class InventoryItem;
+
+struct CraftPointerInput
+{
+ unsigned int width;
+ std::vector<InventoryItem*> items;
+
+ CraftPointerInput(unsigned int width_, const std::vector<InventoryItem*> &items_):
+ width(width_),
+ items(items_)
+ {}
+ CraftPointerInput():
+ width(0)
+ {}
+ ~CraftPointerInput();
+ unsigned int height() const{
+ return (items.size() + width - 1) / width;
+ }
+};
+
+struct CraftInput
+{
+ unsigned int width;
+ std::vector<std::string> items;
+
+ CraftInput(unsigned int width_, const std::vector<std::string> &items_):
+ width(width_),
+ items(items_)
+ {}
+ CraftInput():
+ width(0)
+ {}
+ unsigned int height() const{
+ return (items.size() + width - 1) / width;
+ }
+ std::string dump() const;
+};
+
+struct CraftDefinition
+{
+ std::string output;
+ CraftInput input;
+
+ CraftDefinition(){}
+ CraftDefinition(const std::string &output_, unsigned int width_,
+ const std::vector<std::string> &input_):
+ output(output_),
+ input(width_, input_)
+ {}
+
+ std::string dump() const;
+ void serialize(std::ostream &os) const;
+ void deSerialize(std::istream &is);
+};
+
+class ICraftDefManager
+{
+public:
+ ICraftDefManager(){}
+ virtual ~ICraftDefManager(){}
+ virtual InventoryItem* getCraftResult(const CraftPointerInput &input_cpi,
+ IGameDef *gamedef) const=0;
+
+ virtual void serialize(std::ostream &os)=0;
+};
+
+class IWritableCraftDefManager : public ICraftDefManager
+{
+public:
+ IWritableCraftDefManager(){}
+ virtual ~IWritableCraftDefManager(){}
+ virtual InventoryItem* getCraftResult(const CraftPointerInput &input_cpi,
+ IGameDef *gamedef) const=0;
+
+ virtual void registerCraft(const CraftDefinition &def)=0;
+ virtual void clear()=0;
+
+ virtual void serialize(std::ostream &os)=0;
+ virtual void deSerialize(std::istream &is)=0;
+};
+
+IWritableCraftDefManager* createCraftDefManager();
+
+#endif
+
diff --git a/src/gamedef.h b/src/gamedef.h
index 6708f887d..bca27a21a 100644
--- a/src/gamedef.h
+++ b/src/gamedef.h
@@ -24,6 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
class IToolDefManager;
class INodeDefManager;
+class ICraftDefManager;
//class IItemDefManager; //TODO
// Mineral too?
class ITextureSource;
@@ -40,6 +41,7 @@ public:
// Thus, first they are set up and then they are only read.
virtual IToolDefManager* getToolDefManager()=0;
virtual INodeDefManager* getNodeDefManager()=0;
+ virtual ICraftDefManager* getCraftDefManager()=0;
//virtual IItemDefManager* getItemDefManager()=0;
// This is always thread-safe, but referencing the irrlicht texture
@@ -52,6 +54,7 @@ public:
// Shorthands
IToolDefManager* tdef(){return getToolDefManager();}
INodeDefManager* ndef(){return getNodeDefManager();}
+ ICraftDefManager* cdef(){return getCraftDefManager();}
ITextureSource* tsrc(){return getTextureSource();}
};
diff --git a/src/inventory.cpp b/src/inventory.cpp
index 386868663..c7dd2a87b 100644
--- a/src/inventory.cpp
+++ b/src/inventory.cpp
@@ -1153,5 +1153,85 @@ bool checkItemCombination(InventoryItem const * const *items, const ItemSpec *sp
return true;
}
+
+bool checkItemCombination(const InventoryItem * const * items,
+ const InventoryItem * const * specs)
+{
+ u16 items_min_x = 100;
+ u16 items_max_x = 100;
+ u16 items_min_y = 100;
+ u16 items_max_y = 100;
+ for(u16 y=0; y<3; y++)
+ for(u16 x=0; x<3; x++)
+ {
+ if(items[y*3 + x] == NULL)
+ continue;
+ if(items_min_x == 100 || x < items_min_x)
+ items_min_x = x;
+ if(items_min_y == 100 || y < items_min_y)
+ items_min_y = y;
+ if(items_max_x == 100 || x > items_max_x)
+ items_max_x = x;
+ if(items_max_y == 100 || y > items_max_y)
+ items_max_y = y;
+ }
+ // No items at all, just return false
+ if(items_min_x == 100)
+ return false;
+ u16 items_w = items_max_x - items_min_x + 1;
+ u16 items_h = items_max_y - items_min_y + 1;
+
+ u16 specs_min_x = 100;
+ u16 specs_max_x = 100;
+ u16 specs_min_y = 100;
+ u16 specs_max_y = 100;
+ for(u16 y=0; y<3; y++)
+ for(u16 x=0; x<3; x++)
+ {
+ if(specs[y*3 + x] == NULL)
+ continue;
+ if(specs_min_x == 100 || x < specs_min_x)
+ specs_min_x = x;
+ if(specs_min_y == 100 || y < specs_min_y)
+ specs_min_y = y;
+ if(specs_max_x == 100 || x > specs_max_x)
+ specs_max_x = x;
+ if(specs_max_y == 100 || y > specs_max_y)
+ specs_max_y = y;
+ }
+ // No specs at all, just return false
+ if(specs_min_x == 100)
+ return false;
+
+ u16 specs_w = specs_max_x - specs_min_x + 1;
+ u16 specs_h = specs_max_y - specs_min_y + 1;
+
+ // Different sizes
+ if(items_w != specs_w || items_h != specs_h)
+ return false;
+
+ for(u16 y=0; y<specs_h; y++)
+ for(u16 x=0; x<specs_w; x++)
+ {
+ u16 items_x = items_min_x + x;
+ u16 items_y = items_min_y + y;
+ u16 specs_x = specs_min_x + x;
+ u16 specs_y = specs_min_y + y;
+ const InventoryItem *item = items[items_y * 3 + items_x];
+ const InventoryItem *spec = specs[specs_y * 3 + specs_x];
+
+ if(item == NULL && spec == NULL)
+ continue;
+ if(item == NULL && spec != NULL)
+ return false;
+ if(item != NULL && spec == NULL)
+ return false;
+ if(!spec->isSubsetOf(item))
+ return false;
+ }
+
+ return true;
+}
+
//END
diff --git a/src/inventory.h b/src/inventory.h
index 9c6a967a2..d6049f52f 100644
--- a/src/inventory.h
+++ b/src/inventory.h
@@ -70,25 +70,26 @@ public:
Quantity methods
*/
- // Shall return true if the item can be add()ed to the other
+ // Return true if the item can be add()ed to the other
virtual bool addableTo(const InventoryItem *other) const
- {
- return false;
- }
+ { return false; }
+ // Return true if the other item contains this item
+ virtual bool isSubsetOf(const InventoryItem *other) const
+ { return false; }
+ // Remove the other item from this one if possible and return true
+ // Return false if not possible
+ virtual bool removeOther(const InventoryItem *other)
+ { return false; }
u16 getCount() const
- {
- return m_count;
- }
+ { return m_count; }
void setCount(u16 count)
- {
- m_count = count;
- }
+ { m_count = count; }
+
// This should return something else for stackable items
virtual u16 freeSpace() const
- {
- return 0;
- }
+ { return 0; }
+
void add(u16 count)
{
assert(m_count + count <= QUANTITY_ITEM_MAX_COUNT);
@@ -168,6 +169,24 @@ public:
return false;
return true;
}
+ virtual bool isSubsetOf(const InventoryItem *other) const
+ {
+ if(std::string(other->getName()) != "MaterialItem")
+ return false;
+ MaterialItem *m = (MaterialItem*)other;
+ if(m->m_nodename != m_nodename)
+ return false;
+ return m_count <= m->m_count;
+ }
+ virtual bool removeOther(const InventoryItem *other)
+ {
+ if(!other->isSubsetOf(this))
+ return false;
+ MaterialItem *m = (MaterialItem*)other;
+ m_count += m->m_count;
+ return true;
+ }
+
u16 freeSpace() const
{
if(m_count > QUANTITY_ITEM_MAX_COUNT)
@@ -245,6 +264,24 @@ public:
return false;
return true;
}
+ virtual bool isSubsetOf(const InventoryItem *other) const
+ {
+ if(std::string(other->getName()) != "CraftItem")
+ return false;
+ CraftItem *m = (CraftItem*)other;
+ if(m->m_subname != m_subname)
+ return false;
+ return m_count <= m->m_count;
+ }
+ virtual bool removeOther(const InventoryItem *other)
+ {
+ if(!other->isSubsetOf(this))
+ return false;
+ CraftItem *m = (CraftItem*)other;
+ m_count += m->m_count;
+ return true;
+ }
+
u16 freeSpace() const
{
if(m_count > QUANTITY_ITEM_MAX_COUNT)
@@ -312,23 +349,26 @@ public:
std::string getText()
{
return "";
-
- /*std::ostringstream os;
- u16 f = 4;
- u16 d = 65535/f;
- u16 i;
- for(i=0; i<(65535-m_wear)/d; i++)
- os<<'X';
- for(; i<f; i++)
- os<<'-';
- return os.str();*/
-
- /*std::ostringstream os;
- os<<m_toolname;
- os<<" ";
- os<<(m_wear/655);
- return os.str();*/
}
+
+ virtual bool isSubsetOf(const InventoryItem *other) const
+ {
+ if(std::string(other->getName()) != "ToolItem")
+ return false;
+ ToolItem *m = (ToolItem*)other;
+ if(m->m_toolname != m_toolname)
+ return false;
+ return m_wear <= m->m_wear;
+ }
+ virtual bool removeOther(const InventoryItem *other)
+ {
+ if(!other->isSubsetOf(this))
+ return false;
+ ToolItem *m = (ToolItem*)other;
+ m_wear -= m->m_wear;
+ return true;
+ }
+
/*
Special methods
*/
@@ -591,5 +631,12 @@ struct ItemSpec
*/
bool checkItemCombination(const InventoryItem * const*items, const ItemSpec *specs);
+/*
+ items: a pointer to an array of 9 pointers to items
+ specs: a pointer to an array of 9 pointers to items
+*/
+bool checkItemCombination(const InventoryItem * const * items,
+ const InventoryItem * const * specs);
+
#endif
diff --git a/src/scriptapi.cpp b/src/scriptapi.cpp
index b37c50bc0..cd501060f 100644
--- a/src/scriptapi.cpp
+++ b/src/scriptapi.cpp
@@ -37,6 +37,7 @@ extern "C" {
#include "content_sao.h" // For LuaEntitySAO
#include "tooldef.h"
#include "nodedef.h"
+#include "craftdef.h"
/*
TODO:
@@ -205,26 +206,6 @@ static int l_register_globalstep(lua_State *L)
return 0; /* number of results */
}
-#if 0
-// Clear all registered tools
-// deregister_tools()
-static int l_deregister_tools(lua_State *L)
-{
- infostream<<"deregister_tools"<<std::endl;
-
- // Get server from registry
- lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
- Server *server = (Server*)lua_touserdata(L, -1);
- // And get the writable tool definition manager from the server
- IWritableToolDefManager *tooldef =
- server->getWritableToolDefManager();
-
- tooldef->clear();
-
- return 0; /* number of results */
-}
-#endif
-
// register_tool(name, {lots of stuff})
static int l_register_tool(lua_State *L)
{
@@ -336,16 +317,90 @@ static int l_register_node(lua_State *L)
f.tname_inventory = lua_tostring(L, -1);
lua_pop(L, 1);
+ // TODO: Replace with actual parameter reading
+ // Temporarily set some sane parameters to allow digging
+ f.material.diggability = DIGGABLE_NORMAL;
+ f.material.weight = 0;
+ f.material.crackiness = 0;
+ f.material.crumbliness = 0;
+ f.material.cuttability = 0;
+
nodedef->set(name, f);
return 0; /* number of results */
}
+// register_craft({output=item, recipe={{item00,item10},{item01,item11}})
+static int l_register_craft(lua_State *L)
+{
+ infostream<<"register_craft"<<std::endl;
+ luaL_checktype(L, 1, LUA_TTABLE);
+ int table0 = 1;
+
+ // Get server from registry
+ lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
+ Server *server = (Server*)lua_touserdata(L, -1);
+ // And get the writable craft definition manager from the server
+ IWritableCraftDefManager *craftdef =
+ server->getWritableCraftDefManager();
+
+ std::string output;
+ int width = 0;
+ std::vector<std::string> input;
+
+ lua_getfield(L, table0, "output");
+ luaL_checktype(L, -1, LUA_TSTRING);
+ if(lua_isstring(L, -1))
+ output = lua_tostring(L, -1);
+ lua_pop(L, 1);
+
+ lua_getfield(L, table0, "recipe");
+ luaL_checktype(L, -1, LUA_TTABLE);
+ if(lua_istable(L, -1)){
+ int table1 = lua_gettop(L);
+ lua_pushnil(L);
+ int rowcount = 0;
+ while(lua_next(L, table1) != 0){
+ int colcount = 0;
+ // key at index -2 and value at index -1
+ luaL_checktype(L, -1, LUA_TTABLE);
+ if(lua_istable(L, -1)){
+ int table2 = lua_gettop(L);
+ lua_pushnil(L);
+ while(lua_next(L, table2) != 0){
+ // key at index -2 and value at index -1
+ luaL_checktype(L, -1, LUA_TSTRING);
+ input.push_back(lua_tostring(L, -1));
+ // removes value, keeps key for next iteration
+ lua_pop(L, 1);
+ colcount++;
+ }
+ }
+ if(rowcount == 0){
+ width = colcount;
+ } else {
+ if(colcount != width){
+ script_error(L, "error: %s\n", "Invalid crafting recipe");
+ }
+ }
+ // removes value, keeps key for next iteration
+ lua_pop(L, 1);
+ rowcount++;
+ }
+ }
+ lua_pop(L, 1);
+
+ CraftDefinition def(output, width, input);
+ craftdef->registerCraft(def);
+
+ return 0; /* number of results */
+}
+
static const struct luaL_Reg minetest_f [] = {
{"register_entity", l_register_entity},
{"register_globalstep", l_register_globalstep},
- //{"deregister_tools", l_deregister_tools},
{"register_tool", l_register_tool},
{"register_node", l_register_node},
+ {"register_craft", l_register_craft},
{NULL, NULL}
};
diff --git a/src/server.cpp b/src/server.cpp
index c01b5050d..894c3d362 100644
--- a/src/server.cpp
+++ b/src/server.cpp
@@ -43,6 +43,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "scriptapi.h"
#include "nodedef.h"
#include "tooldef.h"
+#include "craftdef.h"
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
@@ -988,6 +989,7 @@ Server::Server(
m_lua(NULL),
m_toolmgr(createToolDefManager()),
m_nodedef(createNodeDefManager()),
+ m_craftdef(createCraftDefManager()),
m_thread(this),
m_emergethread(this),
m_time_counter(0),
@@ -4332,14 +4334,19 @@ void Server::UpdateCrafting(u16 peer_id)
}
if(clist && rlist && player->craftresult_is_preview)
{
- InventoryItem *items[9];
- for(u16 i=0; i<9; i++)
- {
- items[i] = clist->getItem(i);
+ // Get result of crafting grid
+
+ std::vector<InventoryItem*> items;
+ for(u16 i=0; i<9; i++){
+ if(clist->getItem(i) == NULL)
+ items.push_back(NULL);
+ else
+ items.push_back(clist->getItem(i)->clone());
}
+ CraftPointerInput cpi(3, items);
- // Get result of crafting grid
- InventoryItem *result = craft_get_result(items, this);
+ InventoryItem *result = m_craftdef->getCraftResult(cpi, this);
+ //InventoryItem *result = craft_get_result(items, this);
if(result)
rlist->addItem(result);
}
@@ -4424,6 +4431,10 @@ INodeDefManager* Server::getNodeDefManager()
{
return m_nodedef;
}
+ICraftDefManager* Server::getCraftDefManager()
+{
+ return m_craftdef;
+}
ITextureSource* Server::getTextureSource()
{
return NULL;
@@ -4441,6 +4452,10 @@ IWritableNodeDefManager* Server::getWritableNodeDefManager()
{
return m_nodedef;
}
+IWritableCraftDefManager* Server::getWritableCraftDefManager()
+{
+ return m_craftdef;
+}
v3f findSpawnPos(ServerMap &map)
{
diff --git a/src/server.h b/src/server.h
index ff0abccc4..7620f5341 100644
--- a/src/server.h
+++ b/src/server.h
@@ -35,6 +35,7 @@ struct LuaState;
typedef struct lua_State lua_State;
class IWritableToolDefManager;
class IWritableNodeDefManager;
+class IWritableCraftDefManager;
/*
Some random functions
@@ -490,11 +491,13 @@ public:
// Under envlock
virtual IToolDefManager* getToolDefManager();
virtual INodeDefManager* getNodeDefManager();
+ virtual ICraftDefManager* getCraftDefManager();
virtual ITextureSource* getTextureSource();
virtual u16 allocateUnknownNodeId(const std::string &name);
IWritableToolDefManager* getWritableToolDefManager();
IWritableNodeDefManager* getWritableNodeDefManager();
+ IWritableCraftDefManager* getWritableCraftDefManager();
private:
@@ -635,6 +638,9 @@ private:
// Node definition manager
IWritableNodeDefManager *m_nodedef;
+ // Craft definition manager
+ IWritableCraftDefManager *m_craftdef;
+
/*
Threads
*/