From e070f1e5250b6853788cb827bb2f46ecdbe300a8 Mon Sep 17 00:00:00 2001
From: Kahrl <kahrl@gmx.net>
Date: Sat, 11 Feb 2012 18:10:13 +0100
Subject: Allow replacements in cooking and fuel recipes

---
 src/craftdef.cpp  | 68 +++++++++++++++++++++++++++++--------------------------
 src/craftdef.h    | 17 ++++++++++----
 src/scriptapi.cpp | 22 ++++++++++++++++--
 3 files changed, 69 insertions(+), 38 deletions(-)

diff --git a/src/craftdef.cpp b/src/craftdef.cpp
index e8f67442f..57a1851af 100644
--- a/src/craftdef.cpp
+++ b/src/craftdef.cpp
@@ -260,6 +260,7 @@ std::string CraftOutput::dump() const
 /*
 	CraftReplacements
 */
+
 std::string CraftReplacements::dump() const
 {
 	std::ostringstream os(std::ios::binary);
@@ -276,6 +277,27 @@ std::string CraftReplacements::dump() const
 	return os.str();
 }
 
+void CraftReplacements::serialize(std::ostream &os) const
+{
+	writeU16(os, pairs.size());
+	for(u32 i=0; i<pairs.size(); i++)
+	{
+		os<<serializeString(pairs[i].first);
+		os<<serializeString(pairs[i].second);
+	}
+}
+
+void CraftReplacements::deSerialize(std::istream &is)
+{
+	pairs.clear();
+	u32 count = readU16(is);
+	for(u32 i=0; i<count; i++)
+	{
+		std::string first = deSerializeString(is);
+		std::string second = deSerializeString(is);
+		pairs.push_back(std::make_pair(first, second));
+	}
+}
 
 /*
 	CraftDefinition
@@ -418,12 +440,7 @@ void CraftDefinitionShaped::serializeBody(std::ostream &os) const
 	writeU16(os, recipe.size());
 	for(u32 i=0; i<recipe.size(); i++)
 		os<<serializeString(recipe[i]);
-	writeU16(os, replacements.pairs.size());
-	for(u32 i=0; i<replacements.pairs.size(); i++)
-	{
-		os<<serializeString(replacements.pairs[i].first);
-		os<<serializeString(replacements.pairs[i].second);
-	}
+	replacements.serialize(os);
 }
 
 void CraftDefinitionShaped::deSerializeBody(std::istream &is, int version)
@@ -436,14 +453,7 @@ void CraftDefinitionShaped::deSerializeBody(std::istream &is, int version)
 	u32 count = readU16(is);
 	for(u32 i=0; i<count; i++)
 		recipe.push_back(deSerializeString(is));
-	replacements.pairs.clear();
-	count = readU16(is);
-	for(u32 i=0; i<count; i++)
-	{
-		std::string first = deSerializeString(is);
-		std::string second = deSerializeString(is);
-		replacements.pairs.push_back(std::make_pair(first, second));
-	}
+	replacements.deSerialize(is);
 }
 
 /*
@@ -497,12 +507,7 @@ void CraftDefinitionShapeless::serializeBody(std::ostream &os) const
 	writeU16(os, recipe.size());
 	for(u32 i=0; i<recipe.size(); i++)
 		os<<serializeString(recipe[i]);
-	writeU16(os, replacements.pairs.size());
-	for(u32 i=0; i<replacements.pairs.size(); i++)
-	{
-		os<<serializeString(replacements.pairs[i].first);
-		os<<serializeString(replacements.pairs[i].second);
-	}
+	replacements.serialize(os);
 }
 
 void CraftDefinitionShapeless::deSerializeBody(std::istream &is, int version)
@@ -514,14 +519,7 @@ void CraftDefinitionShapeless::deSerializeBody(std::istream &is, int version)
 	u32 count = readU16(is);
 	for(u32 i=0; i<count; i++)
 		recipe.push_back(deSerializeString(is));
-	replacements.pairs.clear();
-	count = readU16(is);
-	for(u32 i=0; i<count; i++)
-	{
-		std::string first = deSerializeString(is);
-		std::string second = deSerializeString(is);
-		replacements.pairs.push_back(std::make_pair(first, second));
-	}
+	replacements.deSerialize(is);
 }
 
 /*
@@ -664,7 +662,7 @@ CraftOutput CraftDefinitionCooking::getOutput(const CraftInput &input, IGameDef
 
 void CraftDefinitionCooking::decrementInput(CraftInput &input, IGameDef *gamedef) const
 {
-	craftDecrementInput(input, gamedef);
+	craftDecrementOrReplaceInput(input, replacements, gamedef);
 }
 
 std::string CraftDefinitionCooking::dump() const
@@ -672,7 +670,8 @@ std::string CraftDefinitionCooking::dump() const
 	std::ostringstream os(std::ios::binary);
 	os<<"(cooking, output=\""<<output
 		<<"\", recipe=\""<<recipe
-		<<"\", cooktime="<<cooktime<<")";
+		<<"\", cooktime="<<cooktime<<")"
+		<<", replacements="<<replacements.dump()<<")";
 	return os.str();
 }
 
@@ -681,6 +680,7 @@ void CraftDefinitionCooking::serializeBody(std::ostream &os) const
 	os<<serializeString(output);
 	os<<serializeString(recipe);
 	writeF1000(os, cooktime);
+	replacements.serialize(os);
 }
 
 void CraftDefinitionCooking::deSerializeBody(std::istream &is, int version)
@@ -690,6 +690,7 @@ void CraftDefinitionCooking::deSerializeBody(std::istream &is, int version)
 	output = deSerializeString(is);
 	recipe = deSerializeString(is);
 	cooktime = readF1000(is);
+	replacements.deSerialize(is);
 }
 
 /*
@@ -725,14 +726,15 @@ CraftOutput CraftDefinitionFuel::getOutput(const CraftInput &input, IGameDef *ga
 
 void CraftDefinitionFuel::decrementInput(CraftInput &input, IGameDef *gamedef) const
 {
-	craftDecrementInput(input, gamedef);
+	craftDecrementOrReplaceInput(input, replacements, gamedef);
 }
 
 std::string CraftDefinitionFuel::dump() const
 {
 	std::ostringstream os(std::ios::binary);
 	os<<"(fuel, recipe=\""<<recipe
-		<<"\", burntime="<<burntime<<")";
+		<<"\", burntime="<<burntime<<")"
+		<<", replacements="<<replacements.dump()<<")";
 	return os.str();
 }
 
@@ -740,6 +742,7 @@ void CraftDefinitionFuel::serializeBody(std::ostream &os) const
 {
 	os<<serializeString(recipe);
 	writeF1000(os, burntime);
+	replacements.serialize(os);
 }
 
 void CraftDefinitionFuel::deSerializeBody(std::istream &is, int version)
@@ -748,6 +751,7 @@ void CraftDefinitionFuel::deSerializeBody(std::istream &is, int version)
 			"unsupported CraftDefinitionFuel version");
 	recipe = deSerializeString(is);
 	burntime = readF1000(is);
+	replacements.deSerialize(is);
 }
 
 /*
diff --git a/src/craftdef.h b/src/craftdef.h
index 454d7c2e6..107b4cf98 100644
--- a/src/craftdef.h
+++ b/src/craftdef.h
@@ -106,6 +106,8 @@ struct CraftReplacements
 		pairs(pairs_)
 	{}
 	std::string dump() const;
+	void serialize(std::ostream &os) const;
+	void deSerialize(std::istream &is);
 };
 
 /*
@@ -270,8 +272,9 @@ public:
 	CraftDefinitionCooking(
 			const std::string &output_,
 			const std::string &recipe_,
-			float cooktime_):
-		output(output_), recipe(recipe_), cooktime(cooktime_)
+			float cooktime_,
+			const CraftReplacements &replacements_):
+		output(output_), recipe(recipe_), cooktime(cooktime_), replacements(replacements_)
 	{}
 	virtual ~CraftDefinitionCooking(){}
 
@@ -293,6 +296,8 @@ private:
 	std::string recipe;
 	// Time in seconds
 	float cooktime;
+	// Replacement items for decrementInput()
+	CraftReplacements replacements;
 };
 
 /*
@@ -305,8 +310,10 @@ public:
 	CraftDefinitionFuel():
 		recipe(""), burntime()
 	{}
-	CraftDefinitionFuel(std::string recipe_, float burntime_):
-		recipe(recipe_), burntime(burntime_)
+	CraftDefinitionFuel(std::string recipe_,
+			float burntime_,
+			const CraftReplacements &replacements_):
+		recipe(recipe_), burntime(burntime_), replacements(replacements_)
 	{}
 	virtual ~CraftDefinitionFuel(){}
 
@@ -326,6 +333,8 @@ private:
 	std::string recipe;
 	// Time in seconds
 	float burntime;
+	// Replacement items for decrementInput()
+	CraftReplacements replacements;
 };
 
 /*
diff --git a/src/scriptapi.cpp b/src/scriptapi.cpp
index f53355f64..3766496a0 100644
--- a/src/scriptapi.cpp
+++ b/src/scriptapi.cpp
@@ -4129,8 +4129,17 @@ static int l_register_craft(lua_State *L)
 
 		float cooktime = getfloatfield_default(L, table, "cooktime", 3.0);
 
+		CraftReplacements replacements;
+		lua_getfield(L, table, "replacements");
+		if(!lua_isnil(L, -1))
+		{
+			if(!read_craft_replacements(L, -1, replacements))
+				throw LuaError(L, "Invalid replacements"
+						" (cooking output=\"" + output + "\")");
+		}
+
 		CraftDefinition *def = new CraftDefinitionCooking(
-				output, recipe, cooktime);
+				output, recipe, cooktime, replacements);
 		craftdef->registerCraft(def);
 	}
 	/*
@@ -4144,8 +4153,17 @@ static int l_register_craft(lua_State *L)
 
 		float burntime = getfloatfield_default(L, table, "burntime", 1.0);
 
+		CraftReplacements replacements;
+		lua_getfield(L, table, "replacements");
+		if(!lua_isnil(L, -1))
+		{
+			if(!read_craft_replacements(L, -1, replacements))
+				throw LuaError(L, "Invalid replacements"
+						" (fuel recipe=\"" + recipe + "\")");
+		}
+
 		CraftDefinition *def = new CraftDefinitionFuel(
-				recipe, burntime);
+				recipe, burntime, replacements);
 		craftdef->registerCraft(def);
 	}
 	else
-- 
cgit v1.2.3