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"
|
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 = {
|
local TNT = {
|
||||||
-- Maybe handle gravity and collision this way? dunno
|
-- Maybe handle gravity and collision this way? dunno
|
||||||
physical = true,
|
physical = true,
|
||||||
|
@ -94,6 +94,7 @@ configure_file(
|
|||||||
)
|
)
|
||||||
|
|
||||||
set(common_SRCS
|
set(common_SRCS
|
||||||
|
craftdef.cpp
|
||||||
nameidmapping.cpp
|
nameidmapping.cpp
|
||||||
tooldef.cpp
|
tooldef.cpp
|
||||||
nodedef.cpp
|
nodedef.cpp
|
||||||
|
@ -2317,6 +2317,11 @@ INodeDefManager* Client::getNodeDefManager()
|
|||||||
{
|
{
|
||||||
return m_nodedef;
|
return m_nodedef;
|
||||||
}
|
}
|
||||||
|
ICraftDefManager* Client::getCraftDefManager()
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
//return m_craftdef;
|
||||||
|
}
|
||||||
ITextureSource* Client::getTextureSource()
|
ITextureSource* Client::getTextureSource()
|
||||||
{
|
{
|
||||||
return m_tsrc;
|
return m_tsrc;
|
||||||
|
@ -36,6 +36,7 @@ class IGameDef;
|
|||||||
class IWritableTextureSource;
|
class IWritableTextureSource;
|
||||||
class IWritableToolDefManager;
|
class IWritableToolDefManager;
|
||||||
class IWritableNodeDefManager;
|
class IWritableNodeDefManager;
|
||||||
|
//class IWritableCraftDefManager;
|
||||||
|
|
||||||
class ClientNotReadyException : public BaseException
|
class ClientNotReadyException : public BaseException
|
||||||
{
|
{
|
||||||
@ -326,6 +327,7 @@ public:
|
|||||||
// IGameDef interface
|
// IGameDef interface
|
||||||
virtual IToolDefManager* getToolDefManager();
|
virtual IToolDefManager* getToolDefManager();
|
||||||
virtual INodeDefManager* getNodeDefManager();
|
virtual INodeDefManager* getNodeDefManager();
|
||||||
|
virtual ICraftDefManager* getCraftDefManager();
|
||||||
virtual ITextureSource* getTextureSource();
|
virtual ITextureSource* getTextureSource();
|
||||||
virtual u16 allocateUnknownNodeId(const std::string &name);
|
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 IToolDefManager;
|
||||||
class INodeDefManager;
|
class INodeDefManager;
|
||||||
|
class ICraftDefManager;
|
||||||
//class IItemDefManager; //TODO
|
//class IItemDefManager; //TODO
|
||||||
// Mineral too?
|
// Mineral too?
|
||||||
class ITextureSource;
|
class ITextureSource;
|
||||||
@ -40,6 +41,7 @@ public:
|
|||||||
// Thus, first they are set up and then they are only read.
|
// Thus, first they are set up and then they are only read.
|
||||||
virtual IToolDefManager* getToolDefManager()=0;
|
virtual IToolDefManager* getToolDefManager()=0;
|
||||||
virtual INodeDefManager* getNodeDefManager()=0;
|
virtual INodeDefManager* getNodeDefManager()=0;
|
||||||
|
virtual ICraftDefManager* getCraftDefManager()=0;
|
||||||
//virtual IItemDefManager* getItemDefManager()=0;
|
//virtual IItemDefManager* getItemDefManager()=0;
|
||||||
|
|
||||||
// This is always thread-safe, but referencing the irrlicht texture
|
// This is always thread-safe, but referencing the irrlicht texture
|
||||||
@ -52,6 +54,7 @@ public:
|
|||||||
// Shorthands
|
// Shorthands
|
||||||
IToolDefManager* tdef(){return getToolDefManager();}
|
IToolDefManager* tdef(){return getToolDefManager();}
|
||||||
INodeDefManager* ndef(){return getNodeDefManager();}
|
INodeDefManager* ndef(){return getNodeDefManager();}
|
||||||
|
ICraftDefManager* cdef(){return getCraftDefManager();}
|
||||||
ITextureSource* tsrc(){return getTextureSource();}
|
ITextureSource* tsrc(){return getTextureSource();}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1153,5 +1153,85 @@ bool checkItemCombination(InventoryItem const * const *items, const ItemSpec *sp
|
|||||||
|
|
||||||
return true;
|
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
|
//END
|
||||||
|
105
src/inventory.h
105
src/inventory.h
@ -70,25 +70,26 @@ public:
|
|||||||
Quantity methods
|
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
|
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
|
u16 getCount() const
|
||||||
{
|
{ return m_count; }
|
||||||
return m_count;
|
|
||||||
}
|
|
||||||
void setCount(u16 count)
|
void setCount(u16 count)
|
||||||
{
|
{ m_count = count; }
|
||||||
m_count = count;
|
|
||||||
}
|
|
||||||
// This should return something else for stackable items
|
// This should return something else for stackable items
|
||||||
virtual u16 freeSpace() const
|
virtual u16 freeSpace() const
|
||||||
{
|
{ return 0; }
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
void add(u16 count)
|
void add(u16 count)
|
||||||
{
|
{
|
||||||
assert(m_count + count <= QUANTITY_ITEM_MAX_COUNT);
|
assert(m_count + count <= QUANTITY_ITEM_MAX_COUNT);
|
||||||
@ -168,6 +169,24 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
return true;
|
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
|
u16 freeSpace() const
|
||||||
{
|
{
|
||||||
if(m_count > QUANTITY_ITEM_MAX_COUNT)
|
if(m_count > QUANTITY_ITEM_MAX_COUNT)
|
||||||
@ -245,6 +264,24 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
return true;
|
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
|
u16 freeSpace() const
|
||||||
{
|
{
|
||||||
if(m_count > QUANTITY_ITEM_MAX_COUNT)
|
if(m_count > QUANTITY_ITEM_MAX_COUNT)
|
||||||
@ -312,23 +349,26 @@ public:
|
|||||||
std::string getText()
|
std::string getText()
|
||||||
{
|
{
|
||||||
return "";
|
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
|
Special methods
|
||||||
*/
|
*/
|
||||||
@ -591,5 +631,12 @@ struct ItemSpec
|
|||||||
*/
|
*/
|
||||||
bool checkItemCombination(const InventoryItem * const*items, const ItemSpec *specs);
|
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
|
#endif
|
||||||
|
|
||||||
|
@ -37,6 +37,7 @@ extern "C" {
|
|||||||
#include "content_sao.h" // For LuaEntitySAO
|
#include "content_sao.h" // For LuaEntitySAO
|
||||||
#include "tooldef.h"
|
#include "tooldef.h"
|
||||||
#include "nodedef.h"
|
#include "nodedef.h"
|
||||||
|
#include "craftdef.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
TODO:
|
TODO:
|
||||||
@ -205,26 +206,6 @@ static int l_register_globalstep(lua_State *L)
|
|||||||
return 0; /* number of results */
|
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})
|
// register_tool(name, {lots of stuff})
|
||||||
static int l_register_tool(lua_State *L)
|
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);
|
f.tname_inventory = lua_tostring(L, -1);
|
||||||
lua_pop(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);
|
nodedef->set(name, f);
|
||||||
return 0; /* number of results */
|
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 [] = {
|
static const struct luaL_Reg minetest_f [] = {
|
||||||
{"register_entity", l_register_entity},
|
{"register_entity", l_register_entity},
|
||||||
{"register_globalstep", l_register_globalstep},
|
{"register_globalstep", l_register_globalstep},
|
||||||
//{"deregister_tools", l_deregister_tools},
|
|
||||||
{"register_tool", l_register_tool},
|
{"register_tool", l_register_tool},
|
||||||
{"register_node", l_register_node},
|
{"register_node", l_register_node},
|
||||||
|
{"register_craft", l_register_craft},
|
||||||
{NULL, NULL}
|
{NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -43,6 +43,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "scriptapi.h"
|
#include "scriptapi.h"
|
||||||
#include "nodedef.h"
|
#include "nodedef.h"
|
||||||
#include "tooldef.h"
|
#include "tooldef.h"
|
||||||
|
#include "craftdef.h"
|
||||||
|
|
||||||
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
|
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
|
||||||
|
|
||||||
@ -988,6 +989,7 @@ Server::Server(
|
|||||||
m_lua(NULL),
|
m_lua(NULL),
|
||||||
m_toolmgr(createToolDefManager()),
|
m_toolmgr(createToolDefManager()),
|
||||||
m_nodedef(createNodeDefManager()),
|
m_nodedef(createNodeDefManager()),
|
||||||
|
m_craftdef(createCraftDefManager()),
|
||||||
m_thread(this),
|
m_thread(this),
|
||||||
m_emergethread(this),
|
m_emergethread(this),
|
||||||
m_time_counter(0),
|
m_time_counter(0),
|
||||||
@ -4332,14 +4334,19 @@ void Server::UpdateCrafting(u16 peer_id)
|
|||||||
}
|
}
|
||||||
if(clist && rlist && player->craftresult_is_preview)
|
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
|
// 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)
|
if(result)
|
||||||
rlist->addItem(result);
|
rlist->addItem(result);
|
||||||
}
|
}
|
||||||
@ -4424,6 +4431,10 @@ INodeDefManager* Server::getNodeDefManager()
|
|||||||
{
|
{
|
||||||
return m_nodedef;
|
return m_nodedef;
|
||||||
}
|
}
|
||||||
|
ICraftDefManager* Server::getCraftDefManager()
|
||||||
|
{
|
||||||
|
return m_craftdef;
|
||||||
|
}
|
||||||
ITextureSource* Server::getTextureSource()
|
ITextureSource* Server::getTextureSource()
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -4441,6 +4452,10 @@ IWritableNodeDefManager* Server::getWritableNodeDefManager()
|
|||||||
{
|
{
|
||||||
return m_nodedef;
|
return m_nodedef;
|
||||||
}
|
}
|
||||||
|
IWritableCraftDefManager* Server::getWritableCraftDefManager()
|
||||||
|
{
|
||||||
|
return m_craftdef;
|
||||||
|
}
|
||||||
|
|
||||||
v3f findSpawnPos(ServerMap &map)
|
v3f findSpawnPos(ServerMap &map)
|
||||||
{
|
{
|
||||||
|
@ -35,6 +35,7 @@ struct LuaState;
|
|||||||
typedef struct lua_State lua_State;
|
typedef struct lua_State lua_State;
|
||||||
class IWritableToolDefManager;
|
class IWritableToolDefManager;
|
||||||
class IWritableNodeDefManager;
|
class IWritableNodeDefManager;
|
||||||
|
class IWritableCraftDefManager;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Some random functions
|
Some random functions
|
||||||
@ -490,11 +491,13 @@ public:
|
|||||||
// Under envlock
|
// Under envlock
|
||||||
virtual IToolDefManager* getToolDefManager();
|
virtual IToolDefManager* getToolDefManager();
|
||||||
virtual INodeDefManager* getNodeDefManager();
|
virtual INodeDefManager* getNodeDefManager();
|
||||||
|
virtual ICraftDefManager* getCraftDefManager();
|
||||||
virtual ITextureSource* getTextureSource();
|
virtual ITextureSource* getTextureSource();
|
||||||
virtual u16 allocateUnknownNodeId(const std::string &name);
|
virtual u16 allocateUnknownNodeId(const std::string &name);
|
||||||
|
|
||||||
IWritableToolDefManager* getWritableToolDefManager();
|
IWritableToolDefManager* getWritableToolDefManager();
|
||||||
IWritableNodeDefManager* getWritableNodeDefManager();
|
IWritableNodeDefManager* getWritableNodeDefManager();
|
||||||
|
IWritableCraftDefManager* getWritableCraftDefManager();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@ -635,6 +638,9 @@ private:
|
|||||||
// Node definition manager
|
// Node definition manager
|
||||||
IWritableNodeDefManager *m_nodedef;
|
IWritableNodeDefManager *m_nodedef;
|
||||||
|
|
||||||
|
// Craft definition manager
|
||||||
|
IWritableCraftDefManager *m_craftdef;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Threads
|
Threads
|
||||||
*/
|
*/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user