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