1 // ==============================================================
2 //	This file is part of Glest (www.glest.org)
3 //
4 //	Copyright (C) 2001-2008 Martiño Figueroa
5 //
6 //	You can redistribute this code and/or modify it under
7 //	the terms of the GNU General Public License as published
8 //	by the Free Software Foundation; either version 2 of the
9 //	License, or (at your option) any later version
10 // ==============================================================
11 
12 #include "resource_type.h"
13 
14 #include "util.h"
15 #include "element_type.h"
16 #include "logger.h"
17 #include "renderer.h"
18 #include "xml_parser.h"
19 #include "game_util.h"
20 #include "properties.h"
21 #include "lang.h"
22 #include "leak_dumper.h"
23 
24 using namespace Shared::Util;
25 using namespace Shared::Xml;
26 
27 namespace Glest{ namespace Game{
28 
29 // =====================================================
30 // 	class ResourceType
31 // =====================================================
32 
ResourceType()33 ResourceType::ResourceType() {
34     resourceClass=rcTech;
35     tilesetObject=0;
36     resourceNumber=0;
37     interval=0;
38 	defResPerPatch=0;
39 	recoup_cost = false;
40     model = NULL;
41     displayInHud = false;
42     cleanupMemory = true;
43 }
44 
~ResourceType()45 ResourceType::~ResourceType() {
46 	if(cleanupMemory == true) {
47 		while(particleTypes.empty() == false) {
48 			delete particleTypes.back();
49 			particleTypes.pop_back();
50 		}
51 	}
52 }
53 
getName(bool translatedValue) const54 string ResourceType::getName(bool translatedValue) const {
55 	if(translatedValue == false) return name;
56 
57 	Lang &lang = Lang::getInstance();
58 	return lang.getTechTreeString("ResourceTypeName_" + name,name.c_str());
59 }
60 
load(const string & dir,Checksum * checksum,Checksum * techtreeChecksum,std::map<string,vector<pair<string,string>>> & loadedFileList,string techtreePath)61 void ResourceType::load(const string &dir, Checksum* checksum, Checksum *techtreeChecksum,
62 		std::map<string,vector<pair<string, string> > > &loadedFileList, string techtreePath) {
63 
64 	string path, str;
65 	Renderer &renderer= Renderer::getInstance();
66 
67 	try
68 	{
69 	    recoup_cost = true;
70 
71 		name= lastDir(dir);
72 
73 		char szBuf[8096]="";
74 		snprintf(szBuf,8096,Lang::getInstance().getString("LogScreenGameLoadingResourceType","",true).c_str(),formatString(getName(true)).c_str());
75 		Logger::getInstance().add(szBuf, true);
76 
77 		string currentPath = dir;
78 		endPathWithSlash(currentPath);
79 		path= currentPath + name + ".xml";
80 		string sourceXMLFile = path;
81 		checksum->addFile(path);
82 		techtreeChecksum->addFile(path);
83 
84 		//tree
85 		XmlTree xmlTree;
86 		std::map<string,string> mapExtraTagReplacementValues;
87 		mapExtraTagReplacementValues["$COMMONDATAPATH"] = techtreePath + "/commondata/";
88 		xmlTree.load(path, Properties::getTagReplacementValues(&mapExtraTagReplacementValues));
89 		loadedFileList[path].push_back(make_pair(currentPath,currentPath));
90 
91 		const XmlNode *resourceNode= xmlTree.getRootNode();
92 
93 		//image
94 		const XmlNode *imageNode= resourceNode->getChild("image");
95 		image= renderer.newTexture2D(rsGame);
96 		if(image) {
97 			image->load(imageNode->getAttribute("path")->getRestrictedValue(currentPath));
98 		}
99 		loadedFileList[imageNode->getAttribute("path")->getRestrictedValue(currentPath)].push_back(make_pair(sourceXMLFile,imageNode->getAttribute("path")->getRestrictedValue()));
100 
101 		//type
102 		const XmlNode *typeNode= resourceNode->getChild("type");
103 		resourceClass = strToRc(typeNode->getAttribute("value")->getRestrictedValue());
104 
105 		switch(resourceClass)
106 		{
107             case rcTech:
108             {
109                 //model
110                 const XmlNode *modelNode= typeNode->getChild("model");
111                 string modelPath= modelNode->getAttribute("path")->getRestrictedValue(currentPath);
112 
113                 model= renderer.newModel(rsGame, modelPath, false, &loadedFileList, &sourceXMLFile);
114                 loadedFileList[modelPath].push_back(make_pair(sourceXMLFile,modelNode->getAttribute("path")->getRestrictedValue()));
115 
116                 if(modelNode->hasChild("particles")){
117 					const XmlNode *particleNode= modelNode->getChild("particles");
118 					bool particleEnabled= particleNode->getAttribute("value")->getBoolValue();
119 					if(particleEnabled == true) {
120 						for(int k= 0; k < (int)particleNode->getChildCount(); ++k) {
121 							const XmlNode *particleFileNode= particleNode->getChild("particle-file", k);
122 							string particlePath= particleFileNode->getAttribute("path")->getRestrictedValue();
123 
124 							ObjectParticleSystemType *objectParticleSystemType= new ObjectParticleSystemType();
125 							objectParticleSystemType->load(particleFileNode, dir,  currentPath + particlePath,
126 									&Renderer::getInstance(), loadedFileList, sourceXMLFile, techtreePath);
127 							loadedFileList[currentPath + particlePath].push_back(make_pair(sourceXMLFile,particleFileNode->getAttribute("path")->getRestrictedValue()));
128 
129 							particleTypes.push_back(objectParticleSystemType);
130 						}
131 					}
132 				}
133 
134                 //default resources
135                 const XmlNode *defaultAmountNode= typeNode->getChild("default-amount");
136                 defResPerPatch= defaultAmountNode->getAttribute("value")->getIntValue();
137 
138                 //resource number
139                 const XmlNode *resourceNumberNode= typeNode->getChild("resource-number");
140                 resourceNumber= resourceNumberNode->getAttribute("value")->getIntValue();
141 			}
142 			break;
143 
144             case rcTileset:
145             {
146                 //resource number
147                 const XmlNode *defaultAmountNode= typeNode->getChild("default-amount");
148                 defResPerPatch= defaultAmountNode->getAttribute("value")->getIntValue();
149 
150                 //resource number
151                 const XmlNode *tilesetObjectNode= typeNode->getChild("tileset-object");
152                 tilesetObject= tilesetObjectNode->getAttribute("value")->getIntValue();
153 			}
154 			break;
155 
156             case rcConsumable:
157             {
158                 //interval
159                 const XmlNode *intervalNode= typeNode->getChild("interval");
160                 interval= intervalNode->getAttribute("value")->getIntValue();
161 			}
162 			break;
163 
164             case rcStatic:
165             {
166                 //recoup_cost
167                 if(typeNode->hasChild("recoup_cost") == true) {
168                     const XmlNode *recoup_costNode= typeNode->getChild("recoup_cost");
169                     if(recoup_costNode != NULL) {
170                         recoup_cost= recoup_costNode->getAttribute("value")->getBoolValue();
171                     }
172                 }
173 			}
174 			break;
175 
176 		default:
177 			break;
178 		}
179 
180 		//displayInHud
181 		if(resourceNode->hasChild("display") == true) {
182 			const XmlNode *displayNode= resourceNode->getChild("display");
183 			displayInHud= displayNode->getAttribute("value")->getBoolValue();
184 		}
185 		else {
186 			displayInHud=true;
187 		}
188 	}
189     catch(megaglest_runtime_error& ex) {
190 		SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,ex.what());
191 		throw megaglest_runtime_error("Error loading resource type: "+ path + "\nMessage: " + ex.what(),!ex.wantStackTrace());
192     }
193 	catch(const exception &e){
194 		SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",__FILE__,__FUNCTION__,__LINE__,e.what());
195 		throw megaglest_runtime_error("Error loading resource type: " + path + "\n" + e.what());
196 	}
197 }
198 
199 // ==================== misc ====================
200 
strToRc(const string & s)201 ResourceClass ResourceType::strToRc(const string &s){
202 	if(s=="tech"){
203         return rcTech;
204 	}
205 	if(s=="tileset"){
206         return rcTileset;
207 	}
208 	if(s=="static"){
209         return rcStatic;
210 	}
211 	if(s=="consumable"){
212         return rcConsumable;
213 	}
214 	throw megaglest_runtime_error("Error converting from string ro resourceClass, found: " + s);
215 }
216 
deletePixels()217 void ResourceType::deletePixels() {
218 	if(model != NULL) {
219 		model->deletePixels();
220 	}
221 }
222 
saveGame(XmlNode * rootNode)223 void ResourceType::saveGame(XmlNode *rootNode) {
224 	//DisplayableType::saveGame(rootNode);
225 
226 	std::map<string,string> mapTagReplacements;
227 	XmlNode *resourceTypeNode = rootNode->addChild("ResourceType");
228 
229 	resourceTypeNode->addAttribute("name",this->getName(), mapTagReplacements);
230 //    ResourceClass resourceClass;
231 	resourceTypeNode->addAttribute("resourceClass",intToStr(resourceClass), mapTagReplacements);
232 //    int tilesetObject;	//used only if class==rcTileset
233 	resourceTypeNode->addAttribute("tilesetObject",intToStr(tilesetObject), mapTagReplacements);
234 //    int resourceNumber;	//used only if class==rcTech, resource number in the map
235 	resourceTypeNode->addAttribute("resourceNumber",intToStr(resourceNumber), mapTagReplacements);
236 //    int interval;		//used only if class==rcConsumable
237 	resourceTypeNode->addAttribute("interval",intToStr(interval), mapTagReplacements);
238 //	int defResPerPatch;	//used only if class==rcTileset || class==rcTech
239 	resourceTypeNode->addAttribute("defResPerPatch",intToStr(defResPerPatch), mapTagReplacements);
240 //	bool recoup_cost;
241 	resourceTypeNode->addAttribute("recoup_cost",intToStr(recoup_cost), mapTagReplacements);
242 //
243 //    Model *model;
244 	if(model != NULL) {
245 		resourceTypeNode->addAttribute("model",model->getFileName(), mapTagReplacements);
246 	}
247 //    ObjectParticleSystemTypes particleTypes;
248 	for(unsigned int i = 0; i < particleTypes.size(); ++i) {
249 		ObjectParticleSystemType *opst = particleTypes[i];
250 		opst->saveGame(resourceTypeNode);
251 	}
252 }
253 
254 }}//end namespace
255