forked from Mirrorlandia_minetest/minetest
230 lines
6.1 KiB
C++
230 lines
6.1 KiB
C++
|
/*
|
||
|
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();
|
||
|
}
|
||
|
|