Advertisement
Guest User

Untitled

a guest
Sep 7th, 2011
104
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 37.33 KB | None | 0 0
  1. /* $Id: world.cpp 189 2010-04-27 06:18:38Z sausage $
  2. * EOSERV is released under the zlib license.
  3. * See LICENSE.txt for more info.
  4. */
  5.  
  6. #include "world.hpp"
  7.  
  8. #include "character.hpp"
  9. #include "config.hpp"
  10. #include "console.hpp"
  11. #include "database.hpp"
  12. #include "eoclient.hpp"
  13. #include "eodata.hpp"
  14. #include "eoserver.hpp"
  15. #include "guild.hpp"
  16. #include "hash.hpp"
  17. #include "hook.hpp"
  18. #include "map.hpp"
  19. #include "npc.hpp"
  20. #include "packet.hpp"
  21. #include "party.hpp"
  22. #include "player.hpp"
  23. #include "quest.hpp"
  24. #include "scriptreg.hpp"
  25. #include "util.hpp"
  26.  
  27. void world_spawn_npcs(void *world_void)
  28. {
  29. World *world(static_cast<World *>(world_void));
  30.  
  31. double spawnrate = world->config["SpawnRate"];
  32. double current_time = Timer::GetTime();
  33. UTIL_PTR_VECTOR_FOREACH(world->maps, Map, map)
  34. {
  35. UTIL_PTR_VECTOR_FOREACH(map->npcs, NPC, npc)
  36. {
  37. if ((!npc->alive && npc->dead_since + (double(npc->spawn_time) * spawnrate) < current_time)
  38. && (!npc->Data()->child || (npc->parent && npc->parent->alive && world->config["RespawnBossChildren"])))
  39. {
  40. #ifdef DEBUG
  41. Console::Dbg("Spawning NPC %i on map %i", npc->id, map->id);
  42. #endif // DEBUG
  43. npc->Spawn();
  44. }
  45. }
  46. }
  47. }
  48.  
  49. void world_hpdrain(void *world_void)
  50. {
  51. World *world = static_cast<World *>(world_void);
  52.  
  53. UTIL_PTR_VECTOR_FOREACH(world->maps, Map, map)
  54. {
  55. if(map->effect == 8)
  56. {
  57. UTIL_PTR_VECTOR_FOREACH(world->characters, Character, from)
  58. {
  59. map->HPdrain(*from);
  60. }
  61. }
  62. }
  63. }
  64.  
  65. void world_tpdrain(void *world_void)
  66. {
  67. World *world = static_cast<World *>(world_void);
  68.  
  69. UTIL_PTR_VECTOR_FOREACH(world->maps, Map, map)
  70. {
  71. if(map->effect == 9)
  72. {
  73. UTIL_PTR_VECTOR_FOREACH(world->characters, Character, from)
  74. {
  75. map->TPdrain(*from);
  76. }
  77. }
  78. }
  79. }
  80.  
  81. void world_execute_weddings(void *world_void)
  82. {
  83. World *world = static_cast<World *>(world_void);
  84. double now = Timer::GetTime();
  85.  
  86. UTIL_PTR_VECTOR_FOREACH(world->maps, Map, map)
  87. {
  88. UTIL_PTR_VECTOR_FOREACH(map->npcs, NPC, npc)
  89. {
  90. if (npc->marriage && npc->marriage->request_accepted)
  91. {
  92. if (!npc->marriage->partner[0] || !npc->marriage->partner[1])
  93. {
  94. npc->ShowDialog("Something went wrong. Stopping wedding");
  95. npc->marriage = 0;
  96. continue;
  97. }
  98. else if (!npc->marriage->partner[0]->online || !npc->marriage->partner[1]->online)
  99. {
  100. npc->ShowDialog("One of the wedding partners has exited the game. Stopping wedding");
  101. npc->marriage = 0;
  102. continue;
  103. }
  104. else if (npc->marriage->partner[0]->map != npc->map || npc->marriage->partner[1]->map != npc->map)
  105. {
  106. npc->ShowDialog("One of the wedding partners has left the map. Stopping wedding");
  107. npc->marriage = 0;
  108. continue;
  109. }
  110. else if ((npc->marriage->state == 5 && npc->marriage->partner_accepted[0]) || (npc->marriage->state == 8 && npc->marriage->partner_accepted[1]))
  111. {
  112. ++npc->marriage->state;
  113. }
  114. else if (npc->marriage->last_execution + (util::to_int(world->wedding_config["PriestDialogInterval"])) <= now)
  115. {
  116. switch (npc->marriage->state)
  117. {
  118. case 1: // Starting state
  119. {
  120. npc->ShowDialog("We are here at the invitation of " + util::ucfirst(npc->marriage->partner[0]->name) + " and " + util::ucfirst(npc->marriage->partner[1]->name) + ", who have come before us to join together in marriage.");
  121. ++npc->marriage->state;
  122. }
  123. break;
  124.  
  125. case 2: // second dialog
  126. {
  127. npc->ShowDialog("Their relationship is based on love, respect, and a determination to face the future together in health or sickness, in joy and sorrow.");
  128. ++npc->marriage->state;
  129. }
  130. break;
  131.  
  132. case 3: // Partner 1 question
  133. {
  134. npc->ShowDialog(util::ucfirst(npc->marriage->partner[0]->name) + ", do you take " + util::ucfirst(npc->marriage->partner[1]->name) + " to be your partner, and promise to love, comfort and stay together as long as you both shall live?");
  135. ++npc->marriage->state;
  136. }
  137. break;
  138.  
  139. case 4: // Partner 1 question box
  140. {
  141. PacketBuilder builder(PACKET_PRIEST, PACKET_REPLY);
  142. builder.AddChar(PRIEST_REQUEST);
  143. npc->marriage->partner[0]->player->client->SendBuilder(builder);
  144. ++npc->marriage->state;
  145. }
  146. break;
  147.  
  148. case 5: break; // Waiting for Partner 1 acceptance
  149.  
  150. case 6: // Recived agreement from partner 1
  151. {
  152. npc->ShowDialog(util::ucfirst(npc->marriage->partner[1]->name) + ", do you take " + util::ucfirst(npc->marriage->partner[0]->name) + " to be your partner, and promise to love, comfort and stay together as long as you both shall live?");
  153. ++npc->marriage->state;
  154. }
  155. break;
  156.  
  157. case 7: // Partner 2 question box
  158. {
  159. PacketBuilder builder(PACKET_PRIEST, PACKET_REPLY);
  160. builder.AddChar(PRIEST_REQUEST);
  161. npc->marriage->partner[1]->player->client->SendBuilder(builder);
  162. ++npc->marriage->state;
  163. }
  164. break;
  165.  
  166. case 8: break; // Waiting for Partner 2 acceptance
  167.  
  168. case 9: // Rings message
  169. {
  170. npc->ShowDialog("Let these rings be given and received as a token of your affection, sincerity and trust in one another.");
  171. ++npc->marriage->state;
  172. }
  173. break;
  174.  
  175. case 10:
  176. {
  177. PacketBuilder builder(PACKET_ITEM, static_cast<PacketAction>(26));
  178. builder.AddShort(util::to_int(world->wedding_config["WeddingRing"]));
  179. builder.AddThree(1);
  180. for (int i = 0; i < 2; ++i)
  181. {
  182. npc->marriage->partner[i]->AddItem(util::to_int(world->wedding_config["WeddingRing"]), 1);
  183. npc->marriage->partner[i]->player->client->SendBuilder(builder);
  184. }
  185. ++npc->marriage->state;
  186. }
  187.  
  188. case 11:
  189. {
  190. npc->ShowDialog("Please place these rings on eachothers finger");
  191. ++npc->marriage->state;
  192. }
  193. break;
  194.  
  195. case 12:
  196. {
  197. if (npc->marriage->partner[0]->paperdoll[Character::Ring1] == util::to_int(world->wedding_config["WeddingRing"]) ||
  198. npc->marriage->partner[0]->paperdoll[Character::Ring2] == util::to_int(world->wedding_config["WeddingRing"]) ||
  199. npc->marriage->partner[1]->paperdoll[Character::Ring1] == util::to_int(world->wedding_config["WeddingRing"]) ||
  200. npc->marriage->partner[1]->paperdoll[Character::Ring2] == util::to_int(world->wedding_config["WeddingRing"]))
  201. {
  202. ++npc->marriage->state;
  203. }
  204. }
  205. break;
  206.  
  207. case 13: // Waiting for ring equiping
  208. {
  209. int effect = util::to_int(util::explode(',', world->wedding_config["WeddingEffects"])[0]);
  210. for (int i = 0; i < 2; ++i)
  211. npc->marriage->partner[i]->Effect(effect);
  212.  
  213. npc->ShowDialog(util::ucfirst(npc->marriage->partner[0]->name) + " and " + util::ucfirst(npc->marriage->partner[1]->name) + " have consented together in marriage. And are now partners for as long you both shall live.");
  214. ++npc->marriage->state;
  215. }
  216. break;
  217.  
  218. case 14: // Next effect
  219. {
  220. int effect = util::to_int(util::explode(',', world->wedding_config["WeddingEffects"])[1]);
  221. for (int i = 0; i < 2; ++i)
  222. npc->marriage->partner[i]->Effect(effect);
  223. ++npc->marriage->state;
  224. }
  225. break;
  226.  
  227. case 15: // Next effect
  228. {
  229. npc->ShowDialog("Congratulations to the couple!");
  230. int effect = util::to_int(util::explode(',', world->wedding_config["WeddingEffects"])[2]);
  231. for (int i = 0; i < 2; ++i)
  232. npc->marriage->partner[i]->Effect(effect);
  233.  
  234. npc->marriage->partner[0]->partner = npc->marriage->partner[1]->name;
  235. npc->marriage->partner[0]->fiance = "";
  236.  
  237. npc->marriage->partner[1]->partner = npc->marriage->partner[0]->name;
  238. npc->marriage->partner[1]->fiance = "";
  239. npc->marriage = 0;
  240. }
  241. break;
  242.  
  243. default: Console::Err("Invalid state for marriage ceremony."); npc->marriage = 0;
  244. }
  245. if (npc->marriage)
  246. npc->marriage->last_execution = Timer::GetTime();
  247. }
  248. }
  249. }
  250. }
  251. }
  252.  
  253. void world_act_npcs(void *world_void)
  254. {
  255. World *world(static_cast<World *>(world_void));
  256.  
  257. double current_time = Timer::GetTime();
  258. UTIL_PTR_VECTOR_FOREACH(world->maps, Map, map)
  259. {
  260. UTIL_PTR_VECTOR_FOREACH(map->npcs, NPC, npc)
  261. {
  262. if (npc->alive && npc->last_act + npc->act_speed < current_time)
  263. {
  264. npc->Act();
  265. }
  266. }
  267. }
  268. }
  269.  
  270. void world_recover(void *world_void)
  271. {
  272. World *world(static_cast<World *>(world_void));
  273.  
  274. PacketBuilder builder(PACKET_RECOVER, PACKET_PLAYER);
  275.  
  276. UTIL_PTR_VECTOR_FOREACH(world->characters, Character, character)
  277. {
  278. bool updated = false;
  279.  
  280. if (character->hp < character->maxhp)
  281. {
  282. character->hp += character->maxhp / 10;
  283. character->hp = std::min(character->hp, character->maxhp);
  284. updated = true;
  285.  
  286. if (character->party)
  287. {
  288. character->party->UpdateHP(*character);
  289. }
  290. }
  291.  
  292. if (character->tp < character->maxtp)
  293. {
  294. character->tp += character->maxtp / 10;
  295. character->tp = std::min(character->tp, character->maxtp);
  296. updated = true;
  297. }
  298.  
  299. if (updated)
  300. {
  301. builder.Reset();
  302. builder.AddShort(character->hp);
  303. builder.AddShort(character->tp);
  304. builder.AddShort(0); // ?
  305. character->player->client->SendBuilder(builder);
  306. }
  307. }
  308. }
  309.  
  310. void world_despawn_items(void *world_void)
  311. {
  312. World *world = static_cast<World *>(world_void);
  313.  
  314. UTIL_PTR_VECTOR_FOREACH(world->maps, Map, map)
  315. {
  316. restart_loop:
  317. UTIL_PTR_LIST_FOREACH(map->items, Map_Item, item)
  318. {
  319. if (item->unprotecttime < (Timer::GetTime() - static_cast<double>(world->config["ItemDespawnRate"])))
  320. {
  321. map->DelItem(item->uid, 0);
  322. goto restart_loop;
  323. }
  324. }
  325. }
  326. }
  327.  
  328. void world_timed_save(void *world_void)
  329. {
  330. World *world = static_cast<World *>(world_void);
  331.  
  332. UTIL_PTR_VECTOR_FOREACH(world->characters, Character, character)
  333. {
  334. //character->Refresh();
  335. character->Save();
  336. }
  337.  
  338. world->guildmanager->SaveAll();
  339. }
  340.  
  341. void mutetimer(void *world_void)
  342. {
  343. World *world = static_cast<World *>(world_void);
  344.  
  345. UTIL_PTR_VECTOR_FOREACH(world->characters, Character, character)
  346. {
  347. if(character->mute >= 1)
  348. {
  349. character->mute--;
  350. if(character->mute == 1)
  351. {
  352. character->ServerMsg("You may talk again. Behave next time.");
  353. character->mute = 0;
  354. }
  355. }
  356. }
  357. }
  358.  
  359. void world_speak_npcs(void *world_void)
  360. {
  361. World *world = static_cast<World *>(world_void);
  362.  
  363. UTIL_PTR_VECTOR_FOREACH(world->maps, Map, map)
  364. {
  365. UTIL_PTR_VECTOR_FOREACH(map->npcs, NPC, npc)
  366. {
  367. int rand = util::rand(1, 100);
  368. if(rand > 1 && rand < 3) //1% chance say first message
  369. {
  370. npc->Msg(static_cast<std::string>(world->npcsay_config[util::to_string(npc->id) + ".1"]));
  371. }
  372. else if(rand > 30 && rand < 32) //1% chance change message
  373. {
  374. npc->Msg(static_cast<std::string>(world->npcsay_config[util::to_string(npc->id) + ".2"]));
  375. }
  376. else if(rand > 70 && rand < 72) // 1% chance say 3rd
  377. {
  378. npc->Msg(static_cast<std::string>(world->npcsay_config[util::to_string(npc->id) + ".3"]));
  379. }
  380. }
  381. }
  382. }
  383.  
  384. void world_restart(void *world_void)
  385. {
  386. World *world = static_cast<World *>(world_void);
  387.  
  388. UTIL_PTR_VECTOR_FOREACH(world->characters, Character, from)
  389. {
  390. from->Restart();
  391. }
  392. }
  393.  
  394. World::World(util::array<std::string, 6> dbinfo, const Config &eoserv_config, const Config &admin_config)
  395. {
  396. if (int(this->timer.resolution * 1000.0) > 1)
  397. {
  398. Console::Out("Timers set at approx. %i ms resolution", int(this->timer.resolution * 1000.0));
  399. }
  400. else
  401. {
  402. Console::Out("Timers set at < 1 ms resolution");
  403. }
  404.  
  405. this->config = eoserv_config;
  406. this->admin_config = admin_config;
  407.  
  408. Database::Engine engine;
  409. if (dbinfo[0].compare("sqlite") == 0)
  410. {
  411. engine = Database::SQLite;
  412. }
  413. else
  414. {
  415. engine = Database::MySQL;
  416. }
  417. this->db.Connect(engine, dbinfo[1], util::to_int(dbinfo[5]), dbinfo[2], dbinfo[3], dbinfo[4]);
  418.  
  419. try
  420. {
  421. this->drops_config.Read(this->config["DropsFile"]);
  422. this->shops_config.Read(this->config["ShopsFile"]);
  423. this->arenas_config.Read(this->config["ArenasFile"]);
  424. this->formulas_config.Read(this->config["FormulasFile"]);
  425. this->home_config.Read(this->config["HomeFile"]);
  426. this->spells_config.Read(this->config["SpellsFile"]);
  427. this->npcsay_config.Read(this->config["NpcSpeachFile"]);
  428. this->extras_config.Read(this->config["ExtrasFile"]);
  429. this->wedding_config.Read(this->config["WeddingFile"]);
  430. }
  431. catch (std::runtime_error &e)
  432. {
  433. Console::Wrn(e.what());
  434. }
  435.  
  436. this->eif = new EIF(this->config["EIF"]);
  437. this->enf = new ENF(this->config["ENF"]);
  438. this->esf = new ESF(this->config["ESF"]);
  439. this->ecf = new ECF(this->config["ECF"]);
  440.  
  441. this->maps.resize(static_cast<int>(this->config["Maps"])+1);
  442. this->maps[0] = new Map(1, this);
  443. int loaded = 0;
  444. int npcs = 0;
  445. for (int i = 1; i <= static_cast<int>(this->config["Maps"]); ++i)
  446. {
  447. this->maps[i] = new Map(i, this);
  448. if (this->maps[i]->exists)
  449. {
  450. npcs += this->maps[i]->npcs.size();
  451. ++loaded;
  452. }
  453. }
  454. Console::Out("%i/%i maps loaded.", loaded, this->maps.size()-1);
  455. Console::Out("%i NPCs loaded.", npcs);
  456.  
  457. this->quests.resize(static_cast<int>(this->config["Quests"]));
  458. loaded = 0;
  459. for (int i = 1; i <= static_cast<int>(this->config["Quests"]); ++i)
  460. {
  461. this->quests[i-1] = new Quest(i, this);
  462. if (this->quests[i-1]->exists)
  463. ++loaded;
  464. }
  465. Console::Out("%i/%i quests loaded.", loaded, this->quests.size());
  466.  
  467. this->last_character_id = 0;
  468.  
  469. TimeEvent *event = new TimeEvent(world_spawn_npcs, this, 1.0, Timer::FOREVER);
  470. this->timer.Register(event);
  471. event->Release();
  472.  
  473. event = new TimeEvent(world_act_npcs, this, 0.05, Timer::FOREVER);
  474. this->timer.Register(event);
  475. event->Release();
  476.  
  477. event = new TimeEvent(world_execute_weddings, this, 1.0, Timer::FOREVER);
  478. this->timer.Register(event);
  479. event->Release();
  480.  
  481. event = new TimeEvent(world_recover, this, 90.0, Timer::FOREVER);
  482. this->timer.Register(event);
  483. event->Release();
  484.  
  485. event = new TimeEvent(world_speak_npcs, this, 25.0, Timer::FOREVER);
  486. this->timer.Register(event);
  487. event->Release();
  488.  
  489. event = new TimeEvent(mutetimer, this, 1.0, Timer::FOREVER);
  490. this->timer.Register(event);
  491. event->Release();
  492.  
  493. if (this->extras_config["HPdrain"])
  494. {
  495. event = new TimeEvent(world_hpdrain, this, static_cast<double>(this->extras_config["HPdrain"]), Timer::FOREVER);
  496. this->timer.Register(event);
  497. event->Release();
  498. }
  499.  
  500. if (this->extras_config["TPdrain"])
  501. {
  502. event = new TimeEvent(world_tpdrain, this, static_cast<double>(this->extras_config["TPdrain"]), Timer::FOREVER);
  503. this->timer.Register(event);
  504. event->Release();
  505. }
  506.  
  507. if (this->config["ItemDespawn"])
  508. {
  509. event = new TimeEvent(world_despawn_items, this, static_cast<double>(this->config["ItemDespawnCheck"]), Timer::FOREVER);
  510. this->timer.Register(event);
  511. event->Release();
  512. }
  513.  
  514. if (this->config["TimedSave"])
  515. {
  516. event = new TimeEvent(world_timed_save, this, static_cast<double>(this->config["TimedSave"]), Timer::FOREVER);
  517. this->timer.Register(event);
  518. event->Release();
  519. }
  520.  
  521. exp_table[0] = 0;
  522. for (std::size_t i = 1; i < sizeof(this->exp_table)/sizeof(int); ++i)
  523. {
  524. exp_table[i] = int(util::round(std::pow(double(i), 3.0) * 133.1));
  525. }
  526.  
  527. for (std::size_t i = 0; i < this->boards.size(); ++i)
  528. {
  529. this->boards[i] = new Board(i);
  530. }
  531.  
  532. this->hookmanager = new HookManager(this->config["ScriptDir"]);
  533.  
  534. this->guildmanager = new GuildManager(this);
  535.  
  536. this->LoadHome();
  537.  
  538. script_register(*this); // See scriptreg.cpp
  539.  
  540. FILE *fh = fopen(static_cast<std::string>(this->config["ScriptsFile"]).c_str(), "rt");
  541.  
  542. if (!fh)
  543. {
  544. Console::Wrn("Failed to open %s, no scripts will be loaded", static_cast<std::string>(this->config["ScriptsFile"]).c_str());
  545. }
  546.  
  547. char buf[4096];
  548.  
  549. while (fgets(buf, 4096, fh))
  550. {
  551. std::string sbuf(buf);
  552. sbuf = util::trim(sbuf);
  553.  
  554. if (sbuf.length() == 0 || sbuf[0] == '#')
  555. {
  556. continue;
  557. }
  558.  
  559. this->hookmanager->InitCall(sbuf.c_str());
  560. }
  561.  
  562. fclose(fh);
  563. }
  564.  
  565. void World::Restart()
  566. {
  567. TimeEvent *event = new TimeEvent(world_restart, this, 1.00, 6);
  568. this->timer.Register(event);
  569. event->Release();
  570. }
  571.  
  572. void World::LoadHome()
  573. {
  574. this->homes.clear();
  575.  
  576. std::tr1::unordered_map<std::string, Home *> temp_homes;
  577.  
  578. UTIL_UNORDERED_MAP_FOREACH_ALL(this->home_config, std::string, util::variant, hc)
  579. {
  580. std::vector<std::string> parts = util::explode('.', hc.first);
  581.  
  582. if (parts.size() < 2)
  583. {
  584. continue;
  585. }
  586.  
  587. if (parts[0] == "level")
  588. {
  589. int level = util::to_int(parts[1]);
  590.  
  591. std::tr1::unordered_map<std::string, Home *>::iterator home_iter = temp_homes.find(hc.second);
  592.  
  593. if (home_iter == temp_homes.end())
  594. {
  595. Home *home = new Home;
  596. home->id = static_cast<std::string>(hc.second);
  597. temp_homes[hc.second] = home;
  598. home->level = level;
  599. }
  600. else
  601. {
  602. home_iter->second->level = level;
  603. }
  604.  
  605. continue;
  606. }
  607.  
  608. Home *&home = temp_homes[parts[0]];
  609.  
  610. if (!home)
  611. {
  612. temp_homes[parts[0]] = home = new Home;
  613. home->id = parts[0];
  614. }
  615.  
  616. if (parts[1] == "name")
  617. {
  618. home->name = home->name = static_cast<std::string>(hc.second);
  619. }
  620. else if (parts[1] == "location")
  621. {
  622. std::vector<std::string> locparts = util::explode(',', hc.second);
  623. home->map = locparts.size() >= 1 ? util::to_int(locparts[0]) : 1;
  624. home->x = locparts.size() >= 2 ? util::to_int(locparts[1]) : 0;
  625. home->y = locparts.size() >= 3 ? util::to_int(locparts[2]) : 0;
  626. }
  627. }
  628.  
  629. UTIL_UNORDERED_MAP_FOREACH_ALL(temp_homes, std::string, Home *, home)
  630. {
  631. this->homes.push_back(home.second);
  632. home.second->Release();
  633. }
  634. }
  635.  
  636. int World::GenerateCharacterID()
  637. {
  638. return ++this->last_character_id;
  639. }
  640.  
  641. int World::GeneratePlayerID()
  642. {
  643. unsigned int lowest_free_id = 10000;
  644. restart_loop:
  645. UTIL_PTR_LIST_FOREACH(this->server->clients, EOClient, client)
  646. {
  647. if (client->id == lowest_free_id)
  648. {
  649. lowest_free_id = client->id + 1;
  650. goto restart_loop;
  651. }
  652. }
  653. return lowest_free_id;
  654. }
  655.  
  656. void World::Login(Character *character)
  657. {
  658. this->characters.push_back(character);
  659.  
  660. if (this->GetMap(character->mapid)->relog_x || this->GetMap(character->mapid)->relog_y)
  661. {
  662. character->x = this->GetMap(character->mapid)->relog_x;
  663. character->y = this->GetMap(character->mapid)->relog_y;
  664. }
  665.  
  666. this->GetMap(character->mapid)->Enter(character);
  667. }
  668.  
  669. void World::Logout(Character *character)
  670. {
  671. if (this->GetMap(character->mapid)->exists)
  672. {
  673. this->GetMap(character->mapid)->Leave(character);
  674. }
  675.  
  676. erase_first(this->characters, character);
  677. }
  678.  
  679. void World::Msg(Character *from, std::string message, bool echo)
  680. {
  681. message = util::text_cap(message, static_cast<int>(this->config["ChatMaxWidth"]) - util::text_width(util::ucfirst(from ? from->name : "Server") + " "));
  682.  
  683. PacketBuilder builder(PACKET_TALK, PACKET_MSG);
  684. builder.AddBreakString(from ? from->name : "Server");
  685. builder.AddBreakString(message);
  686.  
  687. UTIL_PTR_VECTOR_FOREACH(this->characters, Character, character)
  688. {
  689. if (!echo && *character == from)
  690. {
  691. continue;
  692. }
  693.  
  694. character->player->client->SendBuilder(builder);
  695. }
  696. }
  697.  
  698. void World::AdminMsg(Character *from, std::string message, int minlevel, bool echo)
  699. {
  700. message = util::text_cap(message, static_cast<int>(this->config["ChatMaxWidth"]) - util::text_width(util::ucfirst(from ? from->name : "Server") + " "));
  701.  
  702. PacketBuilder builder(PACKET_TALK, PACKET_ADMIN);
  703. builder.AddBreakString(from ? from->name : "Server");
  704. builder.AddBreakString(message);
  705.  
  706. UTIL_PTR_VECTOR_FOREACH(this->characters, Character, character)
  707. {
  708. if ((!echo && *character == from) || character->admin < minlevel)
  709. {
  710. continue;
  711. }
  712.  
  713. character->player->client->SendBuilder(builder);
  714. }
  715. }
  716.  
  717. void World::AnnounceMsg(Character *from, std::string message, bool echo)
  718. {
  719. message = util::text_cap(message, static_cast<int>(this->config["ChatMaxWidth"]) - util::text_width(util::ucfirst(from ? from->name : "Server") + " "));
  720.  
  721. PacketBuilder builder(PACKET_TALK, PACKET_ANNOUNCE);
  722. builder.AddBreakString(from ? from->name : "Server");
  723. builder.AddBreakString(message);
  724.  
  725. UTIL_PTR_VECTOR_FOREACH(this->characters, Character, character)
  726. {
  727. if (!echo && *character == from)
  728. {
  729. continue;
  730. }
  731.  
  732. character->player->client->SendBuilder(builder);
  733. }
  734. }
  735.  
  736. void World::ServerMsg(std::string message)
  737. {
  738. message = util::text_cap(message, static_cast<int>(this->config["ChatMaxWidth"]) - util::text_width("Server "));
  739.  
  740. PacketBuilder builder(PACKET_TALK, PACKET_SERVER);
  741. builder.AddString(message);
  742.  
  743. UTIL_PTR_VECTOR_FOREACH(this->characters, Character, character)
  744. {
  745. character->player->client->SendBuilder(builder);
  746. }
  747. }
  748.  
  749. void World::AdminReport(Character *from, std::string reportee, std::string message)
  750. {
  751. message = util::text_cap(message, static_cast<int>(this->config["ChatMaxWidth"]) - util::text_width(util::ucfirst(from->name) + " reports: " + reportee + ", "));
  752.  
  753. PacketBuilder builder(PACKET_ADMININTERACT, PACKET_REPLY);
  754. builder.AddChar(2); // message type
  755. builder.AddByte(255);
  756. builder.AddBreakString(from->name);
  757. builder.AddBreakString(message);
  758. builder.AddBreakString(reportee);
  759.  
  760. UTIL_PTR_VECTOR_FOREACH(this->characters, Character, character)
  761. {
  762. if (character->admin >= static_cast<int>(this->admin_config["reports"]))
  763. {
  764. character->player->client->SendBuilder(builder);
  765. }
  766. }
  767.  
  768. short boardid = static_cast<int>(this->server->world->config["AdminBoard"]) - 1;
  769.  
  770. if (static_cast<std::size_t>(boardid) < this->server->world->boards.size())
  771. {
  772. Board *admin_board = this->server->world->boards[boardid];
  773.  
  774. Board_Post *newpost = new Board_Post;
  775. newpost->id = ++admin_board->last_id;
  776. newpost->author = from->name;
  777. newpost->author_admin = from->admin;
  778. newpost->subject = std::string(" [Report] ") + util::ucfirst(from->name) + " reports: " + reportee;
  779. newpost->body = message;
  780. newpost->time = Timer::GetTime();
  781.  
  782. admin_board->posts.push_front(newpost);
  783.  
  784. if (admin_board->posts.size() > static_cast<std::size_t>(static_cast<int>(this->server->world->config["AdminBoardLimit"])))
  785. {
  786. admin_board->posts.pop_back();
  787. }
  788. }
  789. }
  790.  
  791. void World::AdminRequest(Character *from, std::string message)
  792. {
  793. message = util::text_cap(message, static_cast<int>(this->config["ChatMaxWidth"]) - util::text_width(util::ucfirst(from->name) + " needs help: "));
  794.  
  795. PacketBuilder builder(PACKET_ADMININTERACT, PACKET_REPLY);
  796. builder.AddChar(1); // message type
  797. builder.AddByte(255);
  798. builder.AddBreakString(from->name);
  799. builder.AddBreakString(message);
  800.  
  801. UTIL_PTR_VECTOR_FOREACH(this->characters, Character, character)
  802. {
  803. if (character->admin >= static_cast<int>(this->admin_config["reports"]))
  804. {
  805. character->player->client->SendBuilder(builder);
  806. }
  807. }
  808.  
  809. short boardid = static_cast<int>(this->server->world->config["AdminBoard"]) - 1;
  810.  
  811. if (static_cast<std::size_t>(boardid) < this->server->world->boards.size())
  812. {
  813. Board *admin_board = this->server->world->boards[boardid];
  814.  
  815. Board_Post *newpost = new Board_Post;
  816. newpost->id = ++admin_board->last_id;
  817. newpost->author = from->name;
  818. newpost->author_admin = from->admin;
  819. newpost->subject = std::string(" [Request] ") + util::ucfirst(from->name) + " needs help";
  820. newpost->body = message;
  821. newpost->time = Timer::GetTime();
  822.  
  823. admin_board->posts.push_front(newpost);
  824.  
  825. if (admin_board->posts.size() > static_cast<std::size_t>(static_cast<int>(this->server->world->config["AdminBoardLimit"])))
  826. {
  827. admin_board->posts.pop_back();
  828. }
  829. }
  830. }
  831.  
  832. void World::Rehash()
  833. {
  834. try
  835. {
  836. this->config.Read("config.ini");
  837. this->admin_config.Read("admin.ini");
  838. this->drops_config.Read(this->config["DropsFile"]);
  839. this->shops_config.Read(this->config["ShopsFile"]);
  840. this->arenas_config.Read(this->config["ArenasFile"]);
  841. this->formulas_config.Read(this->config["FormulasFile"]);
  842. this->home_config.Read(this->config["HomeFile"]);
  843. this->spells_config.Read(this->config["SpellsFile"]);
  844. this->npcsay_config.Read(this->config["NpcSpeachFile"]);
  845. this->extras_config.Read(this->config["ExtrasFile"]);
  846. this->wedding_config.Read(this->config["WeddingFile"]);
  847. }
  848. catch (std::runtime_error &e)
  849. {
  850. Console::Err(e.what());
  851. }
  852.  
  853. this->LoadHome();
  854.  
  855. UTIL_PTR_VECTOR_FOREACH(this->maps, Map, map)
  856. {
  857. map->LoadArena();
  858.  
  859. UTIL_PTR_VECTOR_FOREACH(map->npcs, NPC, npc)
  860. {
  861. npc->LoadShopDrop();
  862. }
  863. }
  864.  
  865. UTIL_PTR_VECTOR_FOREACH(this->quests, Quest, quest)
  866. {
  867. quest->Reload(this);
  868. }
  869. }
  870.  
  871. void World::ReloadPub()
  872. {
  873. this->eif->Read(this->config["EIF"]);
  874. this->enf->Read(this->config["ENF"]);
  875. this->esf->Read(this->config["ESF"]);
  876. this->ecf->Read(this->config["ECF"]);
  877.  
  878. std::string filename;
  879. std::FILE *fh;
  880. InitReply replycode;
  881.  
  882. for (int i = 0; i < 4; ++i)
  883. {
  884. std::string content;
  885.  
  886. switch (i)
  887. {
  888. case 0: filename = static_cast<std::string>(this->config["EIF"]); replycode = INIT_FILE_EIF; break;
  889. case 1: filename = static_cast<std::string>(this->config["ENF"]); replycode = INIT_FILE_ENF; break;
  890. case 2: filename = static_cast<std::string>(this->config["ESF"]); replycode = INIT_FILE_ESF; break;
  891. case 3: filename = static_cast<std::string>(this->config["ECF"]); replycode = INIT_FILE_ECF; break;
  892. }
  893.  
  894. fh = std::fopen(filename.c_str(), "rb");
  895.  
  896. if (!fh)
  897. {
  898. Console::Err("Could not load file: %s", filename.c_str());
  899. std::exit(1);
  900. }
  901.  
  902. do {
  903. char buf[4096];
  904. int len = std::fread(buf, sizeof(char), 4096, fh);
  905. content.append(buf, len);
  906. } while (!std::feof(fh));
  907.  
  908. std::fclose(fh);
  909.  
  910. PacketBuilder builder(0);
  911. builder.AddChar(replycode);
  912. builder.AddChar(1); // fileid
  913. builder.AddString(content);
  914.  
  915. UTIL_PTR_VECTOR_FOREACH(this->characters, Character, character)
  916. {
  917. character->player->client->SendBuilderRaw(builder);
  918. }
  919. }
  920.  
  921. UTIL_PTR_VECTOR_FOREACH(this->characters, Character, character)
  922. {
  923. character->Warp(character->mapid, character->x, character->y);
  924. }
  925. }
  926.  
  927. Character *World::GetCharacter(std::string name)
  928. {
  929. name = util::lowercase(name);
  930.  
  931. UTIL_PTR_VECTOR_FOREACH(this->characters, Character, character)
  932. {
  933. if (character->name.compare(name) == 0)
  934. {
  935. return *character;
  936. }
  937. }
  938.  
  939. return 0;
  940. }
  941.  
  942. Character *World::GetCharacterPID(unsigned int id)
  943. {
  944. UTIL_PTR_VECTOR_FOREACH(this->characters, Character, character)
  945. {
  946. if (character->player->id == id)
  947. {
  948. return *character;
  949. }
  950. }
  951.  
  952. return 0;
  953. }
  954.  
  955. Character *World::GetCharacterCID(unsigned int id)
  956. {
  957. UTIL_PTR_VECTOR_FOREACH(this->characters, Character, character)
  958. {
  959. if (character->id == id)
  960. {
  961. return *character;
  962. }
  963. }
  964.  
  965. return 0;
  966. }
  967.  
  968. Map *World::GetMap(short id)
  969. {
  970. try
  971. {
  972. return this->maps.at(id);
  973. }
  974. catch (...)
  975. {
  976. return this->maps.at(0);
  977. }
  978. }
  979.  
  980. Home *World::GetHome(Character *character)
  981. {
  982. Home *home = 0;
  983. static Home *null_home = new Home;
  984.  
  985. UTIL_PTR_VECTOR_FOREACH(this->homes, Home, h)
  986. {
  987. if (h->id == character->home)
  988. {
  989. return *h;
  990. }
  991. }
  992.  
  993. int current_home_level = -2;
  994. UTIL_PTR_VECTOR_FOREACH(this->homes, Home, h)
  995. {
  996. if (h->level <= character->level && h->level > current_home_level)
  997. {
  998. home = *h;
  999. current_home_level = h->level;
  1000. }
  1001. }
  1002.  
  1003. if (!home)
  1004. {
  1005. home = null_home;
  1006. }
  1007.  
  1008. return home;
  1009. }
  1010.  
  1011. Home *World::GetHome(std::string id)
  1012. {
  1013. UTIL_PTR_VECTOR_FOREACH(this->homes, Home, h)
  1014. {
  1015. if (h->id == id)
  1016. {
  1017. return *h;
  1018. }
  1019. }
  1020.  
  1021. return 0;
  1022. }
  1023.  
  1024. Quest *World::GetQuest(short id)
  1025. {
  1026. try
  1027. {
  1028. return this->quests.at(id-1);
  1029. }
  1030. catch (...)
  1031. {
  1032. return this->quests.at(0);
  1033. }
  1034. }
  1035.  
  1036. bool World::CharacterExists(std::string name)
  1037. {
  1038. Database_Result res = this->db.Query("SELECT 1 FROM `characters` WHERE `name` = '$'", name.c_str());
  1039. return !res.empty();
  1040. }
  1041.  
  1042. Character *World::CreateCharacter(Player *player, std::string name, Gender gender, int hairstyle, int haircolor, Skin race)
  1043. {
  1044. char buffer[1024];
  1045. std::string startmapinfo;
  1046. std::string startmapval;
  1047.  
  1048. if (static_cast<int>(this->config["StartMap"]))
  1049. {
  1050. startmapinfo = ", `map`, `x`, `y`";
  1051. snprintf(buffer, 1024, ",%i,%i,%i", static_cast<int>(this->config["StartMap"]), static_cast<int>(this->config["StartX"]), static_cast<int>(this->config["StartY"]));
  1052. startmapval = buffer;
  1053. }
  1054.  
  1055. this->db.Query("INSERT INTO `characters` (`name`, `account`, `gender`, `hairstyle`, `haircolor`, `race`, `inventory`, `bank`, `paperdoll`, `spells`, `quest`, `vars`@) VALUES ('$','$',#,#,#,#,'$','','$','$','',''@)",
  1056. startmapinfo.c_str(), name.c_str(), player->username.c_str(), gender, hairstyle, haircolor, race,
  1057. static_cast<std::string>(this->config["StartItems"]).c_str(), static_cast<std::string>(gender?this->config["StartEquipMale"]:this->config["StartEquipFemale"]).c_str(),
  1058. static_cast<std::string>(this->config["StartSpells"]).c_str(), startmapval.c_str());
  1059.  
  1060. return new Character(name, this);
  1061. }
  1062.  
  1063. void World::DeleteCharacter(std::string name)
  1064. {
  1065. this->db.Query("DELETE FROM `characters` WHERE name = '$'", name.c_str());
  1066. }
  1067.  
  1068. Player *World::Login(std::string username, std::string password)
  1069. {
  1070. password = sha256(static_cast<std::string>(this->config["PasswordSalt"]) + username + password);
  1071. Database_Result res = this->db.Query("SELECT 1 FROM `accounts` WHERE `username` = '$' AND `password` = '$'", username.c_str(), password.c_str());
  1072. if (res.empty())
  1073. {
  1074. return 0;
  1075. }
  1076. std::tr1::unordered_map<std::string, util::variant> row = res.front();
  1077.  
  1078. return new Player(username, this);
  1079. }
  1080.  
  1081. bool World::CreatePlayer(std::string username, std::string password, std::string fullname, std::string location, std::string email, std::string computer, std::string hdid, std::string ip)
  1082. {
  1083. password = sha256(static_cast<std::string>(this->config["PasswordSalt"]) + username + password);
  1084. Database_Result result = this->db.Query("INSERT INTO `accounts` (`username`, `password`, `fullname`, `location`, `email`, `computer`, `hdid`, `regip`, `created`) VALUES ('$','$','$','$','$','$','$','$',#)", username.c_str(), password.c_str(), fullname.c_str(), location.c_str(), email.c_str(), computer.c_str(), hdid.c_str(), ip.c_str(), std::time(0));
  1085. return !result.Error();
  1086. }
  1087.  
  1088. bool World::PlayerExists(std::string username)
  1089. {
  1090. Database_Result res = this->db.Query("SELECT 1 FROM `accounts` WHERE `username` = '$'", username.c_str());
  1091. return !res.empty();
  1092. }
  1093.  
  1094. bool World::PlayerOnline(std::string username)
  1095. {
  1096. if (!Player::ValidName(username))
  1097. {
  1098. return false;
  1099. }
  1100.  
  1101. UTIL_PTR_LIST_FOREACH(this->server->clients, EOClient, connection)
  1102. {
  1103. if (connection->player)
  1104. {
  1105. if (connection->player->username.compare(username) == 0)
  1106. {
  1107. return true;
  1108. }
  1109. }
  1110. }
  1111.  
  1112. return false;
  1113. }
  1114.  
  1115. void World::Kick(Character *from, Character *victim, bool announce)
  1116. {
  1117. if (announce)
  1118. {
  1119. std::string msg("Attention!! ");
  1120. msg += victim->name + " has been kicked ";
  1121. if (from) msg += "-" + from->name + " ";
  1122. msg += "[kicked]";
  1123. this->ServerMsg(msg);
  1124. }
  1125.  
  1126. victim->player->client->Close();
  1127. }
  1128.  
  1129. void World::Jail(Character *from, Character *victim, bool announce)
  1130. {
  1131. if (announce)
  1132. {
  1133. std::string msg("Attention!! ");
  1134. msg += victim->name + " has been removed from the game. ";
  1135. if (from) msg += "-" + from->name + " ";
  1136. msg += "[jailed]";
  1137. this->ServerMsg(msg);
  1138. }
  1139.  
  1140. victim->Warp(static_cast<int>(this->server->world->config["JailMap"]), static_cast<int>(this->server->world->config["JailX"]), static_cast<int>(this->server->world->config["JailY"]), WARP_ANIMATION_ADMIN);
  1141. }
  1142.  
  1143. void World::Wall(Character *from, Character *victim, bool announce)
  1144. {
  1145. if (announce)
  1146. {
  1147. std::string msg("Attention!!! ");//Says Attention
  1148. msg += victim->name + " has been "; //Bob has been
  1149. msg += "[Walled]";// Walled
  1150. if (from) msg += "-" + from->name + " ";//-Billy
  1151. this->ServerMsg(msg);
  1152. //Attention!!! Bob has been [Walled] -Billy
  1153. }
  1154.  
  1155. victim->Warp(static_cast<int>(this->server->world->config["WallMap"]), static_cast<int>(this->server->world->config["WallX"]), static_cast<int>(this->server->world->config["WallY"]), WARP_ANIMATION_ADMIN);
  1156. }
  1157.  
  1158. void World::Ban(Character *from, Character *victim, int duration, bool announce)
  1159. {
  1160. if (announce)
  1161. {
  1162. std::string msg("Attention!! ");
  1163. msg += victim->name + " has been booted from the game ";
  1164. if (from) msg += "-" + from->name + " ";
  1165. msg += "[banned]";
  1166. this->ServerMsg(msg);
  1167. }
  1168.  
  1169. std::string query("INSERT INTO bans (username, ip, hdid, expires, setter) VALUES ");
  1170.  
  1171. query += "('" + db.Escape(victim->player->username) + "', ";
  1172. query += util::to_string(static_cast<int>(victim->player->client->GetRemoteAddr())) + ", ";
  1173. query += util::to_string(victim->player->client->hdid) + ", ";
  1174. if (duration == -1)
  1175. {
  1176. query += "0";
  1177. }
  1178. else
  1179. {
  1180. query += util::to_string(int(std::time(0) + duration));
  1181. }
  1182. if (from)
  1183. {
  1184. query += ", '" + db.Escape(from->name) + "')";
  1185. }
  1186. else
  1187. {
  1188. query += ")";
  1189. }
  1190.  
  1191. db.Query(query.c_str(), std::time(0));
  1192.  
  1193. victim->player->client->Close();
  1194. }
  1195.  
  1196. int World::CheckBan(const std::string *username, const IPAddress *address, const int *hdid)
  1197. {
  1198. std::string query("SELECT COALESCE(MAX(expires),-1) AS expires FROM bans WHERE (");
  1199.  
  1200. if (!username && !address && !hdid)
  1201. {
  1202. return -1;
  1203. }
  1204.  
  1205. if (username)
  1206. {
  1207. query += "username = '";
  1208. query += db.Escape(*username);
  1209. query += "' OR ";
  1210. }
  1211.  
  1212. if (address)
  1213. {
  1214. query += "ip = ";
  1215. query += util::to_string(static_cast<int>(*const_cast<IPAddress *>(address)));
  1216. query += " OR ";
  1217. }
  1218.  
  1219. if (hdid)
  1220. {
  1221. query += "hdid = ";
  1222. query += util::to_string(*hdid);
  1223. query += " OR ";
  1224. }
  1225.  
  1226. Database_Result res = db.Query((query.substr(0, query.length()-4) + ") AND (expires > # OR expires = 0)").c_str(), std::time(0));
  1227.  
  1228. return static_cast<int>(res[0]["expires"]);
  1229. }
  1230.  
  1231. static std::list<int> PKExceptUnserialize(std::string serialized)
  1232. {
  1233. std::list<int> list;
  1234. std::size_t p = 0;
  1235. std::size_t lastp = std::numeric_limits<std::size_t>::max();
  1236.  
  1237. if (!serialized.empty() && *(serialized.end()-1) != ',')
  1238. {
  1239. serialized.push_back(',');
  1240. }
  1241.  
  1242. while ((p = serialized.find_first_of(',', p+1)) != std::string::npos)
  1243. {
  1244. list.push_back(util::to_int(serialized.substr(lastp+1, p-lastp-1)));
  1245. lastp = p;
  1246. }
  1247.  
  1248. return list;
  1249. }
  1250.  
  1251. bool World::PKExcept(const Map *map)
  1252. {
  1253. return this->PKExcept(map->id);
  1254. }
  1255.  
  1256. bool World::PKExcept(int mapid)
  1257. {
  1258. if (mapid == static_cast<int>(this->config["JailMap"]))
  1259. {
  1260. return true;
  1261. }
  1262.  
  1263. if (this->GetMap(mapid)->arena)
  1264. {
  1265. return true;
  1266. }
  1267.  
  1268. std::list<int> except_list = PKExceptUnserialize(this->config["PKExcept"]);
  1269.  
  1270. return std::find(except_list.begin(), except_list.end(), mapid) != except_list.end();
  1271. }
  1272.  
  1273. World::~World()
  1274. {
  1275. while (!this->characters.empty())
  1276. {
  1277. this->characters.back()->player->client->Close(true);
  1278. this->characters.back()->Destroy();
  1279. }
  1280.  
  1281. this->hookmanager->Release();
  1282. this->guildmanager->Release();
  1283. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement