1 /*=============================================================================
2 Blobby Volley 2
3 Copyright (C) 2006 Jonathan Sieber (jonathan_sieber@yahoo.de)
4 Copyright (C) 2006 Daniel Knobe (daniel-knobe@web.de)
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 =============================================================================*/
20
21 /* header include */
22 #include "UserConfig.h"
23
24 /* includes */
25 #include <iostream>
26 #include <map>
27
28 #include <boost/make_shared.hpp>
29
30 #include "tinyxml/tinyxml.h"
31
32 #include "Global.h"
33 #include "FileRead.h"
34 #include "FileWrite.h"
35 #include "PlayerIdentity.h"
36 #include "LocalInputSource.h"
37 #include "ScriptedInputSource.h"
38
39
40 /* implementation */
userConfigCache()41 std::map<std::string, boost::shared_ptr<IUserConfigReader> >& userConfigCache()
42 {
43 static std::map<std::string, boost::shared_ptr<IUserConfigReader> > cache;
44 return cache;
45 };
46
createUserConfigReader(const std::string & file)47 boost::shared_ptr<IUserConfigReader> IUserConfigReader::createUserConfigReader(const std::string& file)
48 {
49 // if we have this userconfig already cached, just return from cache
50 std::map<std::string, boost::shared_ptr<IUserConfigReader> >:: iterator cfg_cached = userConfigCache().find(file);
51 if( cfg_cached != userConfigCache().end() )
52 {
53 return cfg_cached->second;
54 }
55
56 // otherwise, load user config...
57 UserConfig* uc = new UserConfig();
58 uc->loadFile(file);
59 boost::shared_ptr<IUserConfigReader> config(uc);
60
61 // ... and add to cache
62 userConfigCache()[file] = config;
63
64 return config;
65 }
66
loadPlayerIdentity(PlayerSide side,bool force_human)67 PlayerIdentity UserConfig::loadPlayerIdentity(PlayerSide side, bool force_human)
68 {
69 std::string prefix = side == LEFT_PLAYER ? "left" : "right";
70 std::string name = "";
71 // init local input
72 if(force_human)
73 {
74 name = getString(prefix + "_player_name");
75 }
76 else
77 {
78 name = getBool(prefix + "_player_human") ?
79 getString(prefix + "_player_name") :
80 getString(prefix + "_script_name") + ".lua";
81 }
82
83 PlayerIdentity player = PlayerIdentity(name);
84
85 player.setStaticColor( Color(
86 getInteger(prefix + "_blobby_color_r"),
87 getInteger(prefix + "_blobby_color_g"),
88 getInteger(prefix + "_blobby_color_b")
89 ) );
90
91 player.setOscillating(getBool(prefix + "_blobby_oscillate"));
92 player.setPreferredSide((PlayerSide)getInteger("network_side"));
93
94 return player;
95 }
96
loadFile(const std::string & filename)97 bool UserConfig::loadFile(const std::string& filename)
98 {
99 boost::shared_ptr<TiXmlDocument> configDoc = FileRead::readXMLDocument(filename);
100
101 if (configDoc->Error())
102 {
103 std::cerr << "Warning: Parse error in " << filename;
104 std::cerr << "!" << std::endl;
105 }
106
107 TiXmlElement* userConfigElem =
108 configDoc->FirstChildElement("userconfig");
109 if (userConfigElem == NULL)
110 return false;
111 for (TiXmlElement* varElem = userConfigElem->FirstChildElement("var");
112 varElem != NULL;
113 varElem = varElem->NextSiblingElement("var"))
114 {
115 std::string name, value;
116 const char* c;
117 c = varElem->Attribute("name");
118 if (c)
119 name = c;
120 c = varElem->Attribute("value");
121 if (c)
122 value = c;
123 createVar(name, value);
124 }
125
126 return true;
127 }
128
saveFile(const std::string & filename) const129 bool UserConfig::saveFile(const std::string& filename) const
130 {
131 // this trows an exception if the file could not be opened for writing
132 FileWrite file(filename);
133
134 const std::string xmlHeader = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<userconfig>\n";
135
136 const std::string xmlFooter = "</userconfig>\n\n";
137
138 file.write(xmlHeader);
139
140 for (unsigned int i = 0; i < mVars.size(); ++i)
141 {
142 char writeBuffer[256];
143 int charsWritten = snprintf(writeBuffer, 256,
144 "\t<var name=\"%s\" value=\"%s\"/>\n",
145 mVars[i]->Name.c_str(), mVars[i]->Value.c_str());
146
147 file.write(writeBuffer, charsWritten);
148 }
149
150 file.write(xmlFooter);
151 file.close();
152
153 // we have to make sure that we don't cache any outdated user configs
154 auto cfg_cached = userConfigCache().find(filename);
155 if( cfg_cached != userConfigCache().end() )
156 {
157 userConfigCache().erase(cfg_cached);
158 }
159
160 return true;
161 }
162
getFloat(const std::string & name,float default_value) const163 float UserConfig::getFloat(const std::string& name, float default_value) const
164 {
165 auto var = checkVarByName(name);
166 if (var)
167 return std::atof( var->Value.c_str() );
168
169 return default_value;
170 }
171
getString(const std::string & name,const std::string & default_value) const172 std::string UserConfig::getString(const std::string& name, const std::string& default_value) const
173 {
174 auto var = checkVarByName(name);
175 if (var)
176 return var->Value;
177
178 return default_value;
179 }
180
getBool(const std::string & name,bool default_value) const181 bool UserConfig::getBool(const std::string& name, bool default_value) const
182 {
183 auto var = checkVarByName(name);
184 if (var)
185 return (var->Value == "true") ? true : false;;
186
187 return default_value;
188 }
189
getInteger(const std::string & name,int default_value) const190 int UserConfig::getInteger(const std::string& name, int default_value) const
191 {
192 auto var = checkVarByName(name);
193 if (var)
194 return std::atoi( var->Value.c_str() );
195
196 return default_value;
197 }
198
setFloat(const std::string & name,float var)199 void UserConfig::setFloat(const std::string& name, float var)
200 {
201 char writeBuffer[256];
202 snprintf(writeBuffer, 256, "%f", var);
203 setValue(name, writeBuffer);
204 }
205
setString(const std::string & name,const std::string & var)206 void UserConfig::setString(const std::string& name, const std::string& var)
207 {
208 setValue(name, var);
209 }
210
setBool(const std::string & name,bool var)211 void UserConfig::setBool(const std::string& name, bool var)
212 {
213 setValue(name, var ? "true" : "false");
214 }
215
setInteger(const std::string & name,int var)216 void UserConfig::setInteger(const std::string& name, int var)
217 {
218 char writeBuffer[256];
219 snprintf(writeBuffer, 256, "%d", var);
220 setValue(name, writeBuffer);
221 }
222
createVar(const std::string & name,const std::string & value)223 UserConfigVar* UserConfig::createVar(const std::string& name, const std::string& value)
224 {
225 if (findVarByName(name)) return NULL;
226 UserConfigVar *var = new UserConfigVar;
227 var->Name = name;
228 var->Value = value;
229 mVars.push_back(var);
230 return var;
231 }
232
setValue(const std::string & name,const std::string & value)233 void UserConfig::setValue(const std::string& name, const std::string& value)
234 {
235 UserConfigVar *var = findVarByName(name);
236 if (!var)
237 {
238 std::cerr << "Warning: impossible to set value of " <<
239 "unknown configuration variable " << name <<
240 "\n Creating new variable" << std::endl;
241 var = createVar(name, value);
242 mChangeFlag = true;
243 return;
244 }
245
246 if (var->Value != value) mChangeFlag = true;
247 var->Value = value;
248 }
249
~UserConfig()250 UserConfig::~UserConfig()
251 {
252 for (unsigned int i = 0; i < mVars.size(); ++i)
253 delete mVars[i];
254 }
255
checkVarByName(const std::string & name) const256 UserConfigVar* UserConfig::checkVarByName(const std::string& name) const
257 {
258 auto var = findVarByName(name);
259 if( !var )
260 {
261 std::cerr << "Warning: impossible to get value of " <<
262 "unknown configuration variable " << name << std::endl;
263 }
264 return var;
265 }
266
findVarByName(const std::string & name) const267 UserConfigVar* UserConfig::findVarByName(const std::string& name) const
268 {
269 for (unsigned int i = 0; i < mVars.size(); ++i)
270 if (mVars[i]->Name == name) return mVars[i];
271
272 return nullptr;
273 }
274
275