Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* $Id: world.cpp 189 2010-04-27 06:18:38Z sausage $
- * EOSERV is released under the zlib license.
- * See LICENSE.txt for more info.
- */
- #include "world.hpp"
- #include "character.hpp"
- #include "config.hpp"
- #include "console.hpp"
- #include "database.hpp"
- #include "eoclient.hpp"
- #include "eodata.hpp"
- #include "eoserver.hpp"
- #include "guild.hpp"
- #include "hash.hpp"
- #include "hook.hpp"
- #include "map.hpp"
- #include "npc.hpp"
- #include "packet.hpp"
- #include "party.hpp"
- #include "player.hpp"
- #include "scriptreg.hpp"
- #include "util.hpp"
- #include "quest.hpp"
- void world_spawn_npcs(void *world_void)
- {
- World *world(static_cast<World *>(world_void));
- double spawnrate = world->config["SpawnRate"];
- double current_time = Timer::GetTime();
- UTIL_PTR_VECTOR_FOREACH(world->maps, Map, map)
- {
- UTIL_PTR_VECTOR_FOREACH(map->npcs, NPC, npc)
- {
- if ((!npc->alive && npc->dead_since + (double(npc->spawn_time) * spawnrate) < current_time)
- && (!npc->Data()->child || (npc->parent && npc->parent->alive && world->config["RespawnBossChildren"])))
- {
- #ifdef DEBUG
- Console::Dbg("Spawning NPC %i on map %i", npc->id, map->id);
- #endif // DEBUG
- npc->Spawn();
- }
- }
- }
- }
- void world_act_npcs(void *world_void)
- {
- World *world(static_cast<World *>(world_void));
- double current_time = Timer::GetTime();
- UTIL_PTR_VECTOR_FOREACH(world->maps, Map, map)
- {
- UTIL_PTR_VECTOR_FOREACH(map->npcs, NPC, npc)
- {
- if (npc->alive && npc->last_act + npc->act_speed < current_time)
- {
- npc->Act();
- }
- }
- }
- }
- void mine(void *world_void)
- {
- World *world(static_cast<World *>(world_void));
- PacketBuilder reply;
- int ItemID, ItemA, Map, X, Y, Dir, Wep, exp, Name,ore;
- for(int i = 0 ; i < static_cast<int>(world->mining_config["LocationAmount"]) ; i++)
- {
- ore = static_cast<int>(world->mining_config[util::to_string(i+1) + "ore"]);
- Name = static_cast<std::string>(world->mining_config[util::to_string(ore)+"OreName"]);
- exp = static_cast<int>(world->mining_config[util::to_string(ore)+"OreExp"]);
- ItemID = static_cast<int>(world->mining_config[util::to_string(ore)+"OreID"]);
- ItemA = 1;
- Wep = static_cast<int>(world->mining_config[util::to_string(ore)+"picaxeID"]);
- Map = static_cast<int>(world->mining_config[util::to_string(i+1) + ".map"]);
- X = static_cast<int>(world->mining_config[util::to_string(i+1) + ".x"]);
- Y = static_cast<int>(world->mining_config[util::to_string(i+1) + ".y"]);
- Dir = static_cast<int>(world->mining_config[util::to_string(i+1) + ".dir"]);
- UTIL_PTR_VECTOR_FOREACH(world->characters, Character, character)
- if (character->x == X && character->y == Y && character->direction == Dir && character->mining == 1 && character->mapid == Map && character->paperdoll[Character::Weapon] == Wep)
- {
- int random = util::rand(0 ,150);
- if (random < 25)
- {
- character->fishing = 0;
- character->ServerMsg("You mined some "+ Name + ".");
- character->AddItem(1, 1);
- reply.SetID(PACKET_ITEM, PACKET_GET);
- reply.AddShort(0);
- reply.AddShort(ItemA);
- reply.AddThree(ItemID);
- reply.AddChar(character->weight);
- reply.AddChar(character->maxweight);
- character->player->client->SendBuilder(reply);
- }
- else if (random >25)
- {
- character->fishing = 0;
- character->ServerMsg("You failed to mine any ore.");
- }
- }
- }
- }
- void woodcut(void *world_void)
- {
- World *world(static_cast<World *>(world_void));
- PacketBuilder reply;
- int ItemID, ItemA, Map, X, Y, Dir, Wep;
- for(int i = 0 ; i < static_cast<int>(world->woodcutting_config["LocationAmount"]) ; i++)
- {
- ItemID = static_cast<int>(world->woodcutting_config["ItemID"]);
- ItemA = static_cast<int>(world->woodcutting_config["ItemAmount"]);
- Wep = static_cast<int>(world->woodcutting_config["Weapon"]);
- Map = static_cast<int>(world->woodcutting_config[util::to_string(i+1) + ".map"]);
- X = static_cast<int>(world->woodcutting_config[util::to_string(i+1) + ".x"]);
- Y = static_cast<int>(world->woodcutting_config[util::to_string(i+1) + ".y"]);
- Dir = static_cast<int>(world->woodcutting_config[util::to_string(i+1) + ".dir"]);
- UTIL_PTR_VECTOR_FOREACH(world->characters, Character, character)
- if (character->x == X && character->y == Y && character->direction == Dir && character->woodcutting == 1 && character->mapid == Map && character->paperdoll[Character::Weapon] == Wep)
- {
- int random = util::rand(0 ,150);
- if (random < 25)
- {
- character->woodcutting = 0;
- character->ServerMsg("You cut the tree.");
- character->AddItem(1, 1);
- reply.SetID(PACKET_ITEM, PACKET_GET);
- reply.AddShort(0);
- reply.AddShort(ItemA);
- reply.AddThree(ItemID);
- reply.AddChar(character->weight);
- reply.AddChar(character->maxweight);
- character->player->client->SendBuilder(reply);
- }
- else if (random >25)
- {
- character->woodcutting = 0;
- character->ServerMsg("You failed to cut the tree.");
- }
- }
- }
- }
- void fishcatch(void *world_void)
- {
- World *world(static_cast<World *>(world_void));
- PacketBuilder reply;
- int ItemID,ItemID2, ItemA, Map, X, Y, Dir, Wep;
- for(int i = 0 ; i < static_cast<int>(world->fish_config["LocationAmount"]) ; i++)
- {
- ItemID = static_cast<int>(world->fish_config["ItemID"]);
- ItemID2 = static_cast<int>(world->fish_config["ItemID2"]);
- ItemA = static_cast<int>(world->fish_config["ItemAmount"]);
- Wep = static_cast<int>(world->fish_config["Weapon"]);
- Map = static_cast<int>(world->fish_config[util::to_string(i+1) + ".map"]);
- X = static_cast<int>(world->fish_config[util::to_string(i+1) + ".x"]);
- Y = static_cast<int>(world->fish_config[util::to_string(i+1) + ".y"]);
- Dir = static_cast<int>(world->fish_config[util::to_string(i+1) + ".dir"]);
- UTIL_PTR_VECTOR_FOREACH(world->characters, Character, character)
- if (character->x == X && character->y == Y && character->direction == Dir && character->fishing == 1 && character->mapid == Map && character->paperdoll[Character::Weapon] == Wep)
- {
- int random = util::rand(0 ,150);
- if (random < 25)
- {
- character->fishing = 0;
- character->ServerMsg("You caught a fish " + character->name + ".");
- character->AddItem(1, 1);
- reply.SetID(PACKET_ITEM, PACKET_GET);
- reply.AddShort(0);
- reply.AddShort(ItemA);
- reply.AddThree(ItemID);
- reply.AddChar(character->weight);
- reply.AddChar(character->maxweight);
- character->player->client->SendBuilder(reply);
- }
- if (random > 25 && random < 50)
- {
- character->fishing = 0;
- character->ServerMsg("You caught a fish " + character->name + ".");
- character->AddItem(1, 1);
- reply.SetID(PACKET_ITEM, PACKET_GET);
- reply.AddShort(0);
- reply.AddShort(ItemA);
- reply.AddThree(ItemID2);
- reply.AddChar(character->weight);
- reply.AddChar(character->maxweight);
- character->player->client->SendBuilder(reply);
- }
- else if (random >50)
- {
- character->fishing = 0;
- character->ServerMsg("You failed to catch a fish " + character->name + ".");
- }
- }
- }
- }
- void world_execute_weddings(void *world_void)
- {
- World *world = static_cast<World *>(world_void);
- double now = Timer::GetTime();
- UTIL_PTR_VECTOR_FOREACH(world->maps, Map, map)
- {
- UTIL_PTR_VECTOR_FOREACH(map->npcs, NPC, npc)
- {
- if (npc->marriage && npc->marriage->request_accepted)
- {
- if (!npc->marriage->partner[0] || !npc->marriage->partner[1])
- {
- npc->ShowDialog("Something went wrong. Stopping wedding");
- npc->marriage = 0;
- continue;
- }
- else if (!npc->marriage->partner[0]->online || !npc->marriage->partner[1]->online)
- {
- npc->ShowDialog("One of the wedding partners has exited the game. Stopping wedding");
- npc->marriage = 0;
- continue;
- }
- else if (npc->marriage->partner[0]->map != npc->map || npc->marriage->partner[1]->map != npc->map)
- {
- npc->ShowDialog("One of the wedding partners has left the map. Stopping wedding");
- npc->marriage = 0;
- continue;
- }
- else if ((npc->marriage->state == 5 && npc->marriage->partner_accepted[0]) || (npc->marriage->state == 8 && npc->marriage->partner_accepted[1]))
- {
- ++npc->marriage->state;
- }
- else if (npc->marriage->last_execution + (util::to_int(world->config["PriestDialogInterval"])) <= now)
- {
- switch (npc->marriage->state)
- {
- case 1: // Starting state
- {
- 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.");
- ++npc->marriage->state;
- }
- break;
- case 2: // second dialog
- {
- 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.");
- ++npc->marriage->state;
- }
- break;
- case 3: // Partner 1 question
- {
- 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?");
- ++npc->marriage->state;
- }
- break;
- case 4: // Partner 1 question box
- {
- PacketBuilder builder(PACKET_PRIEST, PACKET_REPLY);
- builder.AddChar(PRIEST_REQUEST);
- npc->marriage->partner[0]->player->client->SendBuilder(builder);
- ++npc->marriage->state;
- }
- break;
- case 5: break; // Waiting for Partner 1 acceptance
- case 6: // Recived agreement from partner 1
- {
- 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?");
- ++npc->marriage->state;
- }
- break;
- case 7: // Partner 2 question box
- {
- PacketBuilder builder(PACKET_PRIEST, PACKET_REPLY);
- builder.AddChar(PRIEST_REQUEST);
- npc->marriage->partner[1]->player->client->SendBuilder(builder);
- ++npc->marriage->state;
- }
- break;
- case 8: break; // Waiting for Partner 2 acceptance
- case 9: // Rings message
- {
- npc->ShowDialog("Let these rings be given and received as a token of your affection, sincerity and trust in one another.");
- ++npc->marriage->state;
- }
- break;
- case 10:
- {
- PacketBuilder builder(PACKET_ITEM, static_cast<PacketAction>(26));
- builder.AddShort(util::to_int(world->config["WeddingRing"]));
- builder.AddThree(1);
- for (int i = 0; i < 2; ++i)
- {
- npc->marriage->partner[i]->AddItem(util::to_int(world->config["WeddingRing"]), 1);
- npc->marriage->partner[i]->player->client->SendBuilder(builder);
- }
- ++npc->marriage->state;
- }
- case 11:
- {
- npc->ShowDialog("Please place these rings on eachothers finger");
- ++npc->marriage->state;
- }
- break;
- case 12: // Waiting for ring equiping
- {
- int effect = util::to_int(util::explode(',', world->config["WeddingEffects"])[0]);
- for (int i = 0; i < 2; ++i)
- npc->marriage->partner[i]->Effect(effect);
- 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.");
- ++npc->marriage->state;
- }
- break;
- case 13: // Next effect
- {
- int effect = util::to_int(util::explode(',', world->config["WeddingEffects"])[1]);
- for (int i = 0; i < 2; ++i)
- npc->marriage->partner[i]->Effect(effect);
- ++npc->marriage->state;
- }
- break;
- case 14: // Next effect
- {
- npc->ShowDialog("Congratulations to the couple!");
- int effect = util::to_int(util::explode(',', world->config["WeddingEffects"])[2]);
- for (int i = 0; i < 2; ++i)
- npc->marriage->partner[i]->Effect(effect);
- npc->marriage->partner[0]->partner = npc->marriage->partner[1]->name;
- npc->marriage->partner[0]->fiance = "";
- npc->marriage->partner[1]->partner = npc->marriage->partner[0]->name;
- npc->marriage->partner[1]->fiance = "";
- npc->marriage = 0;
- }
- break;
- default: Console::Err("Invalid state for marriage ceremony."); npc->marriage = 0;
- }
- if (npc->marriage)
- npc->marriage->last_execution = Timer::GetTime();
- }
- }
- }
- }
- }
- void world_recover(void *world_void)
- {
- World *world(static_cast<World *>(world_void));
- PacketBuilder builder(PACKET_RECOVER, PACKET_PLAYER);
- UTIL_PTR_VECTOR_FOREACH(world->characters, Character, character)
- {
- bool updated = false;
- if (character->hp < character->maxhp)
- {
- character->hp += character->maxhp / 10;
- character->hp = std::min(character->hp, character->maxhp);
- updated = true;
- if (character->party)
- {
- character->party->UpdateHP(*character);
- }
- }
- if (character->tp < character->maxtp)
- {
- character->tp += character->maxtp / 10;
- character->tp = std::min(character->tp, character->maxtp);
- updated = true;
- }
- if (updated)
- {
- builder.Reset();
- builder.AddShort(character->hp);
- builder.AddShort(character->tp);
- builder.AddShort(0); // ?
- character->player->client->SendBuilder(builder);
- }
- }
- }
- void world_despawn_items(void *world_void)
- {
- World *world = static_cast<World *>(world_void);
- UTIL_PTR_VECTOR_FOREACH(world->maps, Map, map)
- {
- restart_loop:
- UTIL_PTR_LIST_FOREACH(map->items, Map_Item, item)
- {
- if (item->unprotecttime < (Timer::GetTime() - static_cast<double>(world->config["ItemDespawnRate"])))
- {
- map->DelItem(item->uid, 0);
- goto restart_loop;
- }
- }
- }
- }
- void world_timed_save(void *world_void)
- {
- World *world = static_cast<World *>(world_void);
- UTIL_PTR_VECTOR_FOREACH(world->characters, Character, character)
- {
- character->Save();
- }
- world->guildmanager->SaveAll();
- }
- void world_speak_npcs(void *world_void)
- {
- World *world = static_cast<World *>(world_void);
- UTIL_PTR_VECTOR_FOREACH(world->maps, Map, map)
- {
- UTIL_PTR_VECTOR_FOREACH(map->npcs, NPC, npc)
- {
- int rand = util::rand(1, 100);
- if(rand > 1 && rand < 3) //1% chance say first message
- {
- npc->Msg(static_cast<std::string>(world->npcsay_config[util::to_string(npc->id) + ".1"]));
- }
- else if(rand > 30 && rand < 32) //1% chance change message
- {
- npc->Msg(static_cast<std::string>(world->npcsay_config[util::to_string(npc->id) + ".2"]));
- }
- else if(rand > 70 && rand < 72) // 1% chance say 3rd
- {
- npc->Msg(static_cast<std::string>(world->npcsay_config[util::to_string(npc->id) + ".3"]));
- }
- }
- }
- }
- void world_shine_god(void *world_void)
- {
- World *world = static_cast<World *>(world_void);
- UTIL_PTR_VECTOR_FOREACH(world->maps, Map, map)
- {
- map->Shine_God();
- }
- }
- World::World(util::array<std::string, 6> dbinfo, const Config &eoserv_config, const Config &admin_config)
- {
- if (int(this->timer.resolution * 1000.0) > 1)
- {
- Console::Out("Timers set at approx. %i ms resolution", int(this->timer.resolution * 1000.0));
- }
- else
- {
- Console::Out("Timers set at < 1 ms resolution");
- }
- this->config = eoserv_config;
- this->admin_config = admin_config;
- Database::Engine engine;
- if (dbinfo[0].compare("sqlite") == 0)
- {
- engine = Database::SQLite;
- }
- else
- {
- engine = Database::MySQL;
- }
- this->db.Connect(engine, dbinfo[1], util::to_int(dbinfo[5]), dbinfo[2], dbinfo[3], dbinfo[4]);
- try
- {
- this->drops_config.Read(this->config["DropsFile"]);
- this->shops_config.Read(this->config["ShopsFile"]);
- this->arenas_config.Read(this->config["ArenasFile"]);
- this->formulas_config.Read(this->config["FormulasFile"]);
- this->home_config.Read(this->config["HomeFile"]);
- this->spells_config.Read(this->config["SpellsFile"]);
- this->warps_config.Read(this->config["WarpFile"]);
- this->npcsay_config.Read(this->config["NpcSpeachFile"]);
- this->effects_config.Read(this->config["EffectsFile"]);
- this->pet_config.Read(this->config["PetFile"]);
- this->fish_config.Read(this->config["FishFile"]);
- this->magicscroll_config.Read(this->config["MagicScrollFile"]);
- this->mining_config.Read(this->config["MiningFile"]);
- this->woodcutting_config.Read(this->config["WoodcuttingFile"]);
- }
- catch (std::runtime_error &e)
- {
- Console::Wrn(e.what());
- }
- this->eif = new EIF(this->config["EIF"]);
- this->enf = new ENF(this->config["ENF"]);
- this->esf = new ESF(this->config["ESF"]);
- this->ecf = new ECF(this->config["ECF"]);
- this->maps.resize(static_cast<int>(this->config["Maps"])+1);
- this->maps[0] = new Map(1, this); // Just in case
- int loaded = 0;
- int npcs = 0;
- for (int i = 1; i <= static_cast<int>(this->config["Maps"]); ++i)
- {
- this->maps[i] = new Map(i, this);
- if (this->maps[i]->exists)
- {
- npcs += this->maps[i]->npcs.size();
- ++loaded;
- }
- }
- Console::Out("%i/%i maps loaded.", loaded, this->maps.size()-1);
- Console::Out("%i NPCs loaded.", npcs);
- this->quests.resize(static_cast<int>(this->config["Quests"]));
- loaded = 0;
- for (int i = 1; i <= static_cast<int>(this->config["Quests"]); ++i)
- {
- this->quests[i-1] = new Quest(i, this);
- if (this->quests[i-1]->exists)
- ++loaded;
- }
- Console::Out("%i/%i quests loaded.", loaded, this->quests.size());
- this->last_character_id = 0;
- TimeEvent *event = new TimeEvent(world_spawn_npcs, this, 1.0, Timer::FOREVER);
- this->timer.Register(event);
- event->Release();
- event = new TimeEvent(world_act_npcs, this, 0.05, Timer::FOREVER);
- this->timer.Register(event);
- event->Release();
- event = new TimeEvent(world_recover, this, 90.0, Timer::FOREVER);
- this->timer.Register(event);
- event->Release();
- event = new TimeEvent(world_speak_npcs, this, 25.0, Timer::FOREVER);
- this->timer.Register(event);
- event->Release();
- event = new TimeEvent(world_shine_god, this, 1.00, Timer::FOREVER);
- this->timer.Register(event);
- event->Release();
- if (this->config["ItemDespawn"])
- {
- event = new TimeEvent(world_despawn_items, this, static_cast<double>(this->config["ItemDespawnCheck"]), Timer::FOREVER);
- this->timer.Register(event);
- event->Release();
- }
- if (this->config["TimedSave"])
- {
- event = new TimeEvent(world_timed_save, this, static_cast<double>(this->config["TimedSave"]), Timer::FOREVER);
- this->timer.Register(event);
- event->Release();
- }
- exp_table[0] = 0;
- for (std::size_t i = 1; i < sizeof(this->exp_table)/sizeof(int); ++i)
- {
- exp_table[i] = int(util::round(std::pow(double(i), 3.0) * 133.1));
- }
- for (std::size_t i = 0; i < this->boards.size(); ++i)
- {
- this->boards[i] = new Board(i);
- }
- this->hookmanager = new HookManager(this->config["ScriptDir"]);
- this->guildmanager = new GuildManager(this);
- this->LoadHome();
- script_register(*this); // See scriptreg.cpp
- FILE *fh = fopen(static_cast<std::string>(this->config["ScriptsFile"]).c_str(), "rt");
- if (!fh)
- {
- Console::Wrn("Failed to open %s, no scripts will be loaded", static_cast<std::string>(this->config["ScriptsFile"]).c_str());
- }
- char buf[4096];
- while (fgets(buf, 4096, fh))
- {
- std::string sbuf(buf);
- sbuf = util::trim(sbuf);
- if (sbuf.length() == 0 || sbuf[0] == '#')
- {
- continue;
- }
- this->hookmanager->InitCall(sbuf.c_str());
- }
- fclose(fh);
- }
- void World::LoadHome()
- {
- this->homes.clear();
- std::tr1::unordered_map<std::string, Home *> temp_homes;
- UTIL_UNORDERED_MAP_FOREACH_ALL(this->home_config, std::string, util::variant, hc)
- {
- std::vector<std::string> parts = util::explode('.', hc.first);
- if (parts.size() < 2)
- {
- continue;
- }
- if (parts[0] == "level")
- {
- int level = util::to_int(parts[1]);
- std::tr1::unordered_map<std::string, Home *>::iterator home_iter = temp_homes.find(hc.second);
- if (home_iter == temp_homes.end())
- {
- Home *home = new Home;
- home->id = static_cast<std::string>(hc.second);
- temp_homes[hc.second] = home;
- home->level = level;
- }
- else
- {
- home_iter->second->level = level;
- }
- continue;
- }
- Home *&home = temp_homes[parts[0]];
- if (!home)
- {
- temp_homes[parts[0]] = home = new Home;
- home->id = parts[0];
- }
- if (parts[1] == "name")
- {
- home->name = home->name = static_cast<std::string>(hc.second);
- }
- else if (parts[1] == "location")
- {
- std::vector<std::string> locparts = util::explode(',', hc.second);
- home->map = locparts.size() >= 1 ? util::to_int(locparts[0]) : 1;
- home->x = locparts.size() >= 2 ? util::to_int(locparts[1]) : 0;
- home->y = locparts.size() >= 3 ? util::to_int(locparts[2]) : 0;
- }
- }
- UTIL_UNORDERED_MAP_FOREACH_ALL(temp_homes, std::string, Home *, home)
- {
- this->homes.push_back(home.second);
- home.second->Release();
- }
- }
- int World::GenerateCharacterID()
- {
- return ++this->last_character_id;
- }
- void World::fishing(Character *from)
- {
- from->player->character->ServerMsg("Waiting for a bite...");
- TimeEvent *event = new TimeEvent(fishcatch, this, 10.0, 1);
- this->timer.Register(event);
- event->Release();
- }
- void World::mining(Character *from)
- {
- from->player->character->ServerMsg("Hitting the rock...");
- TimeEvent *event = new TimeEvent(mine, this, 10.0, 1);
- this->timer.Register(event);
- event->Release();
- }
- void World::woodcutting(Character *from)
- {
- from->player->character->ServerMsg("Hitting the tree...");
- TimeEvent *event = new TimeEvent(woodcut, this, 10.0, 1);
- this->timer.Register(event);
- event->Release();
- }
- int World::GeneratePlayerID()
- {
- unsigned int lowest_free_id = 10000;
- restart_loop:
- UTIL_PTR_LIST_FOREACH(this->server->clients, EOClient, client)
- {
- if (client->id == lowest_free_id)
- {
- lowest_free_id = client->id + 1;
- goto restart_loop;
- }
- }
- return lowest_free_id;
- }
- void World::Login(Character *character)
- {
- this->characters.push_back(character);
- if (this->GetMap(character->mapid)->relog_x || this->GetMap(character->mapid)->relog_y)
- {
- character->x = this->GetMap(character->mapid)->relog_x;
- character->y = this->GetMap(character->mapid)->relog_y;
- }
- this->GetMap(character->mapid)->Enter(character);
- }
- void World::Logout(Character *character)
- {
- if (this->GetMap(character->mapid)->exists)
- {
- this->GetMap(character->mapid)->Leave(character);
- }
- erase_first(this->characters, character);
- }
- void World::Msg(Character *from, std::string message, bool echo)
- {
- message = util::text_cap(message, static_cast<int>(this->config["ChatMaxWidth"]) - util::text_width(util::ucfirst(from ? from->name : "Server") + " "));
- PacketBuilder builder(PACKET_TALK, PACKET_MSG);
- builder.AddBreakString(from ? from->name : "Server");
- builder.AddBreakString(message);
- UTIL_PTR_VECTOR_FOREACH(this->characters, Character, character)
- {
- if (!echo && *character == from)
- {
- continue;
- }
- character->player->client->SendBuilder(builder);
- }
- }
- void World::AdminMsg(Character *from, std::string message, int minlevel, bool echo)
- {
- message = util::text_cap(message, static_cast<int>(this->config["ChatMaxWidth"]) - util::text_width(util::ucfirst(from ? from->name : "Server") + " "));
- PacketBuilder builder(PACKET_TALK, PACKET_ADMIN);
- builder.AddBreakString(from ? from->name : "Server");
- builder.AddBreakString(message);
- UTIL_PTR_VECTOR_FOREACH(this->characters, Character, character)
- {
- if ((!echo && *character == from) || character->admin < minlevel)
- {
- continue;
- }
- character->player->client->SendBuilder(builder);
- }
- }
- void World::AnnounceMsg(Character *from, std::string message, bool echo)
- {
- message = util::text_cap(message, static_cast<int>(this->config["ChatMaxWidth"]) - util::text_width(util::ucfirst(from ? from->name : "Server") + " "));
- PacketBuilder builder(PACKET_TALK, PACKET_ANNOUNCE);
- builder.AddBreakString(from ? from->name : "Server");
- builder.AddBreakString(message);
- UTIL_PTR_VECTOR_FOREACH(this->characters, Character, character)
- {
- if (!echo && *character == from)
- {
- continue;
- }
- character->player->client->SendBuilder(builder);
- }
- }
- void World::ServerMsg(std::string message)
- {
- message = util::text_cap(message, static_cast<int>(this->config["ChatMaxWidth"]) - util::text_width("Server "));
- PacketBuilder builder(PACKET_TALK, PACKET_SERVER);
- builder.AddString(message);
- UTIL_PTR_VECTOR_FOREACH(this->characters, Character, character)
- {
- character->player->client->SendBuilder(builder);
- }
- }
- void World::AdminReport(Character *from, std::string reportee, std::string message)
- {
- message = util::text_cap(message, static_cast<int>(this->config["ChatMaxWidth"]) - util::text_width(util::ucfirst(from->name) + " reports: " + reportee + ", "));
- PacketBuilder builder(PACKET_ADMININTERACT, PACKET_REPLY);
- builder.AddChar(2); // message type
- builder.AddByte(255);
- builder.AddBreakString(from->name);
- builder.AddBreakString(message);
- builder.AddBreakString(reportee);
- UTIL_PTR_VECTOR_FOREACH(this->characters, Character, character)
- {
- if (character->admin >= static_cast<int>(this->admin_config["reports"]))
- {
- character->player->client->SendBuilder(builder);
- }
- }
- short boardid = static_cast<int>(this->server->world->config["AdminBoard"]) - 1;
- if (static_cast<std::size_t>(boardid) < this->server->world->boards.size())
- {
- Board *admin_board = this->server->world->boards[boardid];
- Board_Post *newpost = new Board_Post;
- newpost->id = ++admin_board->last_id;
- newpost->author = from->name;
- newpost->author_admin = from->admin;
- newpost->subject = std::string(" [Report] ") + util::ucfirst(from->name) + " reports: " + reportee;
- newpost->body = message;
- newpost->time = Timer::GetTime();
- admin_board->posts.push_front(newpost);
- if (admin_board->posts.size() > static_cast<std::size_t>(static_cast<int>(this->server->world->config["AdminBoardLimit"])))
- {
- admin_board->posts.pop_back();
- }
- }
- }
- void World::AdminRequest(Character *from, std::string message)
- {
- message = util::text_cap(message, static_cast<int>(this->config["ChatMaxWidth"]) - util::text_width(util::ucfirst(from->name) + " needs help: "));
- PacketBuilder builder(PACKET_ADMININTERACT, PACKET_REPLY);
- builder.AddChar(1); // message type
- builder.AddByte(255);
- builder.AddBreakString(from->name);
- builder.AddBreakString(message);
- UTIL_PTR_VECTOR_FOREACH(this->characters, Character, character)
- {
- if (character->admin >= static_cast<int>(this->admin_config["reports"]))
- {
- character->player->client->SendBuilder(builder);
- }
- }
- short boardid = static_cast<int>(this->server->world->config["AdminBoard"]) - 1;
- if (static_cast<std::size_t>(boardid) < this->server->world->boards.size())
- {
- Board *admin_board = this->server->world->boards[boardid];
- Board_Post *newpost = new Board_Post;
- newpost->id = ++admin_board->last_id;
- newpost->author = from->name;
- newpost->author_admin = from->admin;
- newpost->subject = std::string(" [Request] ") + util::ucfirst(from->name) + " needs help";
- newpost->body = message;
- newpost->time = Timer::GetTime();
- admin_board->posts.push_front(newpost);
- if (admin_board->posts.size() > static_cast<std::size_t>(static_cast<int>(this->server->world->config["AdminBoardLimit"])))
- {
- admin_board->posts.pop_back();
- }
- }
- }
- void World::Rehash()
- {
- try
- {
- this->config.Read("config.ini");
- this->admin_config.Read("admin.ini");
- this->drops_config.Read(this->config["DropsFile"]);
- this->shops_config.Read(this->config["ShopsFile"]);
- this->arenas_config.Read(this->config["ArenasFile"]);
- this->formulas_config.Read(this->config["FormulasFile"]);
- this->home_config.Read(this->config["HomeFile"]);
- this->spells_config.Read(this->config["SpellsFile"]);
- this->warps_config.Read(this->config["WarpFile"]);
- this->npcsay_config.Read(this->config["NpcSpeachFile"]);
- this->effects_config.Read(this->config["EffectsFile"]);
- this->pet_config.Read(this->config["PetFile"]);
- this->fish_config.Read(this->config["FishFile"]);
- this->magicscroll_config.Read(this->config["MagicScrollFile"]);
- this->mining_config.Read(this->config["MiningFile"]);
- this->woodcutting_config.Read(this->config["WoodcuttingFile"]);
- }
- catch (std::runtime_error &e)
- {
- Console::Err(e.what());
- }
- this->LoadHome();
- UTIL_PTR_VECTOR_FOREACH(this->maps, Map, map)
- {
- map->LoadArena();
- UTIL_PTR_VECTOR_FOREACH(map->npcs, NPC, npc)
- {
- npc->LoadShopDrop();
- }
- }
- UTIL_PTR_VECTOR_FOREACH(this->quests, Quest, quest)
- {
- quest->Reload(this);
- }
- }
- void World::ReloadPub()
- {
- this->eif->Read(this->config["EIF"]);
- this->enf->Read(this->config["ENF"]);
- this->esf->Read(this->config["ESF"]);
- this->ecf->Read(this->config["ECF"]);
- std::string filename;
- std::FILE *fh;
- InitReply replycode;
- for (int i = 0; i < 4; ++i)
- {
- std::string content;
- switch (i)
- {
- case 0: filename = static_cast<std::string>(this->config["EIF"]); replycode = INIT_FILE_EIF; break;
- case 1: filename = static_cast<std::string>(this->config["ENF"]); replycode = INIT_FILE_ENF; break;
- case 2: filename = static_cast<std::string>(this->config["ESF"]); replycode = INIT_FILE_ESF; break;
- case 3: filename = static_cast<std::string>(this->config["ECF"]); replycode = INIT_FILE_ECF; break;
- }
- fh = std::fopen(filename.c_str(), "rb");
- if (!fh)
- {
- Console::Err("Could not load file: %s", filename.c_str());
- std::exit(1);
- }
- do {
- char buf[4096];
- int len = std::fread(buf, sizeof(char), 4096, fh);
- content.append(buf, len);
- } while (!std::feof(fh));
- std::fclose(fh);
- PacketBuilder builder(0);
- builder.AddChar(replycode);
- builder.AddChar(1); // fileid
- builder.AddString(content);
- UTIL_PTR_VECTOR_FOREACH(this->characters, Character, character)
- {
- character->player->client->SendBuilderRaw(builder);
- }
- }
- UTIL_PTR_VECTOR_FOREACH(this->characters, Character, character)
- {
- character->Warp(character->mapid, character->x, character->y);
- }
- }
- Character *World::GetCharacter(std::string name)
- {
- name = util::lowercase(name);
- UTIL_PTR_VECTOR_FOREACH(this->characters, Character, character)
- {
- if (character->name.compare(name) == 0)
- {
- return *character;
- }
- }
- return 0;
- }
- Character *World::GetCharacterPID(unsigned int id)
- {
- UTIL_PTR_VECTOR_FOREACH(this->characters, Character, character)
- {
- if (character->player->id == id)
- {
- return *character;
- }
- }
- return 0;
- }
- Character *World::GetCharacterCID(unsigned int id)
- {
- UTIL_PTR_VECTOR_FOREACH(this->characters, Character, character)
- {
- if (character->id == id)
- {
- return *character;
- }
- }
- return 0;
- }
- Map *World::GetMap(short id)
- {
- try
- {
- return this->maps.at(id);
- }
- catch (...)
- {
- return this->maps.at(0);
- }
- }
- Home *World::GetHome(Character *character)
- {
- Home *home = 0;
- static Home *null_home = new Home;
- UTIL_PTR_VECTOR_FOREACH(this->homes, Home, h)
- {
- if (h->id == character->home)
- {
- return *h;
- }
- }
- int current_home_level = -2;
- UTIL_PTR_VECTOR_FOREACH(this->homes, Home, h)
- {
- if (h->level <= character->level && h->level > current_home_level)
- {
- home = *h;
- current_home_level = h->level;
- }
- }
- if (!home)
- {
- home = null_home;
- }
- return home;
- }
- Home *World::GetHome(std::string id)
- {
- UTIL_PTR_VECTOR_FOREACH(this->homes, Home, h)
- {
- if (h->id == id)
- {
- return *h;
- }
- }
- return 0;
- }
- Quest *World::GetQuest(short id)
- {
- try
- {
- return this->quests.at(id-1);
- }
- catch (...)
- {
- return this->quests.at(0);
- }
- }
- bool World::CharacterExists(std::string name)
- {
- Database_Result res = this->db.Query("SELECT 1 FROM `characters` WHERE `name` = '$'", name.c_str());
- return !res.empty();
- }
- Character *World::CreateCharacter(Player *player, std::string name, Gender gender, int hairstyle, int haircolor, Skin race)
- {
- char buffer[1024];
- std::string startmapinfo;
- std::string startmapval;
- if (static_cast<int>(this->config["StartMap"]))
- {
- startmapinfo = ", `map`, `x`, `y`";
- snprintf(buffer, 1024, ",%i,%i,%i", static_cast<int>(this->config["StartMap"]), static_cast<int>(this->config["StartX"]), static_cast<int>(this->config["StartY"]));
- startmapval = buffer;
- }
- this->db.Query("INSERT INTO `characters` (`name`, `account`, `gender`, `hairstyle`, `haircolor`, `race`, `inventory`, `bank`, `paperdoll`, `spells`, `quest`, `vars`@) VALUES ('$','$',#,#,#,#,'$','','$','$','',''@)",
- startmapinfo.c_str(), name.c_str(), player->username.c_str(), gender, hairstyle, haircolor, race,
- static_cast<std::string>(this->config["StartItems"]).c_str(), static_cast<std::string>(gender?this->config["StartEquipMale"]:this->config["StartEquipFemale"]).c_str(),
- static_cast<std::string>(this->config["StartSpells"]).c_str(), startmapval.c_str());
- return new Character(name, this);
- }
- void World::DeleteCharacter(std::string name)
- {
- this->db.Query("DELETE FROM `characters` WHERE name = '$'", name.c_str());
- }
- Player *World::Login(std::string username, std::string password)
- {
- password = sha256(static_cast<std::string>(this->config["PasswordSalt"]) + username + password);
- Database_Result res = this->db.Query("SELECT 1 FROM `accounts` WHERE `username` = '$' AND `password` = '$'", username.c_str(), password.c_str());
- if (res.empty())
- {
- return 0;
- }
- std::tr1::unordered_map<std::string, util::variant> row = res.front();
- return new Player(username, this);
- }
- 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)
- {
- password = sha256(static_cast<std::string>(this->config["PasswordSalt"]) + username + password);
- 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));
- return !result.Error();
- }
- bool World::PlayerExists(std::string username)
- {
- Database_Result res = this->db.Query("SELECT 1 FROM `accounts` WHERE `username` = '$'", username.c_str());
- return !res.empty();
- }
- bool World::PlayerOnline(std::string username)
- {
- if (!Player::ValidName(username))
- {
- return false;
- }
- UTIL_PTR_LIST_FOREACH(this->server->clients, EOClient, connection)
- {
- if (connection->player)
- {
- if (connection->player->username.compare(username) == 0)
- {
- return true;
- }
- }
- }
- return false;
- }
- void World::Kick(Character *from, Character *victim, bool announce)
- {
- if (announce)
- {
- std::string msg("Attention!! ");
- msg += victim->name + " has been removed from the game ";
- if (from) msg += "-" + from->name + " ";
- msg += "[kicked]";
- this->ServerMsg(msg);
- }
- victim->player->client->Close();
- }
- void World::Jail(Character *from, Character *victim, bool announce)
- {
- if (announce)
- {
- std::string msg("Attention!! ");
- msg += victim->name + " has been removed from the game ";
- if (from) msg += "-" + from->name + " ";
- msg += "[jailed]";
- this->ServerMsg(msg);
- }
- 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);
- }
- void World::Ban(Character *from, Character *victim, int duration, bool announce)
- {
- if (announce)
- {
- std::string msg("Attention!! ");
- msg += victim->name + " has been removed from the game ";
- if (from) msg += "-" + from->name + " ";
- msg += "[banned]";
- this->ServerMsg(msg);
- }
- std::string query("INSERT INTO bans (username, ip, hdid, expires, setter) VALUES ");
- query += "('" + db.Escape(victim->player->username) + "', ";
- query += util::to_string(static_cast<int>(victim->player->client->GetRemoteAddr())) + ", ";
- query += util::to_string(victim->player->client->hdid) + ", ";
- if (duration == -1)
- {
- query += "0";
- }
- else
- {
- query += util::to_string(int(std::time(0) + duration));
- }
- if (from)
- {
- query += ", '" + db.Escape(from->name) + "')";
- }
- else
- {
- query += ")";
- }
- db.Query(query.c_str(), std::time(0));
- victim->player->client->Close();
- }
- int World::CheckBan(const std::string *username, const IPAddress *address, const int *hdid)
- {
- std::string query("SELECT COALESCE(MAX(expires),-1) AS expires FROM bans WHERE (");
- if (!username && !address && !hdid)
- {
- return -1;
- }
- if (username)
- {
- query += "username = '";
- query += db.Escape(*username);
- query += "' OR ";
- }
- if (address)
- {
- query += "ip = ";
- query += util::to_string(static_cast<int>(*const_cast<IPAddress *>(address)));
- query += " OR ";
- }
- if (hdid)
- {
- query += "hdid = ";
- query += util::to_string(*hdid);
- query += " OR ";
- }
- Database_Result res = db.Query((query.substr(0, query.length()-4) + ") AND (expires > # OR expires = 0)").c_str(), std::time(0));
- return static_cast<int>(res[0]["expires"]);
- }
- static std::list<int> PKExceptUnserialize(std::string serialized)
- {
- std::list<int> list;
- std::size_t p = 0;
- std::size_t lastp = std::numeric_limits<std::size_t>::max();
- if (!serialized.empty() && *(serialized.end()-1) != ',')
- {
- serialized.push_back(',');
- }
- while ((p = serialized.find_first_of(',', p+1)) != std::string::npos)
- {
- list.push_back(util::to_int(serialized.substr(lastp+1, p-lastp-1)));
- lastp = p;
- }
- return list;
- }
- bool World::PKExcept(const Map *map)
- {
- return this->PKExcept(map->id);
- }
- bool World::PKExcept(int mapid)
- {
- if (mapid == static_cast<int>(this->config["JailMap"]))
- {
- return true;
- }
- if (this->GetMap(mapid)->arena)
- {
- return true;
- }
- std::list<int> except_list = PKExceptUnserialize(this->config["PKExcept"]);
- return std::find(except_list.begin(), except_list.end(), mapid) != except_list.end();
- }
- World::~World()
- {
- while (!this->characters.empty())
- {
- this->characters.back()->player->client->Close(true);
- this->characters.back()->Destroy();
- }
- this->hookmanager->Release();
- this->guildmanager->Release();
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement