]> jfr.im git - irc/gameservirc.git/blob - gameserv-2.0/libgameservgldl/src/DataLayer/File/FilePlayerDAO.cpp
Wrote some initial MySQLDAO objects, but they're not complete
[irc/gameservirc.git] / gameserv-2.0 / libgameservgldl / src / DataLayer / File / FilePlayerDAO.cpp
1 #include <GameServ/DataLayer/File/FilePlayerDAO.h>
2 using GameServ::DataLayer::File::FilePlayerDAO;
3 #include <GameServ/DataLayer/File/FileItemDAO.h>
4 using GameServ::DataLayer::File::FileItemDAO;
5
6 #include <GameServ/GameLayer/GameObjects/PlayerGO.h>
7 using GameServ::GameLayer::GameObjects::PlayerGO;
8
9 #include <GameServ/DataLayer/DataLayerExceptions.h>
10 using GameServ::DataLayer::Exceptions::ResourceException;
11 using GameServ::DataLayer::Exceptions::DataLayerException;
12
13 #include <GameServ/DataLayer/File/FileId.h>
14 using GameServ::DataLayer::File::FileId;
15
16 #include <GameServ/GameLayer/Helpers/InventoryManager.h>
17 using namespace GameServ::GameLayer::Helpers;
18
19 #include <boost/smart_ptr/shared_ptr.hpp>
20 #include <boost/format.hpp>
21 #include <boost/algorithm/string.hpp>
22 #include <boost/lexical_cast.hpp>
23 using boost::shared_ptr;
24 using boost::shared_static_cast;
25 using boost::format;
26 using boost::str;
27 using boost::algorithm::to_upper;
28 using boost::algorithm::to_lower;
29 using boost::lexical_cast;
30 using boost::bad_lexical_cast;
31 #include <boost/tokenizer.hpp>
32 typedef boost::tokenizer<boost::char_separator<char> >
33 tokenizer;
34
35 #include <boost/date_time/posix_time/posix_time.hpp>
36 using namespace boost::posix_time;
37
38 #include <time.h>
39
40 #include <string>
41 using std::string;
42
43 #include <fstream>
44 using std::ifstream;
45 using std::getline;
46 using std::ofstream;
47 using std::endl;
48
49 #include <map>
50 using std::map;
51
52 FilePlayerDAO::FilePlayerDAO() : mFilename("data\\players.dat")
53 {
54 Initialize(GetPlayerFilePath());
55 }
56
57 FilePlayerDAO::FilePlayerDAO(const string &filename)
58 {
59 Initialize(filename);
60 }
61
62 FilePlayerDAO::~FilePlayerDAO()
63 {
64 WritePlayerCache();
65 }
66
67 void FilePlayerDAO::Initialize(const string &filename)
68 {
69 mFilename = filename;
70 LoadPlayerCache();
71 }
72
73 void FilePlayerDAO::LoadPlayerCache(void)
74 {
75 assert(!mFilename.empty());
76 spPlayerCache.clear();
77 ifstream infile;
78 infile.open(mFilename.c_str());
79 if (infile.fail())
80 {
81 throw DataLayerException(str(format("Unable to open %1% for loading Players") % mFilename),
82 __FILE__, __LINE__);
83 }
84 while (!infile.eof())
85 {
86 string line;
87 shared_ptr<PlayerGO> spPlayer;
88 getline(infile, line);
89 if (line.empty())
90 {
91 continue;
92 }
93 else if (line[0] == '#')
94 {
95 continue;
96 }
97 spPlayer = CreatePlayerFromLine(line);
98 if (spPlayer != 0)
99 {
100 string id = spPlayer->Id();
101 to_lower(id);
102 spPlayerCache[id] = spPlayer;
103 // Load all the items into the player's inventory
104 shared_ptr<InventoryManager> inventory = InventoryManager::Instance();
105 if (!inventory->PlayerHasInventory(spPlayer))
106 {
107 LoadInventoryFromLine(spPlayer, line);
108 }
109 }
110 }
111 infile.close();
112 }
113
114 void FilePlayerDAO::WritePlayerCache(void) const
115 {
116 ofstream outfile;
117 outfile.open(mFilename.c_str());
118 if (outfile.fail())
119 {
120 throw DataLayerException(str(format("Unable to open %1% for writing Players") % mFilename),
121 __FILE__, __LINE__);
122 }
123
124 map<string, shared_ptr<PlayerGO> >::const_iterator iter;
125 for (iter = spPlayerCache.begin(); iter != spPlayerCache.end(); iter++)
126 {
127 outfile << CreateLineFromPlayer(iter->second) << endl;
128 }
129 outfile.close();
130 }
131
132 string FilePlayerDAO::GetPlayerFilePath() const
133 {
134 return mFilename;
135 }
136
137 shared_ptr<PlayerGO> FilePlayerDAO::GetById(const string &Id) const
138 {
139 map<string, shared_ptr<PlayerGO> >::const_iterator iter;
140 string id = Id;
141 to_lower(id);
142 iter = spPlayerCache.find(id);
143 if (iter != spPlayerCache.end())
144 {
145 return shared_ptr<PlayerGO>(iter->second->Clone());
146 }
147 return shared_ptr<PlayerGO>();
148 }
149
150 shared_ptr<PlayerGO> FilePlayerDAO::CreatePlayerFromLine(const string &line) const
151 {
152 assert(!line.empty());
153 shared_ptr<PlayerGO> spPlayer;
154 spPlayer = shared_ptr<PlayerGO>(new PlayerGO());
155 boost::char_separator<char> sep(" ", 0, boost::keep_empty_tokens);
156 tokenizer tokens(line, sep);
157 tokenizer::iterator tok_iter = tokens.begin();
158
159 spPlayer->Name((*tok_iter));
160 spPlayer->Id(FileId::CreatePlayerId(spPlayer->Name()));
161 tok_iter++;
162 if (tok_iter == tokens.end())
163 {
164 throw DataLayerException(str(format("Corrupt player line %1%. Missing information") %
165 line), __FILE__, __LINE__);
166 }
167 spPlayer->LevelNumber(lexical_cast<unsigned int>((*tok_iter)));
168 spPlayer->LevelId(FileId::CreateLevelId(spPlayer->LevelNumber()));
169 tok_iter++;
170 if (tok_iter == tokens.end())
171 {
172 throw DataLayerException(str(format("Corrupt player line %1%. Missing information") %
173 line), __FILE__, __LINE__);
174 }
175 spPlayer->Experience(lexical_cast<unsigned long int>((*tok_iter)));
176 tok_iter++;
177 if (tok_iter == tokens.end())
178 {
179 throw DataLayerException(str(format("Corrupt player line %1%. Missing information") %
180 line), __FILE__, __LINE__);
181 }
182 spPlayer->Gold(lexical_cast<unsigned long int>((*tok_iter)));
183 tok_iter++;
184 if (tok_iter == tokens.end())
185 {
186 throw DataLayerException(str(format("Corrupt player line %1%. Missing information") %
187 line), __FILE__, __LINE__);
188 }
189 spPlayer->Bank(lexical_cast<unsigned long int>((*tok_iter)));
190 tok_iter++;
191 if (tok_iter == tokens.end())
192 {
193 throw DataLayerException(str(format("Corrupt player line %1%. Missing information") %
194 line), __FILE__, __LINE__);
195 }
196 spPlayer->Health(lexical_cast<int>((*tok_iter)));
197 tok_iter++;
198 if (tok_iter == tokens.end())
199 {
200 throw DataLayerException(str(format("Corrupt player line %1%. Missing information") %
201 line), __FILE__, __LINE__);
202 }
203 spPlayer->MaxHealth(lexical_cast<int>((*tok_iter)));
204 tok_iter++;
205 if (tok_iter == tokens.end())
206 {
207 throw DataLayerException(str(format("Corrupt player line %1%. Missing information") %
208 line), __FILE__, __LINE__);
209 }
210 spPlayer->Strength(lexical_cast<int>((*tok_iter)));
211 tok_iter++;
212 if (tok_iter == tokens.end())
213 {
214 throw DataLayerException(str(format("Corrupt player line %1%. Missing information") %
215 line), __FILE__, __LINE__);
216 }
217 spPlayer->Defense(lexical_cast<int>((*tok_iter)));
218 tok_iter++;
219 if (tok_iter == tokens.end())
220 {
221 throw DataLayerException(str(format("Corrupt player line %1%. Missing information") %
222 line), __FILE__, __LINE__);
223 }
224 spPlayer->ForestFights(lexical_cast<int>((*tok_iter)));
225 tok_iter++;
226 if (tok_iter == tokens.end())
227 {
228 throw DataLayerException(str(format("Corrupt player line %1%. Missing information") %
229 line), __FILE__, __LINE__);
230 }
231 spPlayer->PlayerFights(lexical_cast<int>((*tok_iter)));
232 tok_iter++;
233 if (tok_iter == tokens.end())
234 {
235 throw DataLayerException(str(format("Corrupt player line %1%. Missing information") %
236 line), __FILE__, __LINE__);
237 }
238 int flags = lexical_cast<int>((*tok_iter));
239 SetFlags(spPlayer, flags);
240 tok_iter++;
241 if (tok_iter == tokens.end())
242 {
243 throw DataLayerException(str(format("Corrupt player line %1%. Missing information") %
244 line), __FILE__, __LINE__);
245 }
246 spPlayer->Password((*tok_iter));
247
248
249 tok_iter++;
250 if (tok_iter == tokens.end())
251 {
252 throw DataLayerException(str(format("Corrupt player line %1%. Missing information") %
253 line), __FILE__, __LINE__);
254 }
255
256 try
257 {
258 unsigned long int intlast = lexical_cast<unsigned long int>((*tok_iter));
259 time_t t = (time_t)intlast;
260 spPlayer->LastLogin(from_time_t(t));
261 }
262 catch (bad_lexical_cast)
263 {
264 spPlayer->LastLogin(from_iso_string((*tok_iter)));
265 }
266
267
268 // Weapon
269 tok_iter++;
270 if (tok_iter == tokens.end())
271 {
272 throw DataLayerException(str(format("Corrupt player line %1%. Missing information") %
273 line), __FILE__, __LINE__);
274 }
275 FileItemDAO idao;
276 string weaponid = FileId::CreateItemId((*tok_iter));
277 spPlayer->Weapon(boost::shared_static_cast<WeaponGO>(idao.GetById(weaponid)));
278
279 // Armor
280 tok_iter++;
281 if (tok_iter == tokens.end())
282 {
283 throw DataLayerException(str(format("Corrupt player line %1%. Missing information") %
284 line), __FILE__, __LINE__);
285 }
286 string armorid = FileId::CreateItemId((*tok_iter));
287 spPlayer->Armor(boost::shared_static_cast<ArmorGO>(idao.GetById(armorid)));
288
289 tok_iter++;
290 if (tok_iter == tokens.end())
291 {
292 throw DataLayerException(str(format("Corrupt player line %1%. Missing information") %
293 line), __FILE__, __LINE__);
294 }
295
296 return spPlayer;
297 }
298
299 void FilePlayerDAO::LoadInventoryFromLine(shared_ptr<PlayerGO> spPlayer, const string &line) const
300 {
301 assert(!line.empty());
302 boost::char_separator<char> sep(" ", 0);
303 tokenizer tokens(line, sep);
304 tokenizer::iterator tok_iter = tokens.begin();
305
306 for (int x = 0; x < 16; ++x)
307 {
308 tok_iter++;
309 if (tok_iter == tokens.end())
310 {
311 throw DataLayerException(str(format("Corrupt player line %1%. Missing information") %
312 line), __FILE__, __LINE__);
313 }
314 }
315 // Load all the items into the player's inventory
316 shared_ptr<InventoryManager> inventory = InventoryManager::Instance();
317 FileItemDAO idao;
318 while (tok_iter != tokens.end())
319 {
320 string itemid = FileId::CreateItemId((*tok_iter));
321 shared_ptr<ItemGO> spItem = idao.GetById(itemid);
322 tok_iter++;
323 if (tok_iter == tokens.end())
324 {
325 throw DataLayerException(str(format("Corrupt %1% file: Missing item uses for item %2% on player %3%") %
326 mFilename % itemid % spPlayer->Name()), __FILE__, __LINE__);
327 }
328 try
329 {
330 spItem->Uses(lexical_cast<int>((*tok_iter)));
331 }
332 catch (bad_lexical_cast)
333 {
334 throw DataLayerException(str(format("Corrupt %1% file: Non integer item uses for item %2% on player %3%") %
335 mFilename % itemid % spPlayer->Name()), __FILE__, __LINE__);
336 }
337 inventory->AddItem(spPlayer, spItem);
338 tok_iter++;
339 }
340 }
341
342 string FilePlayerDAO::CreateLineFromPlayer(shared_ptr<PlayerGO> spPlayer) const
343 {
344 string line;
345 line = str(format("%1% %2% %3% %4% %5% %6% %7% %8% %9% %10% %11% %12% %13% %14% %15% %16%") %
346 spPlayer->Name() % FileId::GetLevelNumberFromId(spPlayer->LevelId()) % spPlayer->Experience() %
347 spPlayer->Gold() % spPlayer->Bank() % spPlayer->Health() % spPlayer->MaxHealth() %
348 spPlayer->Strength() % spPlayer->Defense() % spPlayer->ForestFights() % spPlayer->PlayerFights() %
349 GetFlags(spPlayer) % spPlayer->Password() % (to_iso_string(spPlayer->LastLogin())) %
350 FileId::GetItemNumberFromId(spPlayer->Weapon()->Id()) % FileId::GetItemNumberFromId(spPlayer->Armor()->Id()));
351
352 shared_ptr<InventoryManager> spInventory = InventoryManager::Instance();
353 ItemList inventory = spInventory->GetInventory(spPlayer);
354 ItemList::const_iterator iter;
355 for (iter = inventory.begin(); iter != inventory.end(); iter++)
356 {
357 shared_ptr<ItemGO> spItem = (*iter);
358 line += " " + FileId::GetItemNumberFromId(spItem->Id()) + " " + lexical_cast<string>(spItem->Uses());
359 }
360
361 return line;
362 }
363
364 void FilePlayerDAO::SetFlags(shared_ptr<PlayerGO> spPlayer, const int &flags) const
365 {
366 if ((flags & 0x00000001) == 0x00000001)
367 {
368 spPlayer->FoughtMaster(true);
369 }
370 else
371 {
372 spPlayer->FoughtMaster(false);
373 }
374
375 if ((flags & 0x00000002) == 0x00000002)
376 {
377 spPlayer->Alive(true);
378 }
379 else
380 {
381 spPlayer->Alive(false);
382 }
383 }
384
385 int FilePlayerDAO::GetFlags(shared_ptr<PlayerGO> spPlayer) const
386 {
387 int flags = 0;
388
389 if (spPlayer->FoughtMaster())
390 {
391 flags |= 0x00000001;
392 }
393 if (spPlayer->Alive())
394 {
395 flags |= 0x00000002;
396 }
397 return 0;
398 }
399
400 void FilePlayerDAO::Update(shared_ptr<PlayerGO> spPlayer)
401 {
402 assert(spPlayer != 0);
403 assert(!spPlayer->Id().empty());
404 assert(!spPlayer->Name().empty());
405
406 // TODO: Lock the file
407 if (IdExists(spPlayer->Id()))
408 {
409 string id = spPlayer->Id();
410 to_lower(id);
411 spPlayerCache[id] = spPlayer;
412 }
413 else
414 {
415 throw DataLayerException(str(format("Unable to Update Player %1%: Player does not exist") %
416 spPlayer->Name()), __FILE__, __LINE__);
417 }
418 }
419
420 void FilePlayerDAO::Insert(shared_ptr<PlayerGO> spPlayer)
421 {
422 assert(spPlayer != 0);
423 assert(!spPlayer->Name().empty());
424 // TODO: Lock the file
425 if (!IdExists(FileId::CreatePlayerId(spPlayer->Name())))
426 {
427 spPlayer->Id(FileId::CreatePlayerId(spPlayer->Name()));
428 string id = spPlayer->Id();
429 to_lower(id);
430 spPlayerCache[id] = spPlayer;
431 /*ofstream outfile;
432 outfile.open(mFilename.c_str(), std::ios::app);
433 if (outfile.fail())
434 {
435 throw ResourceException(str(format("Unable to open %1% for appending.") % mFilename), __FILE__, __LINE__);
436 }
437 outfile << CreateLineFromPlayer(spPlayer) << endl;
438 outfile.close();*/
439 }
440 else
441 {
442 throw DataLayerException(str(format("Unable to Insert Player %1%: Player exists") %
443 spPlayer->Name()), __FILE__, __LINE__);
444 }
445 }
446
447 bool FilePlayerDAO::IdExists(const string &Id) const
448 {
449 map<string, shared_ptr<PlayerGO> >::const_iterator iter;
450 string id = Id;
451 to_lower(id);
452 iter = spPlayerCache.find(id);
453 return (iter != spPlayerCache.end());
454 }
455
456 list<string> FilePlayerDAO::GetIdsByName(const string &Name) const
457 {
458 list<string> ids;
459 if (IdExists(FileId::CreatePlayerId(Name)))
460 {
461 ids.push_back(FileId::CreatePlayerId(Name));
462 }
463 return ids;
464 }