mirror of
https://github.com/minetest/minetest.git
synced 2024-08-19 21:14:15 +02:00
Crafting definition in scripts
This commit is contained in:
parent
8dd3622c6d
commit
9d5b458479
@ -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,
|
||||
|
@ -94,6 +94,7 @@ configure_file(
|
||||
)
|
||||
|
||||
set(common_SRCS
|
||||
craftdef.cpp
|
||||
nameidmapping.cpp
|
||||
tooldef.cpp
|
||||
nodedef.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;
|
||||
|
@ -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);
|
||||
|
||||
|
229
src/craftdef.cpp
Normal file
229
src/craftdef.cpp
Normal file
@ -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();
|
||||
}
|
||||
|
111
src/craftdef.h
Normal file
111
src/craftdef.h
Normal file
@ -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
|
||||
|
@ -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();}
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
105
src/inventory.h
105
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
|
||||
|
||||
|
@ -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}
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
InventoryItem *result = craft_get_result(items, this);
|
||||
|
||||
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);
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -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
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user