bool EffectEvent::configureRaidEvent(xmlNodePtr eventNode) { if(!RaidEvent::configureRaidEvent(eventNode)) return false; int32_t intValue; std::string strValue; if(!readXMLInteger(eventNode, "id", intValue)) { if(!readXMLString(eventNode, "name", strValue)) { std::clog << "[Error - EffectEvent::configureRaidEvent] id (or name) tag missing for effect event." << std::endl; return false; } else m_effect = getMagicEffect(strValue); } else m_effect = (MagicEffect_t)intValue; if(!readXMLString(eventNode, "pos", strValue)) { if(!readXMLInteger(eventNode, "x", intValue)) { std::clog << "[Error - EffectEvent::configureRaidEvent] x tag missing for effect event." << std::endl; return false; } m_position.x = intValue; if(!readXMLInteger(eventNode, "y", intValue)) { std::clog << "[Error - EffectEvent::configureRaidEvent] y tag missing for effect event." << std::endl; return false; } m_position.y = intValue; if(!readXMLInteger(eventNode, "z", intValue)) { std::clog << "[Error - EffectEvent::configureRaidEvent] z tag missing for effect event." << std::endl; return false; } m_position.z = intValue; } else { IntegerVec posList = vectorAtoi(explodeString(strValue, ";")); if(posList.size() < 3) { std::clog << "[Error - EffectEvent::configureRaidEvent] Malformed pos tag for effect event." << std::endl; return false; } m_position = Position(posList[0], posList[1], posList[2]); } return true; }
bool SingleSpawnEvent::configureRaidEvent(xmlNodePtr eventNode) { if(!RaidEvent::configureRaidEvent(eventNode)) return false; std::string strValue; if(!readXMLString(eventNode, "name", strValue)) { std::clog << "[Error - SingleSpawnEvent::configureRaidEvent] name tag missing for singlespawn event." << std::endl; return false; } m_monsterName = strValue; if(!readXMLString(eventNode, "pos", strValue)) { int32_t intValue; if(!readXMLInteger(eventNode, "x", intValue)) { std::clog << "[Error - SingleSpawnEvent::configureRaidEvent] x tag missing for singlespawn event." << std::endl; return false; } m_position.x = intValue; if(!readXMLInteger(eventNode, "y", intValue)) { std::clog << "[Error - SingleSpawnEvent::configureRaidEvent] y tag missing for singlespawn event." << std::endl; return false; } m_position.y = intValue; if(!readXMLInteger(eventNode, "z", intValue)) { std::clog << "[Error - SingleSpawnEvent::configureRaidEvent] z tag missing for singlespawn event." << std::endl; return false; } m_position.z = intValue; } else { IntegerVec posList = vectorAtoi(explodeString(strValue, ";")); if(posList.size() < 3) { std::clog << "[Error - SingleSpawnEvent::configureRaidEvent] Malformed pos tag for singlespawn event." << std::endl; return false; } m_position = Position(posList[0], posList[1], posList[2]); } return true; }
bool parseIntegerVec(std::string str, IntegerVec& intVector) { StringVec strVector = explodeString(str, ";"); IntegerVec tmpIntVector; for(StringVec::iterator it = strVector.begin(); it != strVector.end(); ++it) { tmpIntVector = vectorAtoi(explodeString((*it), "-")); if(!tmpIntVector[0] && it->substr(0, 1) != "0") continue; intVector.push_back(tmpIntVector[0]); if(tmpIntVector.size() > 1) { while(tmpIntVector[0] < tmpIntVector[1]) intVector.push_back(++tmpIntVector[0]); } } return true; }
bool Mailbox::getDepotId(const std::string& townString, uint32_t& depotId) { Town* town = Towns::getInstance()->getTown(townString); if(!town) return false; std::string disabledTowns = g_config.getString(ConfigManager::MAILBOX_DISABLED_TOWNS); if(disabledTowns.size()) { IntegerVec tmpVec = vectorAtoi(explodeString(disabledTowns, ",")); if(tmpVec[0] != 0) { for(IntegerVec::iterator it = tmpVec.begin(); it != tmpVec.end(); ++it) { if(town->getID() == uint32_t(*it)) return false; } } } depotId = town->getID(); return true; }
void otserv( #if !defined(WINDOWS) || defined(_CONSOLE) StringVec, #endif ServiceManager* services) { std::srand((uint32_t)OTSYS_TIME()); #if defined(WINDOWS) #if defined(_CONSOLE) SetConsoleTitle(SOFTWARE_NAME); #else GUI::getInstance()->m_connections = false; #endif #endif g_game.setGameState(GAMESTATE_STARTUP); #if !defined(WINDOWS) && !defined(__ROOT_PERMISSION__) if(!getuid() || !geteuid()) { std::clog << "> WARNING: " "The " << SOFTWARE_NAME << " has been executed as super user! It is " << "recommended to run as a normal user." << std::endl << "Continue? (y/N)" << std::endl; char buffer = OTSYS_getch(); if(buffer != 121 && buffer != 89) startupErrorMessage("Aborted."); } #endif std::clog << "The " << SOFTWARE_NAME << " Version: (" << SOFTWARE_VERSION << "." << MINOR_VERSION << PATCH_VERSION << " - " << REVISION_VERSION << ") - Codename: (" << SOFTWARE_CODENAME << ")" << std::endl << "Compilied with " << BOOST_COMPILER << " for arch " #if defined(__amd64__) || defined(_M_X64) "64 Bits" #elif defined(__i386__) || defined(_M_IX86) || defined(_X86_) "32 Bits" #else "unk" #endif " at " << __DATE__ << " " << __TIME__ << std::endl << std::endl << "A server developed by: "SOFTWARE_DEVELOPERS"." << std::endl << "Visit our forums for updates, support, and resources:" << std::endl << ""FORUMS"" << std::endl; std::stringstream ss; #ifdef __DEBUG__ ss << " GLOBAL"; #endif #ifdef __DEBUG_MOVESYS__ ss << " MOVESYS"; #endif #ifdef __DEBUG_CHAT__ ss << " CHAT"; #endif #ifdef __DEBUG_HOUSES__ ss << " HOUSES"; #endif #ifdef __DEBUG_LUASCRIPTS__ ss << " LUA-SCRIPTS"; #endif #ifdef __DEBUG_MAILBOX__ ss << " MAILBOX"; #endif #ifdef __DEBUG_NET__ ss << " NET"; #endif #ifdef __DEBUG_NET_DETAIL__ ss << " NET-DETAIL"; #endif #ifdef __DEBUG_RAID__ ss << " RAIDS"; #endif #ifdef __DEBUG_SCHEDULER__ ss << " SCHEDULER"; #endif #ifdef __DEBUG_SPAWN__ ss << " SPAWNS"; #endif #ifdef __SQL_QUERY_DEBUG__ ss << " SQL-QUERIES"; #endif std::string debug = ss.str(); if(!debug.empty()) { std::clog << ">> Debugging:"; #if defined(WINDOWS) && !defined(_CONSOLE) SendMessage(GUI::getInstance()->m_statusBar, WM_SETTEXT, 0, (LPARAM)">> Debugging:"); #endif std::clog << debug << "." << std::endl; } std::clog << std::endl; std::clog << ">> Loading config (" << g_config.getString(ConfigManager::CONFIG_FILE) << ")" << std::endl; #if defined(WINDOWS) && !defined(_CONSOLE) SendMessage(GUI::getInstance()->m_statusBar, WM_SETTEXT, 0, (LPARAM)">> Loading config"); #endif if(!g_config.load()) startupErrorMessage("Unable to load " + g_config.getString(ConfigManager::CONFIG_FILE) + "!"); #ifndef WINDOWS if(g_config.getBool(ConfigManager::DAEMONIZE)) { std::clog << "> Daemonization... "; if(fork()) { std::clog << "succeed, bye!" << std::endl; exit(0); } else std::clog << "failed, continuing." << std::endl; } #endif // silently append trailing slash std::string path = g_config.getString(ConfigManager::DATA_DIRECTORY); g_config.setString(ConfigManager::DATA_DIRECTORY, path.erase(path.find_last_not_of("/") + 1) + "/"); path = g_config.getString(ConfigManager::LOGS_DIRECTORY); g_config.setString(ConfigManager::LOGS_DIRECTORY, path.erase(path.find_last_not_of("/") + 1) + "/"); std::clog << ">> Opening logs" << std::endl; #if defined(WINDOWS) && !defined(_CONSOLE) SendMessage(GUI::getInstance()->m_statusBar, WM_SETTEXT, 0, (LPARAM)">> Opening logs"); #endif Logger::getInstance()->open(); IntegerVec cores = vectorAtoi(explodeString(g_config.getString(ConfigManager::CORES_USED), ",")); if(cores[0] != -1) { #ifdef WINDOWS int32_t mask = 0; for(IntegerVec::iterator it = cores.begin(); it != cores.end(); ++it) mask += 1 << (*it); SetProcessAffinityMask(GetCurrentProcess(), mask); } std::stringstream mutexName; mutexName << "otxserver_" << g_config.getNumber(ConfigManager::WORLD_ID); CreateMutex(NULL, FALSE, mutexName.str().c_str()); if(GetLastError() == ERROR_ALREADY_EXISTS) startupErrorMessage("Another instance of The OTX Server is already running with the same worldId.\nIf you want to run multiple servers, please change the worldId in configuration file."); std::string defaultPriority = asLowerCaseString(g_config.getString(ConfigManager::DEFAULT_PRIORITY)); if(defaultPriority == "realtime" || defaultPriority == "real") SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS); else if(defaultPriority == "high" || defaultPriority == "regular") SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); else if(defaultPriority == "higher" || defaultPriority == "above" || defaultPriority == "normal") SetPriorityClass(GetCurrentProcess(), ABOVE_NORMAL_PRIORITY_CLASS); #else #ifndef __APPLE__ cpu_set_t mask; CPU_ZERO(&mask); for(IntegerVec::iterator it = cores.begin(); it != cores.end(); ++it) CPU_SET((*it), &mask); sched_setaffinity(getpid(), (int32_t)sizeof(mask), &mask); }
bool GlobalEvent::configureEvent(const pugi::xml_node& node) { pugi::xml_attribute nameAttribute = node.attribute("name"); if (!nameAttribute) { std::cout << "[Error - GlobalEvent::configureEvent] Missing name for a globalevent" << std::endl; return false; } name = nameAttribute.as_string(); eventType = GLOBALEVENT_NONE; pugi::xml_attribute attr; if ((attr = node.attribute("time"))) { std::vector<int32_t> params = vectorAtoi(explodeString(attr.as_string(), ":")); int32_t hour = params.front(); if (hour < 0 || hour > 23) { std::cout << "[Error - GlobalEvent::configureEvent] Invalid hour \"" << attr.as_string() << "\" for globalevent with name: " << name << std::endl; return false; } interval |= hour << 16; int32_t min = 0; int32_t sec = 0; if (params.size() > 1) { min = params[1]; if (min < 0 || min > 59) { std::cout << "[Error - GlobalEvent::configureEvent] Invalid minute \"" << attr.as_string() << "\" for globalevent with name: " << name << std::endl; return false; } if (params.size() > 2) { sec = params[2]; if (sec < 0 || sec > 59) { std::cout << "[Error - GlobalEvent::configureEvent] Invalid second \"" << attr.as_string() << "\" for globalevent with name: " << name << std::endl; return false; } } } time_t current_time = time(nullptr); tm* timeinfo = localtime(¤t_time); timeinfo->tm_hour = hour; timeinfo->tm_min = min; timeinfo->tm_sec = sec; time_t difference = static_cast<time_t>(difftime(mktime(timeinfo), current_time)); if (difference < 0) { difference += 86400; } nextExecution = current_time + difference; eventType = GLOBALEVENT_TIMER; } else if ((attr = node.attribute("type"))) { const char* value = attr.value(); if (strcasecmp(value, "startup") == 0) { eventType = GLOBALEVENT_STARTUP; } else if (strcasecmp(value, "shutdown") == 0) { eventType = GLOBALEVENT_SHUTDOWN; } else if (strcasecmp(value, "record") == 0) { eventType = GLOBALEVENT_RECORD; } else { std::cout << "[Error - GlobalEvent::configureEvent] No valid type \"" << attr.as_string() << "\" for globalevent with name " << name << std::endl; return false; } } else if ((attr = node.attribute("interval"))) { interval = std::max<int32_t>(SCHEDULER_MINTICKS, pugi::cast<int32_t>(attr.value())); nextExecution = OTSYS_TIME() + interval; } else { std::cout << "[Error - GlobalEvent::configureEvent] No interval for globalevent with name " << name << std::endl; return false; } return true; }
bool GlobalEvent::configureEvent(const pugi::xml_node& node) { pugi::xml_attribute nameAttribute = node.attribute("name"); if (!nameAttribute) { std::cout << "[Error - GlobalEvent::configureEvent] Missing name for a globalevent" << std::endl; return false; } m_name = nameAttribute.as_string(); m_eventType = GLOBALEVENT_NONE; pugi::xml_attribute attr; if ((attr = node.attribute("time"))) { std::vector<int32_t> params = vectorAtoi(explodeString(attr.as_string(), ":")); if (params.front() < 0 || params.front() > 23) { std::cout << "[Error - GlobalEvent::configureEvent] Invalid hour \"" << attr.as_string() << "\" for globalevent with name: " << m_name << std::endl; return false; } m_interval |= params.front() << 16; int32_t hour = params.front(); int32_t min = 0; int32_t sec = 0; if (params.size() > 1) { if (params[1] < 0 || params[1] > 59) { std::cout << "[Error - GlobalEvent::configureEvent] Invalid minute \"" << attr.as_string() << "\" for globalevent with name: " << m_name << std::endl; return false; } min = params[1]; if (params.size() > 2) { if (params[2] < 0 || params[2] > 59) { std::cout << "[Error - GlobalEvent::configureEvent] Invalid second \"" << attr.as_string() << "\" for globalevent with name: " << m_name << std::endl; return false; } sec = params[2]; } } time_t current_time = time(nullptr); tm* timeinfo = localtime(¤t_time); timeinfo->tm_hour = hour; timeinfo->tm_min = min; timeinfo->tm_sec = sec; time_t difference = (time_t)difftime(mktime(timeinfo), current_time); if (difference < 0) { difference += 86400; } m_nextExecution = current_time + difference; m_eventType = GLOBALEVENT_TIMER; } else if ((attr = node.attribute("type"))) { std::string tmpStrValue = asLowerCaseString(attr.as_string()); if (tmpStrValue == "startup" || tmpStrValue == "start" || tmpStrValue == "load") { m_eventType = GLOBALEVENT_STARTUP; } else if (tmpStrValue == "shutdown" || tmpStrValue == "quit" || tmpStrValue == "exit") { m_eventType = GLOBALEVENT_SHUTDOWN; } else if (tmpStrValue == "record" || tmpStrValue == "playersrecord") { m_eventType = GLOBALEVENT_RECORD; } else { std::cout << "[Error - GlobalEvent::configureEvent] No valid type \"" << attr.as_string() << "\" for globalevent with name " << m_name << std::endl; return false; } } else if ((attr = node.attribute("interval"))) { m_interval = std::max<int32_t>(SCHEDULER_MINTICKS, pugi::cast<int32_t>(attr.value())); m_nextExecution = OTSYS_TIME() + m_interval; } else { std::cout << "[Error - GlobalEvent::configureEvent] No interval for globalevent with name " << m_name << std::endl; return false; } return true; }
bool MoveEvents::registerEvent(Event* event, xmlNodePtr p) { MoveEvent* moveEvent = dynamic_cast<MoveEvent*>(event); if (!moveEvent) { return false; } bool success = true; int32_t id, endId; std::string str; MoveEvent_t eventType = moveEvent->getEventType(); if (eventType == MOVE_EVENT_ADD_ITEM || eventType == MOVE_EVENT_REMOVE_ITEM) { if (readXMLInteger(p, "tileitem", id) && id == 1) { switch (eventType) { case MOVE_EVENT_ADD_ITEM: moveEvent->setEventType(MOVE_EVENT_ADD_ITEM_ITEMTILE); break; case MOVE_EVENT_REMOVE_ITEM: moveEvent->setEventType(MOVE_EVENT_REMOVE_ITEM_ITEMTILE); break; default: break; } } } if (readXMLInteger(p, "itemid", id)) { addEvent(moveEvent, id, m_itemIdMap); if (moveEvent->getEventType() == MOVE_EVENT_EQUIP) { ItemType& it = Item::items.getItemType(id); it.wieldInfo = moveEvent->getWieldInfo(); it.minReqLevel = moveEvent->getReqLevel(); it.minReqMagicLevel = moveEvent->getReqMagLv(); it.vocationString = moveEvent->getVocationString(); } } else if (readXMLInteger(p, "fromid", id) && readXMLInteger(p, "toid", endId)) { addEvent(moveEvent, id, m_itemIdMap); if (moveEvent->getEventType() == MOVE_EVENT_EQUIP) { ItemType& it = Item::items.getItemType(id); it.wieldInfo = moveEvent->getWieldInfo(); it.minReqLevel = moveEvent->getReqLevel(); it.minReqMagicLevel = moveEvent->getReqMagLv(); it.vocationString = moveEvent->getVocationString(); while (id < endId) { id++; addEvent(new MoveEvent(moveEvent), id, m_itemIdMap); ItemType& tit = Item::items.getItemType(id); tit.wieldInfo = moveEvent->getWieldInfo(); tit.minReqLevel = moveEvent->getReqLevel(); tit.minReqMagicLevel = moveEvent->getReqMagLv(); tit.vocationString = moveEvent->getVocationString(); } } else { while (id < endId) { addEvent(new MoveEvent(moveEvent), ++id, m_itemIdMap); } } } else if (readXMLInteger(p, "uniqueid", id)) { addEvent(moveEvent, id, m_uniqueIdMap); } else if (readXMLInteger(p, "fromuid", id) && readXMLInteger(p, "touid", endId)) { addEvent(moveEvent, id, m_uniqueIdMap); while (id < endId) { addEvent(new MoveEvent(moveEvent), ++id, m_uniqueIdMap); } } else if (readXMLInteger(p, "actionid", id) || readXMLInteger(p, "aid", id)) { addEvent(moveEvent, id, m_actionIdMap); } else if (readXMLInteger(p, "fromaid", id) && readXMLInteger(p, "toaid", endId)) { addEvent(moveEvent, id, m_actionIdMap); while (id < endId) { addEvent(new MoveEvent(moveEvent), ++id, m_actionIdMap); } } else if (readXMLString(p, "pos", str)) { std::vector<int32_t> posList = vectorAtoi(explodeString(str, ";")); if (posList.size() >= 3) { Position pos(posList[0], posList[1], posList[2]); addEvent(moveEvent, pos, m_positionMap); } else { success = false; } } else { success = false; } return success; }
void otserv( #if !defined(WINDOWS) || defined(__CONSOLE__) StringVec args, #endif ServiceManager* services) { srand((uint32_t)OTSYS_TIME()); #if defined(WINDOWS) #if defined(__CONSOLE__) SetConsoleTitle(STATUS_SERVER_NAME); #else GUI::getInstance()->m_connections = false; #endif #endif g_game.setGameState(GAME_STATE_STARTUP); std::cout << STATUS_SERVER_NAME << ", version " << STATUS_SERVER_VERSION << " (" << STATUS_SERVER_CODENAME << ")" << std::endl; std::cout << "Compiled with " << BOOST_COMPILER << " at " << __DATE__ << ", " << __TIME__ << "." << std::endl; std::cout << "A server developed by Gesior." << std::endl; std::stringstream ss; #ifdef __DEBUG__ ss << " GLOBAL"; #endif #ifdef __DEBUG_MOVESYS__ ss << " MOVESYS"; #endif #ifdef __DEBUG_CHAT__ ss << " CHAT"; #endif #ifdef __DEBUG_EXCEPTION_REPORT__ ss << " EXCEPTION-REPORT"; #endif #ifdef __DEBUG_HOUSES__ ss << " HOUSES"; #endif #ifdef __DEBUG_LUASCRIPTS__ ss << " LUA-SCRIPTS"; #endif #ifdef __DEBUG_MAILBOX__ ss << " MAILBOX"; #endif #ifdef __DEBUG_NET__ ss << " NET"; #endif #ifdef __DEBUG_NET_DETAIL__ ss << " NET-DETAIL"; #endif #ifdef __DEBUG_RAID__ ss << " RAIDS"; #endif #ifdef __DEBUG_SCHEDULER__ ss << " SCHEDULER"; #endif #ifdef __DEBUG_SPAWN__ ss << " SPAWNS"; #endif #ifdef __SQL_QUERY_DEBUG__ ss << " SQL-QUERIES"; #endif std::string debug = ss.str(); if(!debug.empty()) { std::cout << ">> Debugging:"; #if defined(WINDOWS) && !defined(__CONSOLE__) SendMessage(GUI::getInstance()->m_statusBar, WM_SETTEXT, 0, (LPARAM)">> Displaying debugged components"); #endif std::cout << debug << "." << std::endl; } std::cout << ">> Loading config (" << g_config.getString(ConfigManager::CONFIG_FILE) << ")" << std::endl; #if defined(WINDOWS) && !defined(__CONSOLE__) SendMessage(GUI::getInstance()->m_statusBar, WM_SETTEXT, 0, (LPARAM)">> Loading config"); #endif if(!g_config.load()) startupErrorMessage("Unable to load " + g_config.getString(ConfigManager::CONFIG_FILE) + "!"); Logger::getInstance()->open(); IntegerVec cores = vectorAtoi(explodeString(g_config.getString(ConfigManager::CORES_USED), ",")); if(cores[0] != -1) { #ifdef WINDOWS int32_t mask = 0; for(IntegerVec::iterator it = cores.begin(); it != cores.end(); ++it) mask += 1 << (*it); SetProcessAffinityMask(GetCurrentProcess(), mask); } std::stringstream mutexName; mutexName << "forgottenserver_" << g_config.getNumber(ConfigManager::WORLD_ID); CreateMutex(NULL, FALSE, mutexName.str().c_str()); if(GetLastError() == ERROR_ALREADY_EXISTS) startupErrorMessage("Another instance of The Forgotten Server is already running with the same worldId.\nIf you want to run multiple servers, please change the worldId in configuration file."); std::string defaultPriority = asLowerCaseString(g_config.getString(ConfigManager::DEFAULT_PRIORITY)); if(defaultPriority == "realtime") SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS); else if(defaultPriority == "high") SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); else if(defaultPriority == "higher") SetPriorityClass(GetCurrentProcess(), ABOVE_NORMAL_PRIORITY_CLASS); #else cpu_set_t mask; CPU_ZERO(&mask); for(IntegerVec::iterator it = cores.begin(); it != cores.end(); ++it) CPU_SET((*it), &mask); sched_setaffinity(getpid(), (int32_t)sizeof(mask), &mask); }
bool ScriptManager::loadFromXml(const std::string& file, bool& enabled) { enabled = false; xmlDocPtr doc = xmlParseFile(getFilePath(FILE_TYPE_MOD, file).c_str()); if(!doc) { std::clog << "[Error - ScriptManager::loadFromXml] Cannot load mod " << file << std::endl; std::clog << getLastXMLError() << std::endl; return false; } int32_t intValue; std::string strValue; xmlNodePtr p, root = xmlDocGetRootElement(doc); if(xmlStrcmp(root->name,(const xmlChar*)"mod")) { std::clog << "[Error - ScriptManager::loadFromXml] Malformed mod " << file << std::endl; std::clog << getLastXMLError() << std::endl; xmlFreeDoc(doc); return false; } if(!readXMLString(root, "name", strValue)) strValue = file; ModBlock mod; mod.enabled = true; mod.name = strValue; if(readXMLString(root, "enabled", strValue) && !booleanString(strValue)) mod.enabled = false; mod.file = file; if(readXMLString(root, "author", strValue)) mod.author = strValue; if(readXMLString(root, "version", strValue)) mod.version = strValue; if(readXMLString(root, "contact", strValue)) mod.contact = strValue; bool supported = true; for(p = root->children; p; p = p->next) { if(xmlStrcmp(p->name, (const xmlChar*)"server")) continue; supported = false; for(xmlNodePtr versionNode = p->children; versionNode; versionNode = versionNode->next) { std::string id = SOFTWARE_VERSION; if(readXMLString(versionNode, "id", strValue)) id = asLowerCaseString(strValue); IntegerVec protocol; protocol.push_back(CLIENT_VERSION_MIN); if(readXMLString(versionNode, "protocol", strValue)) protocol = vectorAtoi(explodeString(strValue, "-")); int16_t database = VERSION_DATABASE; if(readXMLInteger(versionNode, "database", intValue)) database = intValue; if(id == asLowerCaseString(SOFTWARE_VERSION) && database >= VERSION_DATABASE && protocol[0] >= CLIENT_VERSION_MIN && (protocol.size() < 2 || protocol[1] <= CLIENT_VERSION_MAX)) { supported = true; break; } } } if(!supported) { std::clog << "[Warning - ScriptManager::loadFromXml] Your server is not supported by mod " << file << std::endl; xmlFreeDoc(doc); return false; } if(mod.enabled) { std::string scriptsPath = getFilePath(FILE_TYPE_MOD, "scripts/"); for(p = root->children; p; p = p->next) { if(!xmlStrcmp(p->name, (const xmlChar*)"quest")) Quests::getInstance()->parseQuestNode(p, modsLoaded); else if(!xmlStrcmp(p->name, (const xmlChar*)"outfit")) Outfits::getInstance()->parseOutfitNode(p); else if(!xmlStrcmp(p->name, (const xmlChar*)"vocation")) Vocations::getInstance()->parseVocationNode(p); //duplicates checking is dangerous, shouldn't be performed until we find some good solution else if(!xmlStrcmp(p->name, (const xmlChar*)"group")) Groups::getInstance()->parseGroupNode(p); //duplicates checking is dangerous, shouldn't be performed until we find some good solution else if(!xmlStrcmp(p->name, (const xmlChar*)"raid")) Raids::getInstance()->parseRaidNode(p, modsLoaded, FILE_TYPE_MOD); //TODO: support mods path else if(!xmlStrcmp(p->name, (const xmlChar*)"spawn")) Spawns::getInstance()->parseSpawnNode(p, modsLoaded); else if(!xmlStrcmp(p->name, (const xmlChar*)"channel")) g_chat.parseChannelNode(p); //TODO: duplicates- channel destructor needs to send closeChannel to users! else if(!xmlStrcmp(p->name, (const xmlChar*)"npc")) g_npcs.parseNpcNode(p, FILE_TYPE_MOD); else if(!xmlStrcmp(p->name, (const xmlChar*)"monster")) { std::string path, name; if((readXMLString(p, "file", path) || readXMLString(p, "path", path)) && readXMLString(p, "name", name)) g_monsters.loadMonster(getFilePath(FILE_TYPE_MOD, "monster/" + path), name, true); } else if(!xmlStrcmp(p->name, (const xmlChar*)"item")) { if(readXMLInteger(p, "id", intValue)) Item::items.parseItemNode(p, intValue); } if(!xmlStrcmp(p->name, (const xmlChar*)"description") || !xmlStrcmp(p->name, (const xmlChar*)"info")) { if(parseXMLContentString(p->children, strValue)) { replaceString(strValue, "\t", ""); mod.description = strValue; } } else if(!xmlStrcmp(p->name, (const xmlChar*)"lib") || !xmlStrcmp(p->name, (const xmlChar*)"config")) { if(!readXMLString(p, "name", strValue)) { if(!xmlStrcmp(p->name, (const xmlChar*)"lib")) strValue = mod.name + "-lib"; else if(!xmlStrcmp(p->name, (const xmlChar*)"config")) strValue = mod.name + "-config"; } else toLowerCaseString(strValue); std::string strLib; if(parseXMLContentString(p->children, strLib)) { LibMap::iterator it = libMap.find(strValue); if(it == libMap.end()) { LibBlock lb; lb.first = file; lb.second = strLib; libMap[strValue] = lb; } else std::clog << "[Warning - ScriptManager::loadFromXml] Duplicated lib in mod " << strValue << ", previously declared in " << it->second.first << std::endl; } } else if(!g_actions->parseEventNode(p, scriptsPath, modsLoaded)) { if(!g_talkActions->parseEventNode(p, scriptsPath, modsLoaded)) { if(!g_moveEvents->parseEventNode(p, scriptsPath, modsLoaded)) { if(!g_creatureEvents->parseEventNode(p, scriptsPath, modsLoaded)) { if(!g_globalEvents->parseEventNode(p, scriptsPath, modsLoaded)) { if(!g_spells->parseEventNode(p, scriptsPath, modsLoaded)) g_weapons->parseEventNode(p, scriptsPath, modsLoaded); } } } } } } } enabled = mod.enabled; modMap[mod.name] = mod; xmlFreeDoc(doc); return true; }
bool AreaSpawnEvent::configureRaidEvent(xmlNodePtr eventNode) { if(!RaidEvent::configureRaidEvent(eventNode)) return false; int32_t intValue; std::string strValue; if(readXMLInteger(eventNode, "radius", intValue)) { int32_t radius = intValue; Position centerPos; if(readXMLString(eventNode, "centerPosition", strValue) || readXMLString(eventNode, "centerpos", strValue)) { IntegerVec posList = vectorAtoi(explodeString(strValue, ";")); if(posList.size() < 3) { std::clog << "[Error - AreaSpawnEvent::configureRaidEvent] Malformed centerPosition tag for areaspawn event." << std::endl; return false; } centerPos = Position(posList[0], posList[1], posList[2]); } else { if(!readXMLInteger(eventNode, "centerx", intValue)) { std::clog << "[Error - AreaSpawnEvent::configureRaidEvent] centerx tag missing for areaspawn event." << std::endl; return false; } centerPos.x = intValue; if(!readXMLInteger(eventNode, "centery", intValue)) { std::clog << "[Error - AreaSpawnEvent::configureRaidEvent] centery tag missing for areaspawn event." << std::endl; return false; } centerPos.y = intValue; if(!readXMLInteger(eventNode, "centerz", intValue)) { std::clog << "[Error - AreaSpawnEvent::configureRaidEvent] centerz tag missing for areaspawn event." << std::endl; return false; } centerPos.z = intValue; } m_fromPos.x = centerPos.x - radius; m_fromPos.y = centerPos.y - radius; m_fromPos.z = centerPos.z; m_toPos.x = centerPos.x + radius; m_toPos.y = centerPos.y + radius; m_toPos.z = centerPos.z; } else { if(readXMLString(eventNode, "fromPosition", strValue) || readXMLString(eventNode, "frompos", strValue)) { IntegerVec posList = vectorAtoi(explodeString(strValue, ";")); if(posList.size() < 3) { std::clog << "[Error - AreaSpawnEvent::configureRaidEvent] Malformed fromPosition tag for areaspawn event." << std::endl; return false; } m_fromPos = Position(posList[0], posList[1], posList[2]); } else { if(!readXMLInteger(eventNode, "fromx", intValue)) { std::clog << "[Error - AreaSpawnEvent::configureRaidEvent] fromx tag missing for areaspawn event." << std::endl; return false; } m_fromPos.x = intValue; if(!readXMLInteger(eventNode, "fromy", intValue)) { std::clog << "[Error - AreaSpawnEvent::configureRaidEvent] fromy tag missing for areaspawn event." << std::endl; return false; } m_fromPos.y = intValue; if(!readXMLInteger(eventNode, "fromz", intValue)) { std::clog << "[Error - AreaSpawnEvent::configureRaidEvent] fromz tag missing for areaspawn event." << std::endl; return false; } m_fromPos.z = intValue; } if(readXMLString(eventNode, "toPosition", strValue) || readXMLString(eventNode, "topos", strValue)) { IntegerVec posList = vectorAtoi(explodeString(strValue, ";")); if(posList.size() < 3) { std::clog << "[Error - AreaSpawnEvent::configureRaidEvent] Malformed toPosition tag for areaspawn event." << std::endl; return false; } m_toPos = Position(posList[0], posList[1], posList[2]); } else { if(!readXMLInteger(eventNode, "tox", intValue)) { std::clog << "[Error - AreaSpawnEvent::configureRaidEvent] tox tag missing for areaspawn event." << std::endl; return false; } m_toPos.x = intValue; if(!readXMLInteger(eventNode, "toy", intValue)) { std::clog << "[Error - AreaSpawnEvent::configureRaidEvent] toy tag missing for areaspawn event." << std::endl; return false; } m_toPos.y = intValue; if(!readXMLInteger(eventNode, "toz", intValue)) { std::clog << "[Error - AreaSpawnEvent::configureRaidEvent] toz tag missing for areaspawn event." << std::endl; return false; } m_toPos.z = intValue; } } xmlNodePtr monsterNode = eventNode->children; while(monsterNode) { if(!xmlStrcmp(monsterNode->name, (const xmlChar*)"monster")) { if(!readXMLString(monsterNode, "name", strValue)) { std::clog << "[Error - AreaSpawnEvent::configureRaidEvent] name tag missing for monster node." << std::endl; return false; } std::string name = strValue; int32_t min = 0, max = 0; if(readXMLInteger(monsterNode, "min", intValue) || readXMLInteger(monsterNode, "minamount", intValue)) min = intValue; if(readXMLInteger(monsterNode, "max", intValue) || readXMLInteger(monsterNode, "maxamount", intValue)) max = intValue; if(!min && !max) { if(!readXMLInteger(monsterNode, "amount", intValue)) { std::clog << "[Error - AreaSpawnEvent::configureRaidEvent] amount tag missing for monster node." << std::endl; return false; } min = max = intValue; } addMonster(name, min, max); } monsterNode = monsterNode->next; } return true; }
bool ItemSpawnEvent::configureRaidEvent(xmlNodePtr eventNode) { if(!RaidEvent::configureRaidEvent(eventNode)) return false; int32_t intValue; std::string strValue; if(!readXMLInteger(eventNode, "id", intValue)) { if(!readXMLString(eventNode, "name", strValue)) { std::clog << "[Error - ItemSpawnEvent::configureRaidEvent] id (or name) tag missing for itemspawn event." << std::endl; return false; } else m_itemId = Item::items.getItemIdByName(strValue); } else m_itemId = intValue; if(readXMLInteger(eventNode, "chance", intValue)) m_chance = intValue; if(readXMLInteger(eventNode, "subType", intValue)) m_subType = intValue; if(!readXMLString(eventNode, "pos", strValue)) { if(!readXMLInteger(eventNode, "x", intValue)) { std::clog << "[Error - ItemSpawnEvent::configureRaidEvent] x tag missing for itemspawn event." << std::endl; return false; } m_position.x = intValue; if(!readXMLInteger(eventNode, "y", intValue)) { std::clog << "[Error - ItemSpawnEvent::configureRaidEvent] y tag missing for itemspawn event." << std::endl; return false; } m_position.y = intValue; if(!readXMLInteger(eventNode, "z", intValue)) { std::clog << "[Error - ItemSpawnEvent::configureRaidEvent] z tag missing for itemspawn event." << std::endl; return false; } m_position.z = intValue; } else { IntegerVec posList = vectorAtoi(explodeString(strValue, ";")); if(posList.size() < 3) { std::clog << "[Error - ItemSpawnEvent::configureRaidEvent] Malformed pos tag for itemspawn event." << std::endl; return false; } m_position = Position(posList[0], posList[1], posList[2]); } return true; }
bool MoveEvents::registerEvent(Event* event, const pugi::xml_node& node) { MoveEvent* moveEvent = static_cast<MoveEvent*>(event); //event is guaranteed to be a MoveEvent const MoveEvent_t eventType = moveEvent->getEventType(); if (eventType == MOVE_EVENT_ADD_ITEM || eventType == MOVE_EVENT_REMOVE_ITEM) { pugi::xml_attribute tileItemAttribute = node.attribute("tileitem"); if (tileItemAttribute && pugi::cast<uint16_t>(tileItemAttribute.value()) == 1) { switch (eventType) { case MOVE_EVENT_ADD_ITEM: moveEvent->setEventType(MOVE_EVENT_ADD_ITEM_ITEMTILE); break; case MOVE_EVENT_REMOVE_ITEM: moveEvent->setEventType(MOVE_EVENT_REMOVE_ITEM_ITEMTILE); break; default: break; } } } pugi::xml_attribute attr; if ((attr = node.attribute("itemid"))) { int32_t id = pugi::cast<int32_t>(attr.value()); addEvent(moveEvent, id, m_itemIdMap); if (moveEvent->getEventType() == MOVE_EVENT_EQUIP) { ItemType& it = Item::items.getItemType(id); it.wieldInfo = moveEvent->getWieldInfo(); it.minReqLevel = moveEvent->getReqLevel(); it.minReqMagicLevel = moveEvent->getReqMagLv(); it.vocationString = moveEvent->getVocationString(); } } else if ((attr = node.attribute("fromid"))) { uint32_t id = pugi::cast<uint32_t>(attr.value()); uint32_t endId = pugi::cast<uint32_t>(node.attribute("toid").value()); addEvent(moveEvent, id, m_itemIdMap); if (moveEvent->getEventType() == MOVE_EVENT_EQUIP) { ItemType& it = Item::items.getItemType(id); it.wieldInfo = moveEvent->getWieldInfo(); it.minReqLevel = moveEvent->getReqLevel(); it.minReqMagicLevel = moveEvent->getReqMagLv(); it.vocationString = moveEvent->getVocationString(); while (++id <= endId) { addEvent(moveEvent, id, m_itemIdMap); ItemType& tit = Item::items.getItemType(id); tit.wieldInfo = moveEvent->getWieldInfo(); tit.minReqLevel = moveEvent->getReqLevel(); tit.minReqMagicLevel = moveEvent->getReqMagLv(); tit.vocationString = moveEvent->getVocationString(); } } else { while (++id <= endId) { addEvent(moveEvent, id, m_itemIdMap); } } } else if ((attr = node.attribute("uniqueid"))) { addEvent(moveEvent, pugi::cast<int32_t>(attr.value()), m_uniqueIdMap); } else if ((attr = node.attribute("fromuid"))) { uint32_t id = pugi::cast<uint32_t>(attr.value()); uint32_t endId = pugi::cast<uint32_t>(node.attribute("touid").value()); addEvent(moveEvent, id, m_uniqueIdMap); while (++id <= endId) { addEvent(moveEvent, id, m_uniqueIdMap); } } else if ((attr = node.attribute("actionid"))) { addEvent(moveEvent, pugi::cast<int32_t>(attr.value()), m_actionIdMap); } else if ((attr = node.attribute("fromaid"))) { uint32_t id = pugi::cast<uint32_t>(attr.value()); uint32_t endId = pugi::cast<uint32_t>(node.attribute("toaid").value()); addEvent(moveEvent, id, m_actionIdMap); while (++id <= endId) { addEvent(moveEvent, id, m_actionIdMap); } } else if ((attr = node.attribute("pos"))) { std::vector<int32_t> posList = vectorAtoi(explodeString(attr.as_string(), ";")); if (posList.size() < 3) { return false; } Position pos(posList[0], posList[1], posList[2]); addEvent(moveEvent, pos, m_positionMap); } else { return false; } return true; }
bool Spawns::parseSpawnNode(xmlNodePtr p, bool checkDuplicate) { if(xmlStrcmp(p->name, (const xmlChar*)"spawn")) return false; int32_t intValue; std::string strValue; Position centerPos; if(!readXMLString(p, "centerpos", strValue)) { if(!readXMLInteger(p, "centerx", intValue)) return false; centerPos.x = intValue; if(!readXMLInteger(p, "centery", intValue)) return false; centerPos.y = intValue; if(!readXMLInteger(p, "centerz", intValue)) return false; centerPos.z = intValue; } else { IntegerVec posVec = vectorAtoi(explodeString(",", strValue)); if(posVec.size() < 3) return false; centerPos = Position(posVec[0], posVec[1], posVec[2]); } if(!readXMLInteger(p, "radius", intValue)) return false; int32_t radius = intValue; Spawn* spawn = new Spawn(centerPos, radius); if(checkDuplicate) { for(SpawnList::iterator it = spawnList.begin(); it != spawnList.end(); ++it) { if((*it)->getPosition() == centerPos) delete *it; } } spawnList.push_back(spawn); xmlNodePtr tmpNode = p->children; while(tmpNode) { if(!xmlStrcmp(tmpNode->name, (const xmlChar*)"monster")) { std::string name; if(!readXMLString(tmpNode, "name", strValue)) { tmpNode = tmpNode->next; continue; } name = strValue; int32_t interval = MINSPAWN_INTERVAL / 1000; if(readXMLInteger(tmpNode, "spawntime", intValue) || readXMLInteger(tmpNode, "interval", intValue)) { if(intValue <= interval) { std::cout << "[Warning - Spawns::loadFromXml] " << name << " " << centerPos << " spawntime cannot"; std::cout << " be less than " << interval << " seconds." << std::endl; tmpNode = tmpNode->next; continue; } interval = intValue; } interval *= 1000; Position placePos = centerPos; if(readXMLInteger(tmpNode, "x", intValue)) placePos.x += intValue; if(readXMLInteger(tmpNode, "y", intValue)) placePos.y += intValue; if(readXMLInteger(tmpNode, "z", intValue)) placePos.z /*+*/= intValue; Direction direction = NORTH; if(readXMLInteger(tmpNode, "direction", intValue) && direction >= EAST && direction <= WEST) direction = (Direction)intValue; spawn->addMonster(name, placePos, direction, interval); } else if(!xmlStrcmp(tmpNode->name, (const xmlChar*)"npc")) { std::string name; if(!readXMLString(tmpNode, "name", strValue)) { tmpNode = tmpNode->next; continue; } name = strValue; Position placePos = centerPos; if(readXMLInteger(tmpNode, "x", intValue)) placePos.x += intValue; if(readXMLInteger(tmpNode, "y", intValue)) placePos.y += intValue; if(readXMLInteger(tmpNode, "z", intValue)) placePos.z /*+*/= intValue; Direction direction = NORTH; if(readXMLInteger(tmpNode, "direction", intValue) && direction >= EAST && direction <= WEST) direction = (Direction)intValue; Npc* npc = Npc::createNpc(name); if(!npc) { tmpNode = tmpNode->next; continue; } npc->setMasterPos(placePos, radius); npc->setDirection(direction); npcList.push_back(npc); } tmpNode = tmpNode->next; } return true; }
void otserv(StringVec, ServiceManager* services) { srand((uint32_t)OTSYS_TIME()); #if defined(WINDOWS) SetConsoleTitle(SOFTWARE_NAME); #endif g_game.setGameState(GAMESTATE_STARTUP); #if !defined(WINDOWS) && !defined(__ROOT_PERMISSION__) if(!getuid() || !geteuid()) { std::clog << "> WARNING: " << SOFTWARE_NAME << " has been executed as super user! It is " << "recommended to run as a normal user." << std::endl << "Continue? (y/N)" << std::endl; char buffer = getch(); if(buffer != 121 && buffer != 89) startupErrorMessage("Aborted."); } #endif std::clog << SOFTWARE_NAME << " " << SOFTWARE_VERSION << std::endl << std::endl; std::stringstream ss; #ifdef __DEBUG__ ss << " GLOBAL"; #endif #ifdef __DEBUG_MOVESYS__ ss << " MOVESYS"; #endif #ifdef __DEBUG_CHAT__ ss << " CHAT"; #endif #ifdef __DEBUG_EXCEPTION_REPORT__ ss << " EXCEPTION-REPORT"; #endif #ifdef __DEBUG_HOUSES__ ss << " HOUSES"; #endif #ifdef __DEBUG_LUASCRIPTS__ ss << " LUA-SCRIPTS"; #endif #ifdef __DEBUG_MAILBOX__ ss << " MAILBOX"; #endif #ifdef __DEBUG_NET__ ss << " NET"; #endif #ifdef __DEBUG_NET_DETAIL__ ss << " NET-DETAIL"; #endif #ifdef __DEBUG_RAID__ ss << " RAIDS"; #endif #ifdef __DEBUG_SCHEDULER__ ss << " SCHEDULER"; #endif #ifdef __DEBUG_SPAWN__ ss << " SPAWNS"; #endif #ifdef __SQL_QUERY_DEBUG__ ss << " SQL-QUERIES"; #endif std::string debug = ss.str(); if(!debug.empty()) std::clog << ">> Debugging:" << debug << "." << std::endl; std::clog << ">> Loading config (" << g_config.getString(ConfigManager::CONFIG_FILE) << ")" << std::endl; if(!g_config.load()) startupErrorMessage("Unable to load " + g_config.getString(ConfigManager::CONFIG_FILE) + "!"); // silently append trailing slash std::string path = g_config.getString(ConfigManager::DATA_DIRECTORY); g_config.setString(ConfigManager::DATA_DIRECTORY, path.erase(path.find_last_not_of("/") + 1) + "/"); path = g_config.getString(ConfigManager::LOGS_DIRECTORY); g_config.setString(ConfigManager::LOGS_DIRECTORY, path.erase(path.find_last_not_of("/") + 1) + "/"); std::clog << ">> Opening logs" << std::endl; Logger::getInstance()->open(); IntegerVec cores = vectorAtoi(explodeString(g_config.getString(ConfigManager::CORES_USED), ",")); if(cores[0] != -1) { #ifdef WINDOWS int32_t mask = 0; for(IntegerVec::iterator it = cores.begin(); it != cores.end(); ++it) mask += 1 << (*it); SetProcessAffinityMask(GetCurrentProcess(), mask); } std::stringstream mutexName; mutexName << "forgottenserver_" << g_config.getNumber(ConfigManager::WORLD_ID); CreateMutex(NULL, FALSE, mutexName.str().c_str()); if(GetLastError() == ERROR_ALREADY_EXISTS) startupErrorMessage("Another instance of The Forgotten Server is already running with the same worldId.\nIf you want to run multiple servers, please change the worldId in configuration file."); std::string defaultPriority = asLowerCaseString(g_config.getString(ConfigManager::DEFAULT_PRIORITY)); if(defaultPriority == "realtime") SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS); else if(defaultPriority == "high") SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); else if(defaultPriority == "higher") SetPriorityClass(GetCurrentProcess(), ABOVE_NORMAL_PRIORITY_CLASS); #else #ifndef MACOS cpu_set_t mask; CPU_ZERO(&mask); for(IntegerVec::iterator it = cores.begin(); it != cores.end(); ++it) CPU_SET((*it), &mask); sched_setaffinity(getpid(), (int32_t)sizeof(mask), &mask); }