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