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