hmm Ok Ill post my others then.
World.hpp
----------------
/* $Id: world.hpp 186 2010-02-06 00:06:47Z sausage $
* EOSERV is released under the zlib license.
* See LICENSE.txt for more info.
*/
#ifndef WORLD_HPP_INCLUDED
#define WORLD_HPP_INCLUDED
#include "stdafx.h"
#include "config.hpp"
#include "database.hpp"
#include "script.hpp"
#include "timer.hpp"
struct Board_Post : public Shared
{
short id;
std::string author;
int author_admin;
std::string subject;
std::string body;
double time;
SCRIPT_REGISTER_REF_DF(Board_Post)
SCRIPT_REGISTER_VARIABLE("int16", id);
SCRIPT_REGISTER_VARIABLE("string", author);
SCRIPT_REGISTER_VARIABLE("int", author_admin);
SCRIPT_REGISTER_VARIABLE("string", subject);
SCRIPT_REGISTER_VARIABLE("string", body);
SCRIPT_REGISTER_VARIABLE("double", time);
SCRIPT_REGISTER_END()
};
struct Board : public Shared
{
int id;
short last_id;
PtrList<Board_Post> posts;
Board(int id_) : id(id_), last_id(0) { }
static Board *ScriptFactory(int id) { return new Board(id); }
SCRIPT_REGISTER_REF(Board)
SCRIPT_REGISTER_FACTORY("Board @f(int id)", ScriptFactory);
SCRIPT_REGISTER_VARIABLE("int16", last_id);
SCRIPT_REGISTER_VARIABLE("PtrList<Board_Post>", posts);
SCRIPT_REGISTER_END()
};
struct Home : public Shared
{
std::string id;
std::string name;
short map;
unsigned char x;
unsigned char y;
int level;
Home() : map(1), x(0), y(0), level(-1) { }
SCRIPT_REGISTER_REF_DF(Home)
SCRIPT_REGISTER_VARIABLE("string", id);
SCRIPT_REGISTER_VARIABLE("string", name);
SCRIPT_REGISTER_VARIABLE("int16", map);
SCRIPT_REGISTER_VARIABLE("uint8", x);
SCRIPT_REGISTER_VARIABLE("uint8", y);
SCRIPT_REGISTER_VARIABLE("int", level);
SCRIPT_REGISTER_END()
};
/**
* Object which holds and manages all maps and characters on the server, as well as timed events
* Only one of these should exist per server
*/
class World : public Shared
{
protected:
int last_character_id;
public:
Timer timer;
EOServer *server;
Database db;
HookManager *hookmanager;
GuildManager *guildmanager;
EIF *eif;
ENF *enf;
ESF *esf;
ECF *ecf;
Config config;
Config admin_config;
Config drops_config;
Config shops_config;
Config arenas_config;
Config formulas_config;
Config fish_config;
Config home_config;
Config warps_config;
Config player_config;
Config npcsay_config;
PtrVector<Character> characters;
PtrVector<Guild> guilds;
PtrVector<Party> parties;
PtrVector<Map> maps;
PtrVector<Home> homes;
util::array<Board *, 8> boards;
util::array<int, 254> exp_table;
World(util::array<std::string, 5> dbinfo, const Config &eoserv_config, const Config &admin_config);
void LoadHome();
int GenerateCharacterID();
int GeneratePlayerID();
void Login(Character *);
void Logout(Character *);
void Msg(Character *from, std::string message, bool echo = true);
void AdminMsg(Character *from, std::string message, int minlevel = ADMIN_GUARDIAN, bool echo = true);
void AnnounceMsg(Character *from, std::string message, bool echo = true);
void ServerMsg(std::string message);
void AdminReport(Character *from, std::string reportee, std::string message);
void AdminRequest(Character *from, std::string message);
void Reboot();
void Reboot(int seconds, std::string reason);
void Rehash();
void ReloadPub();
void Kick(Character *from, Character *victim, bool announce = true);
void Jail(Character *from, Character *victim, bool announce = true);
void Ban(Character *from, Character *victim, int duration, bool announce = true);
int CheckBan(const std::string *username, const IPAddress *address, const int *hdid);
Character *GetCharacter(std::string name);
Character *GetCharacterPID(unsigned int id);
Character *GetCharacterCID(unsigned int id);
Map *GetMap(short id);
Home *GetHome(Character *);
Home *GetHome(std::string);
bool CharacterExists(std::string name);
Character *CreateCharacter(Player *, std::string name, Gender, int hairstyle, int haircolor, Skin);
void DeleteCharacter(std::string name);
Player *Login(std::string username, std::string password);
bool 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);
bool PlayerExists(std::string username);
bool PlayerOnline(std::string username);
bool PKExcept(const Map *map);
bool PKExcept(int mapid);
void Srestart();
void EvacTimer(int map);
~World();
SCRIPT_REGISTER_REF(World)
SCRIPT_REGISTER_VARIABLE("Timer", timer);
SCRIPT_REGISTER_VARIABLE("EOServer @", server);
SCRIPT_REGISTER_VARIABLE("Database", db);
SCRIPT_REGISTER_VARIABLE("EIF @", eif);
SCRIPT_REGISTER_VARIABLE("ENF @", enf);
SCRIPT_REGISTER_VARIABLE("ESF @", esf);
SCRIPT_REGISTER_VARIABLE("ECF @", ecf);
SCRIPT_REGISTER_VARIABLE("Config", config);
SCRIPT_REGISTER_VARIABLE("Config", admin_config);
SCRIPT_REGISTER_VARIABLE("Config", drops_config);
SCRIPT_REGISTER_VARIABLE("Config", shops_config);
SCRIPT_REGISTER_VARIABLE("Config", arenas_config);
SCRIPT_REGISTER_VARIABLE("Config", formulas_config);
SCRIPT_REGISTER_VARIABLE("Config", home_config);
SCRIPT_REGISTER_VARIABLE("PtrVector<Character @>", characters);
SCRIPT_REGISTER_VARIABLE("PtrVector<Guild @>", guilds);
SCRIPT_REGISTER_VARIABLE("PtrVector<Party @>", parties);
SCRIPT_REGISTER_VARIABLE("PtrVector<Map @>", maps);
//SCRIPT_REGISTER_VARIABLE("Array<Board @, 8>", boards);
//SCRIPT_REGISTER_VARIABLE("Array<int, 254>", exp_table);
SCRIPT_REGISTER_FUNCTION("void LoadHome()", LoadHome);
SCRIPT_REGISTER_FUNCTION("int GenerateCharacterID()", GenerateCharacterID);
SCRIPT_REGISTER_FUNCTION("int GeneratePlayerID()", GeneratePlayerID);
SCRIPT_REGISTER_FUNCTION_PR("void Login(Character @)", Login, (Character *), void);
SCRIPT_REGISTER_FUNCTION("void Logout(Character @)", Logout);
SCRIPT_REGISTER_FUNCTION("void Msg(Character @, string, bool echo)", Msg);
SCRIPT_REGISTER_FUNCTION("void AdminMsg(Character @, string, int minlevel, bool echo)", AdminMsg);
SCRIPT_REGISTER_FUNCTION("void AnnounceMsg(Character @, string, bool echo)", AnnounceMsg);
SCRIPT_REGISTER_FUNCTION("void ServerMsg(string)", ServerMsg);
SCRIPT_REGISTER_FUNCTION("void AdminReport(Character @, string reportee, string message)", AdminReport);
SCRIPT_REGISTER_FUNCTION("void AdminRequest(Character @, string message)", AdminRequest);
//SCRIPT_REGISTER_FUNCTION_PR("void Reboot()", Reboot, (), void);
//SCRIPT_REGISTER_FUNCTION_PR("void Reboot(int, string)", Reboot, (int, std::string), void);
SCRIPT_REGISTER_FUNCTION("void Kick(Character @, Character @, bool announce)", Kick);
SCRIPT_REGISTER_FUNCTION("void Jail(Character @, Character @, bool announce)", Jail);
SCRIPT_REGISTER_FUNCTION("void Ban(Character @, Character @, int, bool announce)", Ban);
//SCRIPT_REGISTER_FUNCTION("int CheckBan(const string @, const IPAddress @, const int @)", CheckBan);
SCRIPT_REGISTER_FUNCTION("Character @GetCharacter(string)", GetCharacter);
SCRIPT_REGISTER_FUNCTION("Character @GetCharacterPID(uint)", GetCharacterPID);
SCRIPT_REGISTER_FUNCTION("Character @GetCharacterCID(uint)", GetCharacterCID);
SCRIPT_REGISTER_FUNCTION_PR("Map @GetMap(int16)", GetMap, (short), Map *);
SCRIPT_REGISTER_FUNCTION_PR("Home @GetHome(Character @)", GetHome, (Character *), Home *);
SCRIPT_REGISTER_FUNCTION_PR("Home @GetHome(string)", GetHome, (std::string), Home *);
SCRIPT_REGISTER_FUNCTION("bool CharacterExists(string)", CharacterExists);
SCRIPT_REGISTER_FUNCTION("Character @CreateCharacter(Player @, string, Gender, int, int, Skin)", CreateCharacter);
SCRIPT_REGISTER_FUNCTION("void DeleteCharacter(string)", DeleteCharacter);
SCRIPT_REGISTER_FUNCTION_PR("Player @Login(string, string)", Login, (std::string, std::string), Player *);
SCRIPT_REGISTER_FUNCTION("void CreatePlayer(string, string, string, string, string, string, string, string)", CreatePlayer);
SCRIPT_REGISTER_FUNCTION("bool PlayerExists(string)", PlayerExists);
SCRIPT_REGISTER_FUNCTION("bool PlayerOnline(string)", PlayerOnline);
SCRIPT_REGISTER_FUNCTION_PR("bool PKExcept(const Map @)", PKExcept, (const Map *), bool);
SCRIPT_REGISTER_FUNCTION_PR("bool PKExcept(int)", PKExcept, (int), bool);
SCRIPT_REGISTER_END()
};
#endif // WORLD_HPP_INCLUDED
-------------------------------------------------------
World.cpp
---------------------
/* $Id: world.cpp 186 2010-02-06 00:06:47Z 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"
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 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)
{
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);
}
}
}
}
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 server_reboot(void *world_void)
{
World *world = static_cast<World *>(world_void);
UTIL_PTR_VECTOR_FOREACH(world->characters, Character, character)
{
character->Save();
}
world->Destroy();
std::exit(0);
}
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 < 30) //30% chance say first message
{
npc->Msg(static_cast<std::string>(world->npcsay_config[util::to_string(npc->id) + ".1"]));
}
else if(rand > 30 && rand < 40) //10% chance change message
{
npc->Msg(static_cast<std::string>(world->npcsay_config[util::to_string(npc->id) + ".2"]));
}
else if(rand > 40 && rand < 60) // 20% chance say 3rd
{
npc->Msg(static_cast<std::string>(world->npcsay_config[util::to_string(npc->id) + ".3"]));
}
}
}
}
World::World(util::array<std::string, 5> 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], 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->fish_config.Read(static_cast<std::string>(this->config["FishFile"]));
this->home_config.Read(this->config["HomeFile"]);
this->warps_config.Read(this->config["WarpsFile"]);
this->player_config.Read("player.ini");
this->npcsay_config.Read(this->config["NpcSpeachFile"]);
}
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->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();
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;
}
int World::GeneratePlayerID()
{
unsigned int lowest_free_id = 1;
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->fish_config.Read(this->config["FishFile"]);
this->warps_config.Read(this->config["WarpsFile"]);
this->player_config.Read("player.ini");
this->npcsay_config.Read(this->config["NpcSpeachFile"]);
}
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();
}
}
}
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;
}
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();
}
void World::Srestart()
{
TimeEvent *event = new TimeEvent(server_reboot, this, 10.0, 1);
this->timer.Register(event);
event->Release();
}
World::~World()
{
while (!this->characters.empty())
{
this->characters.back()->player->client->Close(true);
this->characters.back()->Destroy();
}
this->hookmanager->Release();