void Raids::checkRaids() { if (!getRunning()) { uint64_t now = OTSYS_TIME(); for (auto it = raidList.begin(), end = raidList.end(); it != end; ++it) { Raid* raid = *it; if (now >= (getLastRaidEnd() + raid->getMargin())) { if (((MAX_RAND_RANGE * CHECK_RAIDS_INTERVAL) / raid->getInterval()) >= static_cast<uint32_t>(uniform_random(0, MAX_RAND_RANGE))) { setRunning(raid); raid->startRaid(); if (!raid->canBeRepeated()) { raidList.erase(it); } break; } } } } checkRaidsEvent = g_scheduler.addEvent(createSchedulerTask(CHECK_RAIDS_INTERVAL * 1000, std::bind(&Raids::checkRaids, this))); }
bool Actions::useItem(Player* player, const Position& pos, uint8_t index, Item* item, bool isHotkey) { if (!player->canDoAction()) { return false; } player->setNextActionTask(nullptr); player->setNextAction(OTSYS_TIME() + g_config.getNumber(ConfigManager::ACTIONS_DELAY_INTERVAL)); player->stopWalk(); if (isHotkey) { showUseHotkeyMessage(player, item->getID(), player->__getItemTypeCount(item->getID(), -1)); } ReturnValue ret = internalUseItem(player, pos, index, item, 0); if (ret != RET_NOERROR) { player->sendCancelMessage(ret); return false; } return true; }
bool Ban::acceptConnection(uint32_t clientip) { std::lock_guard<std::recursive_mutex> lockClass(lock); uint64_t currentTime = OTSYS_TIME(); auto it = ipConnectMap.find(clientip); if (it == ipConnectMap.end()) { ConnectBlock cb; cb.lastAttempt = currentTime; cb.blockTime = 0; cb.count = 1; ipConnectMap[clientip] = cb; return true; } ConnectBlock& connectBlock = it->second; if (connectBlock.blockTime > currentTime) { connectBlock.blockTime += 250; return false; } int64_t timeDiff = currentTime - connectBlock.lastAttempt; connectBlock.lastAttempt = currentTime; if (timeDiff <= 5000) { if (++connectBlock.count > 5) { connectBlock.count = 0; if (timeDiff <= 500) { connectBlock.blockTime = currentTime + 3000; return false; } } } else { connectBlock.count = 1; } return true; }
bool Party::canUseSharedExperience(const Player* player) const { uint32_t highestLevel = getLeader()->getLevel(); for(PlayerVector::const_iterator it = memberList.begin(); it != memberList.end(); ++it){ if( (*it)->getLevel() > highestLevel){ highestLevel = (*it)->getLevel(); } } uint32_t minLevel = (int32_t)std::ceil(((float)(highestLevel) * 2) / 3); if(player->getLevel() < minLevel){ return false; } const Position& leaderPos = getLeader()->getPosition(); const Position& memberPos = player->getPosition(); if(!Position::areInRange<30,30,1>(leaderPos, memberPos)){ return false; } if(!player->hasFlag(PlayerFlag_NotGainInFight)){ //check if the player has healed/attacked anything recently CountMap::const_iterator it = pointMap.find(player->getID()); if(it == pointMap.end()){ return false; } uint64_t timeDiff = OTSYS_TIME() - it->second.ticks; if(timeDiff > g_game.getInFightTicks()){ //player has not attacked or healed anyone for a period of infight ticks return false; } } return true; }
void MagicField::onStepInField(const CreatureP& creature) { if(getId() == ITEM_MAGICWALL_SAFE || getId() == ITEM_WILDGROWTH_SAFE || isBlocking(creature.get())) { if(!creature->isGhost()) server.game().internalRemoveItem(creature.get(), this, 1); return; } if(!getKind()->condition) return; Condition* condition = getKind()->condition->clone(); uint32_t ownerId = getOwner(); if(ownerId && !getTile()->hasFlag(TILESTATE_PVPZONE)) { if(auto owner = server.world().getCreatureById(ownerId)) { bool harmful = true; if((server.game().getWorldType() == WORLD_TYPE_NO_PVP || getTile()->hasFlag(TILESTATE_NOPVPZONE)) && (owner->getPlayer() || owner->hasController())) harmful = false; else if(Player* targetPlayer = creature->getPlayer()) { if(owner->getPlayer() && Combat::isProtected(owner->getPlayer(), targetPlayer)) harmful = false; } if(!harmful || (OTSYS_TIME() - createTime) <= (uint32_t)server.configManager().getNumber( ConfigManager::FIELD_OWNERSHIP) || creature->hasBeenAttacked(ownerId)) condition->setParam(CONDITIONPARAM_OWNER, ownerId); } } creature->addCondition(condition); }
void Creature::onWalk(Direction& dir) { int32_t drunk = -1; if(!isSuppress(CONDITION_DRUNK)) { Condition* condition = NULL; for(ConditionList::const_iterator it = conditions.begin(); it != conditions.end(); ++it) { if(!(condition = *it) || condition->getType() != CONDITION_DRUNK) continue; int32_t subId = condition->getSubId(); if((!condition->getEndTime() || condition->getEndTime() >= OTSYS_TIME()) && subId > drunk) drunk = subId; } } if(drunk < 0) return; drunk += 25; int32_t r = random_range(1, 100); if(r > drunk) return; int32_t tmp = (drunk / 5); if(r <= tmp) dir = NORTH; else if(r <= (tmp * 2)) dir = WEST; else if(r <= (tmp * 3)) dir = SOUTH; else if(r <= (tmp * 4)) dir = EAST; g_game.internalCreatureSay(this, MSG_SPEAK_MONSTER_SAY, "Hicks!", isGhost()); }
bool Party::canUseSharedExperience(const Player* player) const { if (memberList.empty()) { return false; } uint32_t highestLevel = leader->getLevel(); for (Player* member : memberList) { if (member->getLevel() > highestLevel) { highestLevel = member->getLevel(); } } uint32_t minLevel = static_cast<int32_t>(std::ceil((static_cast<float>(highestLevel) * 2) / 3)); if (player->getLevel() < minLevel) { return false; } if (!Position::areInRange<30, 30, 1>(leader->getPosition(), player->getPosition())) { return false; } if (!player->hasFlag(PlayerFlag_NotGainInFight)) { //check if the player has healed/attacked anything recently auto it = ticksMap.find(player->getID()); if (it == ticksMap.end()) { return false; } uint64_t timeDiff = OTSYS_TIME() - it->second; if (timeDiff > static_cast<uint64_t>(g_config.getNumber(ConfigManager::PZ_LOCKED))) { return false; } } return true; }
void Spawn::cleanup() { Monster* monster; uint32_t spawnId; for (SpawnedMap::iterator it = spawnedMap.begin(); it != spawnedMap.end();) { spawnId = it->first; monster = it->second; if (monster->isRemoved()) { if (spawnId != 0) { spawnMap[spawnId].lastSpawn = OTSYS_TIME(); } monster->releaseThing2(); spawnedMap.erase(it++); } else if (!isInSpawnZone(monster->getPosition()) && spawnId != 0) { spawnedMap.insert(spawned_pair(0, monster)); spawnedMap.erase(it++); } else { ++it; } } }
bool Spawn::spawnMonster(uint32_t spawnId, MonsterType* mType, const Position& pos, Direction dir, bool startup /*= false*/) { std::unique_ptr<Monster> monster_ptr(new Monster(mType)); if (startup) { //No need to send out events to the surrounding since there is no one out there to listen! if (!g_game.internalPlaceCreature(monster_ptr.get(), pos, true)) { return false; } } else { if (!g_game.placeCreature(monster_ptr.get(), pos, false, true)) { return false; } } Monster* monster = monster_ptr.release(); monster->setDirection(dir); monster->setSpawn(this); monster->setMasterPos(pos); monster->incrementReferenceCounter(); spawnedMap.insert(spawned_pair(spawnId, monster)); spawnMap[spawnId].lastSpawn = OTSYS_TIME(); return true; }
void Raids::checkRaids() { if(!getRunning()) { uint64_t now = OTSYS_TIME(); for(RaidList::iterator it = raidList.begin(); it != raidList.end(); ++it) { if(now >= (getLastRaidEnd() + (*it)->getMargin())) { if(MAX_RAND_RANGE*CHECK_RAIDS_INTERVAL/(*it)->getInterval() >= (uint32_t)random_range(0, MAX_RAND_RANGE)) { #ifdef __DEBUG_RAID__ std::cout << formatDate(time(NULL)) << " [Notice] Raids: Starting raid " << (*it)->getName() << std::endl; #endif setRunning(*it); (*it)->startRaid(); break; } } } } checkRaidsEvent = g_scheduler.addEvent(createSchedulerTask(CHECK_RAIDS_INTERVAL * 1000, boost::bind(&Raids::checkRaids, this))); }
void ProtocolStatus::sendStatusString() { OutputMessage_ptr output = OutputMessagePool::getInstance()->getOutputMessage(this, false); if (!output) { getConnection()->close(); return; } setRawMessages(true); pugi::xml_document doc; pugi::xml_node decl = doc.prepend_child(pugi::node_declaration); decl.append_attribute("version") = "1.0"; pugi::xml_node tsqp = doc.append_child("tsqp"); tsqp.append_attribute("version") = "1.0"; pugi::xml_node serverinfo = tsqp.append_child("serverinfo"); uint64_t uptime = (OTSYS_TIME() - ProtocolStatus::start) / 1000; serverinfo.append_attribute("uptime") = std::to_string(uptime).c_str(); serverinfo.append_attribute("ip") = g_config.getString(ConfigManager::IP).c_str(); serverinfo.append_attribute("servername") = g_config.getString(ConfigManager::SERVER_NAME).c_str(); serverinfo.append_attribute("port") = std::to_string(g_config.getNumber(ConfigManager::LOGIN_PORT)).c_str(); serverinfo.append_attribute("location") = g_config.getString(ConfigManager::LOCATION).c_str(); serverinfo.append_attribute("url") = g_config.getString(ConfigManager::URL).c_str(); serverinfo.append_attribute("server") = STATUS_SERVER_NAME; serverinfo.append_attribute("version") = STATUS_SERVER_VERSION; serverinfo.append_attribute("client") = CLIENT_VERSION_STR; pugi::xml_node owner = tsqp.append_child("owner"); owner.append_attribute("name") = g_config.getString(ConfigManager::OWNER_NAME).c_str(); owner.append_attribute("email") = g_config.getString(ConfigManager::OWNER_EMAIL).c_str(); pugi::xml_node players = tsqp.append_child("players"); players.append_attribute("online") = std::to_string(g_game.getPlayersOnline()).c_str(); players.append_attribute("max") = std::to_string(g_config.getNumber(ConfigManager::MAX_PLAYERS)).c_str(); players.append_attribute("peak") = std::to_string(g_game.getPlayersRecord()).c_str(); pugi::xml_node monsters = tsqp.append_child("monsters"); monsters.append_attribute("total") = std::to_string(g_game.getMonstersOnline()).c_str(); pugi::xml_node npcs = tsqp.append_child("npcs"); npcs.append_attribute("total") = std::to_string(g_game.getNpcsOnline()).c_str(); pugi::xml_node rates = tsqp.append_child("rates"); rates.append_attribute("experience") = std::to_string(g_config.getNumber(ConfigManager::RATE_EXPERIENCE)).c_str(); rates.append_attribute("skill") = std::to_string(g_config.getNumber(ConfigManager::RATE_SKILL)).c_str(); rates.append_attribute("loot") = std::to_string(g_config.getNumber(ConfigManager::RATE_LOOT)).c_str(); rates.append_attribute("magic") = std::to_string(g_config.getNumber(ConfigManager::RATE_MAGIC)).c_str(); rates.append_attribute("spawn") = std::to_string(g_config.getNumber(ConfigManager::RATE_SPAWN)).c_str(); pugi::xml_node map = tsqp.append_child("map"); map.append_attribute("name") = g_config.getString(ConfigManager::MAP_NAME).c_str(); map.append_attribute("author") = g_config.getString(ConfigManager::MAP_AUTHOR).c_str(); uint32_t mapWidth, mapHeight; g_game.getMapDimensions(mapWidth, mapHeight); map.append_attribute("width") = std::to_string(mapWidth).c_str(); map.append_attribute("height") = std::to_string(mapHeight).c_str(); pugi::xml_node motd = tsqp.append_child("motd"); motd.text() = g_config.getString(ConfigManager::MOTD).c_str(); std::ostringstream ss; doc.save(ss, "", pugi::format_raw); std::string data = ss.str(); output->addBytes(data.c_str(), data.size()); OutputMessagePool::getInstance()->send(output); getConnection()->close(); }
void ProtocolStatus::sendInfo(uint16_t requestedInfo, const std::string& characterName) { OutputMessage_ptr output = OutputMessagePool::getInstance()->getOutputMessage(this, false); if (!output) { getConnection()->close(); return; } if (requestedInfo & REQUEST_BASIC_SERVER_INFO) { output->addByte(0x10); output->addString(g_config.getString(ConfigManager::SERVER_NAME)); output->addString(g_config.getString(ConfigManager::IP)); output->addString(std::to_string(g_config.getNumber(ConfigManager::LOGIN_PORT))); } if (requestedInfo & REQUEST_OWNER_SERVER_INFO) { output->addByte(0x11); output->addString(g_config.getString(ConfigManager::OWNER_NAME)); output->addString(g_config.getString(ConfigManager::OWNER_EMAIL)); } if (requestedInfo & REQUEST_MISC_SERVER_INFO) { output->addByte(0x12); output->addString(g_config.getString(ConfigManager::MOTD)); output->addString(g_config.getString(ConfigManager::LOCATION)); output->addString(g_config.getString(ConfigManager::URL)); output->add<uint64_t>((OTSYS_TIME() - ProtocolStatus::start) / 1000); } if (requestedInfo & REQUEST_PLAYERS_INFO) { output->addByte(0x20); output->add<uint32_t>(g_game.getPlayersOnline()); output->add<uint32_t>(g_config.getNumber(ConfigManager::MAX_PLAYERS)); output->add<uint32_t>(g_game.getPlayersRecord()); } if (requestedInfo & REQUEST_MAP_INFO) { output->addByte(0x30); output->addString(g_config.getString(ConfigManager::MAP_NAME)); output->addString(g_config.getString(ConfigManager::MAP_AUTHOR)); uint32_t mapWidth, mapHeight; g_game.getMapDimensions(mapWidth, mapHeight); output->add<uint16_t>(mapWidth); output->add<uint16_t>(mapHeight); } if (requestedInfo & REQUEST_EXT_PLAYERS_INFO) { output->addByte(0x21); // players info - online players list const auto& players = g_game.getPlayers(); output->add<uint32_t>(players.size()); for (const auto& it : players) { output->addString(it.second->getName()); output->add<uint32_t>(it.second->getLevel()); } } if (requestedInfo & REQUEST_PLAYER_STATUS_INFO) { output->addByte(0x22); // players info - online status info of a player if (g_game.getPlayerByName(characterName) != nullptr) { output->addByte(0x01); } else { output->addByte(0x00); } } if (requestedInfo & REQUEST_SERVER_SOFTWARE_INFO) { output->addByte(0x23); // server software info output->addString(STATUS_SERVER_NAME); output->addString(STATUS_SERVER_VERSION); output->addString(CLIENT_VERSION_STR); } OutputMessagePool::getInstance()->send(output); getConnection()->close(); }
#include "otpch.h" #include "protocolstatus.h" #include "configmanager.h" #include "game.h" #include "connection.h" #include "networkmessage.h" #include "outputmessage.h" #include "tools.h" #include "tasks.h" extern ConfigManager g_config; extern Game g_game; std::map<uint32_t, int64_t> ProtocolStatus::ipConnectMap; const uint64_t ProtocolStatus::start = OTSYS_TIME(); enum RequestedInfo_t : uint16_t { REQUEST_BASIC_SERVER_INFO = 1 << 0, REQUEST_OWNER_SERVER_INFO = 1 << 1, REQUEST_MISC_SERVER_INFO = 1 << 2, REQUEST_PLAYERS_INFO = 1 << 3, REQUEST_MAP_INFO = 1 << 4, REQUEST_EXT_PLAYERS_INFO = 1 << 5, REQUEST_PLAYER_STATUS_INFO = 1 << 6, REQUEST_SERVER_SOFTWARE_INFO = 1 << 7, }; void ProtocolStatus::onRecvFirstMessage(NetworkMessage& msg) { uint32_t ip = getIP();
void Creature::onCreatureMove(const Creature* creature, const Tile* newTile, const Position& newPos, const Tile* oldTile, const Position& oldPos, bool teleport) { if (creature == this) { lastStep = OTSYS_TIME(); lastStepCost = 1; if (!teleport) { if (oldPos.z != newPos.z) { //floor change extra cost lastStepCost = 2; } else if (Position::getDistanceX(newPos, oldPos) >= 1 && Position::getDistanceY(newPos, oldPos) >= 1) { //diagonal extra cost lastStepCost = 2; } } else { stopEventWalk(); } if (!summons.empty()) { //check if any of our summons is out of range (+/- 2 floors or 30 tiles away) std::list<Creature*> despawnList; std::list<Creature*>::iterator cit; for (cit = summons.begin(); cit != summons.end(); ++cit) { const Position pos = (*cit)->getPosition(); if (Position::getDistanceZ(newPos, pos) > 2 || (std::max<int32_t>(Position::getDistanceX(newPos, pos), Position::getDistanceY(newPos, pos)) > 30)) { despawnList.push_back((*cit)); } } for (cit = despawnList.begin(); cit != despawnList.end(); ++cit) { g_game.removeCreature((*cit), true); } } if (newTile->getZone() != oldTile->getZone()) { onChangeZone(getZone()); } //update map cache if (isMapLoaded) { if (teleport || oldPos.z != newPos.z) { updateMapCache(); } else { Tile* tile; const Position& myPos = getPosition(); Position pos; if (oldPos.y > newPos.y) { //north //shift y south for (int32_t y = mapWalkHeight - 1 - 1; y >= 0; --y) { memcpy(localMapCache[y + 1], localMapCache[y], sizeof(localMapCache[y])); } //update 0 for (int32_t x = -((mapWalkWidth - 1) / 2); x <= ((mapWalkWidth - 1) / 2); ++x) { tile = g_game.getTile(myPos.getX() + x, myPos.getY() - ((mapWalkHeight - 1) / 2), myPos.z); updateTileCache(tile, x, -((mapWalkHeight - 1) / 2)); } } else if (oldPos.y < newPos.y) { // south //shift y north for (int32_t y = 0; y <= mapWalkHeight - 1 - 1; ++y) { memcpy(localMapCache[y], localMapCache[y + 1], sizeof(localMapCache[y])); } //update mapWalkHeight - 1 for (int32_t x = -((mapWalkWidth - 1) / 2); x <= ((mapWalkWidth - 1) / 2); ++x) { tile = g_game.getTile(myPos.getX() + x, myPos.getY() + ((mapWalkHeight - 1) / 2), myPos.z); updateTileCache(tile, x, (mapWalkHeight - 1) / 2); } } if (oldPos.x < newPos.x) { // east //shift y west int32_t starty = 0; int32_t endy = mapWalkHeight - 1; int32_t dy = Position::getDistanceY(oldPos, newPos); if (dy < 0) { endy += dy; } else if (dy > 0) { starty = dy; } for (int32_t y = starty; y <= endy; ++y) { for (int32_t x = 0; x <= mapWalkWidth - 2; ++x) { localMapCache[y][x] = localMapCache[y][x + 1]; } } //update mapWalkWidth - 1 for (int32_t y = -((mapWalkHeight - 1) / 2); y <= ((mapWalkHeight - 1) / 2); ++y) { tile = g_game.getTile(myPos.x + ((mapWalkWidth - 1) / 2), myPos.y + y, myPos.z); updateTileCache(tile, (mapWalkWidth - 1) / 2, y); } } else if (oldPos.x > newPos.x) { // west //shift y east int32_t starty = 0; int32_t endy = mapWalkHeight - 1; int32_t dy = Position::getDistanceY(oldPos, newPos); if (dy < 0) { endy += dy; } else if (dy > 0) { starty = dy; } for (int32_t y = starty; y <= endy; ++y) { for (int32_t x = mapWalkWidth - 2; x >= 0; --x) { localMapCache[y][x + 1] = localMapCache[y][x]; } } //update 0 for (int32_t y = -((mapWalkHeight - 1) / 2); y <= ((mapWalkHeight - 1) / 2); ++y) { tile = g_game.getTile(myPos.x - ((mapWalkWidth - 1) / 2), myPos.y + y, myPos.z); updateTileCache(tile, -((mapWalkWidth - 1) / 2), y); } } updateTileCache(oldTile, oldPos); } } } else { if (isMapLoaded) { const Position& myPos = getPosition(); if (newPos.z == myPos.z) { updateTileCache(newTile, newPos); } if (oldPos.z == myPos.z) { updateTileCache(oldTile, oldPos); } } } if (creature == followCreature || (creature == this && followCreature)) { if (hasFollowPath) { isUpdatingPath = true; } if (newPos.z != oldPos.z || !canSee(followCreature->getPosition())) { onCreatureDisappear(followCreature, false); } } if (creature == attackedCreature || (creature == this && attackedCreature)) { if (newPos.z != oldPos.z || !canSee(attackedCreature->getPosition())) { onCreatureDisappear(attackedCreature, false); } else { if (hasExtraSwing()) { //our target is moving lets see if we can get in hit g_dispatcher.addTask(createTask(boost::bind(&Game::checkCreatureAttack, &g_game, getID()))); } if (newTile->getZone() != oldTile->getZone()) { onAttackedCreatureChangeZone(attackedCreature->getZone()); } } } }
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; }
void Creature::onDeath() { bool lastHitUnjustified = false; bool mostDamageUnjustified = false; Creature* lastHitCreature = g_game.getCreatureByID(lastHitCreatureId); Creature* lastHitCreatureMaster; if (lastHitCreature) { lastHitUnjustified = lastHitCreature->onKilledCreature(this); lastHitCreatureMaster = lastHitCreature->getMaster(); } else { lastHitCreatureMaster = nullptr; } Creature* mostDamageCreature = nullptr; const int64_t timeNow = OTSYS_TIME(); const uint32_t inFightTicks = g_config.getNumber(ConfigManager::PZ_LOCKED); int32_t mostDamage = 0; std::map<Creature*, uint64_t> experienceMap; for (const auto& it : damageMap) { if (Creature* attacker = g_game.getCreatureByID(it.first)) { CountBlock_t cb = it.second; if ((cb.total > mostDamage && (timeNow - cb.ticks <= inFightTicks))) { mostDamage = cb.total; mostDamageCreature = attacker; } if (attacker != this) { uint64_t gainExp = getGainedExperience(attacker); if (Player* player = attacker->getPlayer()) { Party* party = player->getParty(); if (party && party->getLeader() && party->isSharedExperienceActive() && party->isSharedExperienceEnabled()) { attacker = party->getLeader(); } } auto tmpIt = experienceMap.find(attacker); if (tmpIt == experienceMap.end()) { experienceMap[attacker] = gainExp; } else { tmpIt->second += gainExp; } } } } for (const auto& it : experienceMap) { it.first->onGainExperience(it.second, this); } if (mostDamageCreature) { if (mostDamageCreature != lastHitCreature && mostDamageCreature != lastHitCreatureMaster) { Creature* mostDamageCreatureMaster = mostDamageCreature->getMaster(); if (lastHitCreature != mostDamageCreatureMaster && (lastHitCreatureMaster == nullptr || mostDamageCreatureMaster != lastHitCreatureMaster)) { mostDamageUnjustified = mostDamageCreature->onKilledCreature(this, false); } } } bool droppedCorpse = dropCorpse(lastHitCreature, mostDamageCreature, lastHitUnjustified, mostDamageUnjustified); death(lastHitCreature); if (master) { master->removeSummon(this); } if (droppedCorpse) { g_game.removeCreature(this, false); } }
void Condition::setTicks(int32_t _ticks) { ticks = _ticks; if(_ticks > 0) endTime = OTSYS_TIME() + _ticks; }
void Dispatcher::dispatcherThread(void* p) { #if defined __EXCEPTION_TRACER__ ExceptionHandler dispatcherExceptionHandler; dispatcherExceptionHandler.InstallHandler(); #endif srand((unsigned int)OTSYS_TIME()); #ifdef __DEBUG_SCHEDULER__ std::cout << "Starting Dispatcher" << std::endl; #endif OutputMessagePool* outputPool; // NOTE: second argument defer_lock is to prevent from immediate locking boost::unique_lock<boost::mutex> taskLockUnique(getDispatcher().m_taskLock, boost::defer_lock); while(Dispatcher::m_threadState != Dispatcher::STATE_TERMINATED){ Task* task = NULL; // check if there are tasks waiting taskLockUnique.lock();//getDispatcher().m_taskLock.lock(); if(getDispatcher().m_taskList.empty()){ //if the list is empty wait for signal #ifdef __DEBUG_SCHEDULER__ std::cout << "Dispatcher: Waiting for task" << std::endl; #endif getDispatcher().m_taskSignal.wait(taskLockUnique); } #ifdef __DEBUG_SCHEDULER__ std::cout << "Dispatcher: Signalled" << std::endl; #endif if(!getDispatcher().m_taskList.empty() && (Dispatcher::m_threadState != Dispatcher::STATE_TERMINATED)){ // take the first task task = getDispatcher().m_taskList.front(); getDispatcher().m_taskList.pop_front(); } taskLockUnique.unlock(); // finally execute the task... if(task){ OutputMessagePool::getInstance()->startExecutionFrame(); (*task)(); delete task; outputPool = OutputMessagePool::getInstance(); if(outputPool){ outputPool->sendAll(); } g_game.clearSpectatorCache(); #ifdef __DEBUG_SCHEDULER__ std::cout << "Dispatcher: Executing task" << std::endl; #endif } } #if defined __EXCEPTION_TRACER__ dispatcherExceptionHandler.RemoveHandler(); #endif }
int main(int argc, char *argv[]) { std::srand((uint32_t)OTSYS_TIME()); StringVec args = StringVec(argv, argv + argc); if(argc > 1 && !argumentsHandler(args)) return 0; #else void serverMain(void* param) { std::cout.rdbuf(&g_logger); std::cerr.rdbuf(&g_logger); std::clog.rdbuf(&g_logger); #endif std::set_new_handler(allocationHandler); ServiceManager servicer; g_config.startup(); #ifdef __OTSERV_ALLOCATOR_STATS__ //boost::thread(boost::bind(&allocatorStatsThread, (void*)NULL)); // TODO: this thread needs a shutdown (timed_lock + interrupt? .interrupt + .unlock) #endif #ifdef __EXCEPTION_TRACER__ ExceptionHandler mainExceptionHandler; mainExceptionHandler.InstallHandler(); #endif #ifndef WINDOWS // ignore sigpipe... struct sigaction sigh; sigh.sa_handler = SIG_IGN; sigh.sa_flags = 0; sigemptyset(&sigh.sa_mask); sigaction(SIGPIPE, &sigh, NULL); // register signals signal(SIGHUP, signalHandler); //save signal(SIGTRAP, signalHandler); //clean signal(SIGCHLD, signalHandler); //refresh signal(SIGUSR1, signalHandler); //close server signal(SIGUSR2, signalHandler); //open server signal(SIGCONT, signalHandler); //reload all signal(SIGQUIT, signalHandler); //save & shutdown signal(SIGTERM, signalHandler); //shutdown #endif Dispatcher::getInstance().addTask(createTask(boost::bind(otserv, #if !defined(WINDOWS) || defined(_CONSOLE) args, #endif &servicer))); g_loaderSignal.wait(g_loaderUniqueLock); boost::this_thread::sleep(boost::posix_time::milliseconds(1000)); if(servicer.isRunning()) { Status::getInstance(); std::clog << ">> " << g_config.getString(ConfigManager::SERVER_NAME) << " server Online!" << std::endl << std::endl; #if defined(WINDOWS) && !defined(_CONSOLE) SendMessage(GUI::getInstance()->m_statusBar, WM_SETTEXT, 0, (LPARAM)">> server Online!"); GUI::getInstance()->m_connections = true; #endif servicer.run(); } else { Status::getInstance(); std::clog << ">> " << g_config.getString(ConfigManager::SERVER_NAME) << " server Offline! No services available..." << std::endl << std::endl; #if defined(WINDOWS) && !defined(_CONSOLE) SendMessage(GUI::getInstance()->m_statusBar, WM_SETTEXT, 0, (LPARAM)">> server Offline! No services available..."); GUI::getInstance()->m_connections = true; #endif } Dispatcher::getInstance().exit(); Scheduler::getInstance().exit(); #ifdef __EXCEPTION_TRACER__ mainExceptionHandler.RemoveHandler(); #endif #if !defined(WINDOWS) || defined(_CONSOLE) return 0; #endif }
void mainLoader(int, char*[], ServiceManager* services) { //dispatcher thread g_game.setGameState(GAME_STATE_STARTUP); srand(static_cast<unsigned int>(OTSYS_TIME())); #ifdef _WIN32 SetConsoleTitle(STATUS_SERVER_NAME); #endif std::cout << "The " << STATUS_SERVER_NAME << " Version: (" << STATUS_SERVER_VERSION << "." << MINOR_VERSION << " . " << REVISION_VERSION << ") - Codename: ( " << SOFTWARE_CODENAME << " )" << std::endl; std::cout << "Compiled with: " << BOOST_COMPILER << std::endl; std::cout << "Compiled on " << __DATE__ << ' ' << __TIME__ << " for platform "; #if defined(__amd64__) || defined(_M_X64) std::cout << "x64" << std::endl; #elif defined(__i386__) || defined(_M_IX86) || defined(_X86_) std::cout << "x86" << std::endl; #elif defined(__arm__) std::cout << "ARM" << std::endl; #else std::cout << "unknown" << std::endl; #endif std::cout << std::endl; std::cout << "A server developed by " << STATUS_SERVER_DEVELOPERS << "." << std::endl; std::cout << "Visit our forum for updates, support, and resources: " << GIT_REPO <<"." << std::endl; std::cout << std::endl; // read global config std::cout << ">> Loading config" << std::endl; if (!g_config.load()) { startupErrorMessage("Unable to load config.lua!"); return; } #ifdef _WIN32 const std::string& defaultPriority = g_config.getString(ConfigManager::DEFAULT_PRIORITY); if (strcasecmp(defaultPriority.c_str(), "high") == 0) { SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); } else if (strcasecmp(defaultPriority.c_str(), "above-normal") == 0) { SetPriorityClass(GetCurrentProcess(), ABOVE_NORMAL_PRIORITY_CLASS); } #endif //set RSA key const char* p("14299623962416399520070177382898895550795403345466153217470516082934737582776038882967213386204600674145392845853859217990626450972452084065728686565928113"); const char* q("7630979195970404721891201847792002125535401292779123937207447574596692788513647179235335529307251350570728407373705564708871762033017096809910315212884101"); g_RSA.setKey(p, q); std::cout << ">> Establishing database connection..." << std::flush; Database* db = Database::getInstance(); if (!db->connect()) { startupErrorMessage("Failed to connect to database."); return; } std::cout << " MySQL " << Database::getClientVersion() << std::endl; // run database manager std::cout << ">> Running database manager" << std::endl; if (!DatabaseManager::isDatabaseSetup()) { startupErrorMessage("The database you have specified in config.lua is empty, please import the schema.sql to your database."); return; } g_databaseTasks.start(); DatabaseManager::updateDatabase(); if (g_config.getBoolean(ConfigManager::OPTIMIZE_DATABASE) && !DatabaseManager::optimizeTables()) { std::cout << "> No tables were optimized." << std::endl; } //load vocations std::cout << ">> Loading vocations" << std::endl; if (!g_vocations.loadFromXml()) { startupErrorMessage("Unable to load vocations!"); return; } // load item data std::cout << ">> Loading items" << std::endl; if (Item::items.loadFromOtb("data/items/items.otb") != ERROR_NONE) { startupErrorMessage("Unable to load items (OTB)!"); return; } if (!Item::items.loadFromXml()) { startupErrorMessage("Unable to load items (XML)!"); return; } std::cout << ">> Loading script systems" << std::endl; if (!ScriptingManager::getInstance()->loadScriptSystems()) { startupErrorMessage("Failed to load script systems"); return; } std::cout << ">> Loading monsters" << std::endl; if (!g_monsters.loadFromXml()) { startupErrorMessage("Unable to load monsters!"); return; } std::cout << ">> Loading outfits" << std::endl; Outfits* outfits = Outfits::getInstance(); if (!outfits->loadFromXml()) { startupErrorMessage("Unable to load outfits!"); return; } std::cout << ">> Checking world type... " << std::flush; std::string worldType = asLowerCaseString(g_config.getString(ConfigManager::WORLD_TYPE)); if (worldType == "pvp") { g_game.setWorldType(WORLD_TYPE_PVP); } else if (worldType == "no-pvp") { g_game.setWorldType(WORLD_TYPE_NO_PVP); } else if (worldType == "pvp-enforced") { g_game.setWorldType(WORLD_TYPE_PVP_ENFORCED); } else { std::cout << std::endl; std::ostringstream ss; ss << "> ERROR: Unknown world type: " << g_config.getString(ConfigManager::WORLD_TYPE) << ", valid world types are: pvp, no-pvp and pvp-enforced."; startupErrorMessage(ss.str()); return; } std::cout << asUpperCaseString(worldType) << std::endl; std::cout << ">> Loading map" << std::endl; if (!g_game.loadMainMap(g_config.getString(ConfigManager::MAP_NAME))) { startupErrorMessage("Failed to load map"); return; } std::cout << ">> Initializing gamestate" << std::endl; g_game.setGameState(GAME_STATE_INIT); // Game client protocols services->add<ProtocolGame>(g_config.getNumber(ConfigManager::GAME_PORT)); services->add<ProtocolLogin>(g_config.getNumber(ConfigManager::LOGIN_PORT)); // OT protocols services->add<ProtocolStatus>(g_config.getNumber(ConfigManager::STATUS_PORT)); // Legacy login protocol services->add<ProtocolOld>(g_config.getNumber(ConfigManager::LOGIN_PORT)); RentPeriod_t rentPeriod; std::string strRentPeriod = asLowerCaseString(g_config.getString(ConfigManager::HOUSE_RENT_PERIOD)); if (strRentPeriod == "yearly") { rentPeriod = RENTPERIOD_YEARLY; } else if (strRentPeriod == "weekly") { rentPeriod = RENTPERIOD_WEEKLY; } else if (strRentPeriod == "monthly") { rentPeriod = RENTPERIOD_MONTHLY; } else if (strRentPeriod == "daily") { rentPeriod = RENTPERIOD_DAILY; } else { rentPeriod = RENTPERIOD_NEVER; } g_game.map.houses.payHouses(rentPeriod); IOMarket::checkExpiredOffers(); IOMarket::getInstance()->updateStatistics(); std::cout << ">> Loaded all modules, server starting up..." << std::endl; #ifndef _WIN32 if (getuid() == 0 || geteuid() == 0) { std::cout << "> Warning: " << STATUS_SERVER_NAME << " has been executed as root user, please consider running it as a normal user." << std::endl; } #endif g_game.start(services); g_game.setGameState(GAME_STATE_NORMAL); g_loaderSignal.notify_all(); }
void mainLoader(int, char*[], ServiceManager* services) { srand(static_cast<unsigned int>(OTSYS_TIME())); #ifdef _WIN32 SetConsoleTitle(STATUS_SERVER_NAME); #endif std::cout << STATUS_SERVER_NAME << " - Version " << STATUS_SERVER_VERSION << std::endl; std::cout << "Compiled with " << BOOST_COMPILER << std::endl; std::cout << "Compiled on " << __DATE__ << ' ' << __TIME__ << " for platform "; #if defined(__amd64__) || defined(_M_X64) std::cout << "x64" << std::endl; #elif defined(__i386__) || defined(_M_IX86) || defined(_X86_) std::cout << "x86" << std::endl; #elif defined(__arm__) std::cout << "ARM" << std::endl; #else std::cout << "unknown" << std::endl; #endif std::cout << std::endl; std::cout << "A server developed by " << STATUS_SERVER_DEVELOPERS << std::endl; std::cout << "Visit our forum for updates, support, and resources: http://otland.net/." << std::endl; std::cout << std::endl; // read global config std::cout << ">> Loading config" << std::endl; if (!g_config.load()) { startupErrorMessage("Unable to load config.lua!"); return; } std::cout << ">> Loading gameserver config..." << std::endl; if (!g_gameserver.load()) { startupErrorMessage("Unable to load gameservers!"); return; } #ifdef _WIN32 const std::string& defaultPriority = g_config.getString(ConfigManager::DEFAULT_PRIORITY); if (strcasecmp(defaultPriority.c_str(), "high") == 0) { SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); } else if (strcasecmp(defaultPriority.c_str(), "above-normal") == 0) { SetPriorityClass(GetCurrentProcess(), ABOVE_NORMAL_PRIORITY_CLASS); } #endif //set RSA key const char* p("14299623962416399520070177382898895550795403345466153217470516082934737582776038882967213386204600674145392845853859217990626450972452084065728686565928113"); const char* q("7630979195970404721891201847792002125535401292779123937207447574596692788513647179235335529307251350570728407373705564708871762033017096809910315212884101"); g_RSA.setKey(p, q); std::cout << ">> Establishing database connection..." << std::flush; Database* db = Database::getInstance(); if (!db->connect()) { startupErrorMessage("Failed to connect to database."); return; } std::cout << " MySQL " << Database::getClientVersion() << std::endl; // run database manager std::cout << ">> Running database manager" << std::endl; if (!DatabaseManager::isDatabaseSetup()) { startupErrorMessage("The database you have specified in config.lua is empty, please import the schema.sql to your database."); return; } g_databaseTasks.start(); if (g_config.getBoolean(ConfigManager::OPTIMIZE_DATABASE) && !DatabaseManager::optimizeTables()) { std::cout << "> No tables were optimized." << std::endl; } services->add<ProtocolLogin>(g_config.getNumber(ConfigManager::LOGIN_PORT)); services->add<ProtocolOld>(g_config.getNumber(ConfigManager::LOGIN_PORT)); std::cout << ">> Loaded all modules, server starting up..." << std::endl; #ifndef _WIN32 if (getuid() == 0 || geteuid() == 0) { std::cout << "> Warning: " << STATUS_SERVER_NAME << " has been executed as root user, please consider running it as a normal user." << std::endl; } #endif g_loaderSignal.notify_all(); }
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; }
long long Protocol::getSleepTicks() { long long delay = 0; int stepDuration = 0; Tile *tile =game->getTile(player->pos.x, player->pos.y, player->pos.z); if(tile && tile->ground) { int groundid = tile->ground->getID(); uint8_t stepspeed = Item::items[groundid].speed; if(stepspeed != 0) { stepDuration = player->getStepDuration(stepspeed); if(player->lastmove != 0) { delay = (((long long)(player->lastmove)) + ((long long)(stepDuration))) - ((long long)(OTSYS_TIME())); } } } return delay; }
bool IOMap::loadMap(Map* map, const std::string& identifier) { int64_t start = OTSYS_TIME(); FileLoader f; if (!f.openFile(identifier.c_str(), "OTBM")) { std::ostringstream ss; ss << "Could not open the file " << identifier << '.'; setLastErrorString(ss.str()); return false; } uint32_t type; PropStream propStream; NODE root = f.getChildNode(nullptr, type); if (!f.getProps(root, propStream)) { setLastErrorString("Could not read root property."); return false; } const OTBM_root_header* root_header; if (!propStream.readStruct(root_header)) { setLastErrorString("Could not read header."); return false; } uint32_t headerVersion = root_header->version; if (headerVersion <= 0) { //In otbm version 1 the count variable after splashes/fluidcontainers and stackables //are saved as attributes instead, this solves alot of problems with items //that is changed (stackable/charges/fluidcontainer/splash) during an update. setLastErrorString("This map need to be upgraded by using the latest map editor version to be able to load correctly."); return false; } if (headerVersion > 2) { setLastErrorString("Unknown OTBM version detected."); return false; } if (root_header->majorVersionItems < 3) { setLastErrorString("This map need to be upgraded by using the latest map editor version to be able to load correctly."); return false; } if (root_header->majorVersionItems > Items::dwMajorVersion) { setLastErrorString("The map was saved with a different items.otb version, an upgraded items.otb is required."); return false; } if (root_header->minorVersionItems < CLIENT_VERSION_810) { setLastErrorString("This map needs to be updated."); return false; } if (root_header->minorVersionItems > Items::dwMinorVersion) { std::cout << "[Warning - IOMap::loadMap] This map needs an updated items.otb." << std::endl; } std::cout << "> Map size: " << root_header->width << "x" << root_header->height << '.' << std::endl; map->width = root_header->width; map->height = root_header->height; NODE nodeMap = f.getChildNode(root, type); if (type != OTBM_MAP_DATA) { setLastErrorString("Could not read data node."); return false; } if (!f.getProps(nodeMap, propStream)) { setLastErrorString("Could not read map data attributes."); return false; } std::string mapDescription; std::string tmp; uint8_t attribute; while (propStream.read<uint8_t>(attribute)) { switch (attribute) { case OTBM_ATTR_DESCRIPTION: if (!propStream.readString(mapDescription)) { setLastErrorString("Invalid description tag."); return false; } break; case OTBM_ATTR_EXT_SPAWN_FILE: if (!propStream.readString(tmp)) { setLastErrorString("Invalid spawn tag."); return false; } map->spawnfile = identifier.substr(0, identifier.rfind('/') + 1); map->spawnfile += tmp; break; case OTBM_ATTR_EXT_HOUSE_FILE: if (!propStream.readString(tmp)) { setLastErrorString("Invalid house tag."); return false; } map->housefile = identifier.substr(0, identifier.rfind('/') + 1); map->housefile += tmp; break; default: setLastErrorString("Unknown header node."); return false; } } NODE nodeMapData = f.getChildNode(nodeMap, type); while (nodeMapData != NO_NODE) { if (f.getError() != ERROR_NONE) { setLastErrorString("Invalid map node."); return false; } if (type == OTBM_TILE_AREA) { if (!f.getProps(nodeMapData, propStream)) { setLastErrorString("Invalid map node."); return false; } const OTBM_Destination_coords* area_coord; if (!propStream.readStruct(area_coord)) { setLastErrorString("Invalid map node."); return false; } int32_t base_x = area_coord->x; int32_t base_y = area_coord->y; int32_t base_z = area_coord->z; NODE nodeTile = f.getChildNode(nodeMapData, type); while (nodeTile != NO_NODE) { if (f.getError() != ERROR_NONE) { setLastErrorString("Could not read node data."); return false; } if (type != OTBM_TILE && type != OTBM_HOUSETILE) { setLastErrorString("Unknown tile node."); return false; } if (!f.getProps(nodeTile, propStream)) { setLastErrorString("Could not read node data."); return false; } const OTBM_Tile_coords* tile_coord; if (!propStream.readStruct(tile_coord)) { setLastErrorString("Could not read tile position."); return false; } uint16_t px = base_x + tile_coord->x; uint16_t py = base_y + tile_coord->y; uint16_t pz = base_z; bool isHouseTile = false; House* house = nullptr; Tile* tile = nullptr; Item* ground_item = nullptr; uint32_t tileflags = TILESTATE_NONE; if (type == OTBM_HOUSETILE) { uint32_t houseId; if (!propStream.read<uint32_t>(houseId)) { std::ostringstream ss; ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] Could not read house id."; setLastErrorString(ss.str()); return false; } house = map->houses.addHouse(houseId); if (!house) { std::ostringstream ss; ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] Could not create house id: " << houseId; setLastErrorString(ss.str()); return false; } tile = new HouseTile(px, py, pz, house); house->addTile(reinterpret_cast<HouseTile*>(tile)); isHouseTile = true; } //read tile attributes while (propStream.read<uint8_t>(attribute)) { switch (attribute) { case OTBM_ATTR_TILE_FLAGS: { uint32_t flags; if (!propStream.read<uint32_t>(flags)) { std::ostringstream ss; ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] Failed to read tile flags."; setLastErrorString(ss.str()); return false; } if ((flags & TILESTATE_PROTECTIONZONE) == TILESTATE_PROTECTIONZONE) { tileflags |= TILESTATE_PROTECTIONZONE; } else if ((flags & TILESTATE_NOPVPZONE) == TILESTATE_NOPVPZONE) { tileflags |= TILESTATE_NOPVPZONE; } else if ((flags & TILESTATE_PVPZONE) == TILESTATE_PVPZONE) { tileflags |= TILESTATE_PVPZONE; } if ((flags & TILESTATE_NOLOGOUT) == TILESTATE_NOLOGOUT) { tileflags |= TILESTATE_NOLOGOUT; } break; } case OTBM_ATTR_ITEM: { Item* item = Item::CreateItem(propStream); if (!item) { std::ostringstream ss; ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] Failed to create item."; setLastErrorString(ss.str()); return false; } if (isHouseTile && item->isMoveable()) { std::cout << "[Warning - IOMap::loadMap] Moveable item with ID: " << item->getID() << ", in house: " << house->getId() << ", at position [x: " << px << ", y: " << py << ", z: " << pz << "]." << std::endl; delete item; } else { if (item->getItemCount() <= 0) { item->setItemCount(1); } if (tile) { tile->internalAddThing(item); item->startDecaying(); item->setLoadedFromMap(true); } else if (item->isGroundTile()) { delete ground_item; ground_item = item; } else { tile = createTile(ground_item, item, px, py, pz); tile->internalAddThing(item); item->startDecaying(); item->setLoadedFromMap(true); } } break; } default: std::ostringstream ss; ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] Unknown tile attribute."; setLastErrorString(ss.str()); return false; } } NODE nodeItem = f.getChildNode(nodeTile, type); while (nodeItem) { if (type != OTBM_ITEM) { std::ostringstream ss; ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] Unknown node type."; setLastErrorString(ss.str()); return false; } PropStream stream; if (!f.getProps(nodeItem, stream)) { setLastErrorString("Invalid item node."); return false; } Item* item = Item::CreateItem(stream); if (!item) { std::ostringstream ss; ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] Failed to create item."; setLastErrorString(ss.str()); return false; } if (!item->unserializeItemNode(f, nodeItem, stream)) { std::ostringstream ss; ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] Failed to load item " << item->getID() << '.'; setLastErrorString(ss.str()); delete item; return false; } if (isHouseTile && item->isMoveable()) { std::cout << "[Warning - IOMap::loadMap] Moveable item with ID: " << item->getID() << ", in house: " << house->getId() << ", at position [x: " << px << ", y: " << py << ", z: " << pz << "]." << std::endl; delete item; } else { if (item->getItemCount() <= 0) { item->setItemCount(1); } if (tile) { tile->internalAddThing(item); item->startDecaying(); item->setLoadedFromMap(true); } else if (item->isGroundTile()) { delete ground_item; ground_item = item; } else { tile = createTile(ground_item, item, px, py, pz); tile->internalAddThing(item); item->startDecaying(); item->setLoadedFromMap(true); } } nodeItem = f.getNextNode(nodeItem, type); } if (!tile) { tile = createTile(ground_item, nullptr, px, py, pz); } tile->setFlag(static_cast<tileflags_t>(tileflags)); map->setTile(px, py, pz, tile); nodeTile = f.getNextNode(nodeTile, type); } } else if (type == OTBM_TOWNS) { NODE nodeTown = f.getChildNode(nodeMapData, type); while (nodeTown != NO_NODE) { if (type != OTBM_TOWN) { setLastErrorString("Unknown town node."); return false; } if (!f.getProps(nodeTown, propStream)) { setLastErrorString("Could not read town data."); return false; } uint32_t townId; if (!propStream.read<uint32_t>(townId)) { setLastErrorString("Could not read town id."); return false; } Town* town = map->towns.getTown(townId); if (!town) { town = new Town(townId); map->towns.addTown(townId, town); } std::string townName; if (!propStream.readString(townName)) { setLastErrorString("Could not read town name."); return false; } town->setName(townName); const OTBM_Destination_coords* town_coords; if (!propStream.readStruct(town_coords)) { setLastErrorString("Could not read town coordinates."); return false; } town->setTemplePos(Position(town_coords->x, town_coords->y, town_coords->z)); nodeTown = f.getNextNode(nodeTown, type); } } else if (type == OTBM_WAYPOINTS && headerVersion > 1) { NODE nodeWaypoint = f.getChildNode(nodeMapData, type); while (nodeWaypoint != NO_NODE) { if (type != OTBM_WAYPOINT) { setLastErrorString("Unknown waypoint node."); return false; } if (!f.getProps(nodeWaypoint, propStream)) { setLastErrorString("Could not read waypoint data."); return false; } std::string name; if (!propStream.readString(name)) { setLastErrorString("Could not read waypoint name."); return false; } const OTBM_Destination_coords* waypoint_coords; if (!propStream.readStruct(waypoint_coords)) { setLastErrorString("Could not read waypoint coordinates."); return false; } map->waypoints[name] = Position(waypoint_coords->x, waypoint_coords->y, waypoint_coords->z); nodeWaypoint = f.getNextNode(nodeWaypoint, type); } } else { setLastErrorString("Unknown map node."); return false; } nodeMapData = f.getNextNode(nodeMapData, type); } std::cout << "> Map loading time: " << (OTSYS_TIME() - start) / (1000.) << " seconds." << std::endl; 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); }
void OutputMessagePool::startExecutionFrame() { m_frameTime = OTSYS_TIME(); m_shutdown = false; }
int main(int argc, char* argv[]) { #if defined WIN32 || defined __WINDOWS__ WSADATA wsd; if(WSAStartup(MAKEWORD(2,2), &wsd) != 0){ return 1; } LARGE_INTEGER counter; QueryPerformanceCounter(&counter); srand(counter.LowPart); #else srand(time(NULL)); #endif disconnect_function = getCommand("disconnect", true); ping_function = getCommand("ping", true); char command[1024]; long lineCounter = 0; long exit_code = 0; std::stringstream is; if(argc > 1){ for(int i = 1; i < argc; ++i){ is << argv[i] << std::endl; } } else{ is << std::cin.rdbuf(); } while(!is.eof()){ lineCounter++; is.getline(command, 1024); if(strcmp(command, "") != 0){ //comments line if(command[0] == '#'){ continue; } //lower case until first space for(int i = 0; i < strlen(command) && command[i] != ' '; ++i){ command[i] = tolower(command[i]); if(command[i] == '\r'){ command[i] = 0; break; } } if(strlen(command) == 0) continue; CommandLine* commandLine; if(commandLine = parseLine(command)){ commands_queue.push_back(commandLine); } else{ std::cout << "Syntax error in line " << lineCounter << " " << command << std::endl; //clear commands COMMANDS_QUEUE::iterator it; for(it = commands_queue.begin(); it != commands_queue.end(); ++it){ delete[] (*it)->params; delete *it; } commands_queue.clear(); return 1; } } } //execute commands now NetworkMessage msg; COMMANDS_QUEUE::iterator it = commands_queue.begin(); long last_ping = 0; while(it != commands_queue.end()){ OTSYS_SLEEP(250); last_ping = last_ping + 250; if(next_command_delay > 250){ next_command_delay = next_command_delay - 250; } else{ next_command_delay = 0; long long time = OTSYS_TIME(); //execute the command int retCode = (*it)->function((*it)->params); if(retCode == 1){ //everything was ok ++it; } else if(retCode == 2){ //timeout } else{ //error in the command exit_code = 1; break; } last_ping += (OTSYS_TIME() - time); } if(!g_shutdown && last_ping > 10000){ //send ping here ping_function(NULL); last_ping = 0; } } //if connected end the connection if(g_connected){ disconnect_function(NULL); } //free it for(it = commands_queue.begin(); it != commands_queue.end(); ++it){ delete[] (*it)->params; delete *it; } commands_queue.clear(); #if defined WIN32 || defined __WINDOWS__ WSACleanup(); #endif return exit_code; }
void Condition::setTicks(int32_t newTicks) { ticks = newTicks; endTime = ticks + OTSYS_TIME(); }
bool Condition::updateCondition(const Condition* addCondition) { return conditionType == addCondition->getType() && (ticks != -1 || addCondition->getTicks() < 1) && (addCondition->getTicks() < 0 || endTime <= (OTSYS_TIME() + addCondition->getTicks())); }
void OutputMessagePool::startExecutionFrame() { //std::lock_guard<std::recursive_mutex> lockClass(m_outputPoolLock); m_frameTime = OTSYS_TIME(); m_isOpen = true; }