bool Manager::allow(uint32_t ip) const { if(!g_config.getBool(ConfigManager::MANAGER_LOCALHOST_ONLY)) return !ConnectionManager::getInstance()->isDisabled(ip, 0xFE); if(ip == 0x0100007F) //127.0.0.1 return true; if(g_config.getBool(ConfigManager::MANAGER_LOGS)) LOG_MESSAGE(LOGTYPE_EVENT, "forbidden connection try", "MANAGER " + convertIPAddress(ip)); return false; }
void Monster::onCreatureLeave(Creature* creature) { #ifdef __DEBUG__ std::clog << "onCreatureLeave - " << creature->getName() << std::endl; #endif if(isSummon() && master == creature) { if(!g_config.getBool(ConfigManager::TELEPORT_SUMMONS) && (!master->getPlayer() || !g_config.getBool(ConfigManager::TELEPORT_PLAYER_SUMMONS))) { //Turn the monster off until its master comes back isMasterInRange = false; updateIdleStatus(); } else if(!doTeleportToMaster()) teleportToMaster = true; } //update friendList if(isFriend(creature)) { CreatureList::iterator it = std::find(friendList.begin(), friendList.end(), creature); if(it != friendList.end()) { (*it)->unRef(); friendList.erase(it); } #ifdef __DEBUG__ else std::clog << "Monster: " << creature->getName() << " not found in the friendList." << std::endl; #endif } //update targetList if(isOpponent(creature)) { CreatureList::iterator it = std::find(targetList.begin(), targetList.end(), creature); if(it != targetList.end()) { (*it)->unRef(); targetList.erase(it); if(targetList.empty()) updateIdleStatus(); } #ifdef __DEBUG__ else std::clog << "Player: " << creature->getName() << " not found in the targetList." << std::endl; #endif } }
void ServicePort::open(uint16_t port) { m_serverPort = port; m_pendingStart = false; try { if(g_config.getBool(ConfigManager::BIND_IP_ONLY)) m_acceptor = new boost::asio::ip::tcp::acceptor(m_io_service, boost::asio::ip::tcp::endpoint( boost::asio::ip::address(boost::asio::ip::address_v4::from_string( g_config.getString(ConfigManager::IP))), m_serverPort)); else m_acceptor = new boost::asio::ip::tcp::acceptor(m_io_service, boost::asio::ip::tcp::endpoint( boost::asio::ip::address(boost::asio::ip::address_v4(INADDR_ANY)), m_serverPort)); accept(); } catch(boost::system::system_error& e) { if(m_logError) { LOG_MESSAGE(LOGTYPE_ERROR, e.what(), "NETWORK") m_logError = false; } m_pendingStart = true; Scheduler::getInstance().addEvent(createSchedulerTask(5000, boost::bind( &ServicePort::onOpen, boost::weak_ptr<ServicePort>(shared_from_this()), m_serverPort))); } }
bool IOMapSerialize::saveMap(Map* map) { if(g_config.getBool(ConfigManager::HOUSE_STORAGE)) return saveMapBinary(map); return saveMapRelational(map); }
void House::updateDoorDescription() { std::stringstream houseDescription; houseDescription << "It belongs to house '" << houseName << "'. " << std::endl; if(houseOwner != 0){ houseDescription << houseOwnerName; } else{ houseDescription << "Nobody"; } houseDescription << " owns this house." << std::endl; if(getHouseOwner() == 0 && g_config.getBool(ConfigManager::SHOW_HOUSE_PRICE)) { int price = 0; for(HouseTileList::iterator it = getHouseTileBegin(); it != getHouseTileEnd(); it++) { price += g_config.getNumber(ConfigManager::HOUSE_PRICE); } houseDescription << " This house costs " << price << " gold." << std::endl; } HouseDoorList::iterator it; for(it = doorList.begin(); it != doorList.end(); ++it){ (*it)->setSpecialDescription(houseDescription.str()); } }
bool WaitingList::login(const Player* player) { uint32_t online = g_game.getPlayersOnline(), max = g_config.getNumber(ConfigManager::MAX_PLAYERS); if(player->hasFlag(PlayerFlag_CanAlwaysLogin) || player->isAccountManager() || (waitList.empty() && online < max) || (g_config.getBool(ConfigManager::PREMIUM_SKIP_WAIT) && player->isPremium())) return true; cleanup(); uint32_t slot = 0; WaitList::iterator it = find(player, slot); if(it != waitList.end()) { if((online + slot) > max) { //let them wait a bit longer (*it)->timeout = OTSYS_TIME() + getTimeout(slot) * 1000; return false; } //should be able to login now delete *it; waitList.erase(it); return true; } Wait* wait = new Wait(); if(player->isPremium()) { slot = 1; WaitList::iterator it = waitList.end(); for(WaitList::iterator wit = waitList.begin(); wit != it; ++wit) { if(!(*wit)->premium) { it = wit; break; } ++slot; } waitList.insert(it, wait); } else { waitList.push_back(wait); slot = waitList.size(); } wait->name = player->getName(); wait->ip = player->getIP(); wait->premium = player->isPremium(); wait->timeout = OTSYS_TIME() + getTimeout(slot) * 1000; return false; }
void Creature::dropCorpse(DeathList deathList) { if(master && !g_config.getBool(ConfigManager::SUMMONS_DROP_CORPSE)) { g_game.addMagicEffect(getPosition(), MAGIC_EFFECT_POFF); return; } Item* corpse = createCorpse(deathList); if(corpse) corpse->setParent(VirtualCylinder::virtualCylinder); bool deny = false; CreatureEventList deathEvents = getCreatureEvents(CREATURE_EVENT_DEATH); for(CreatureEventList::iterator it = deathEvents.begin(); it != deathEvents.end(); ++it) { if(!(*it)->executeDeath(this, corpse, deathList) && !deny) deny = true; } if(!corpse) return; corpse->setParent(NULL); if(deny) return; Tile* tile = getTile(); if(!tile) return; Item* splash = NULL; switch(getRace()) { case RACE_VENOM: splash = Item::CreateItem(ITEM_FULLSPLASH, FLUID_GREEN); break; case RACE_BLOOD: splash = Item::CreateItem(ITEM_FULLSPLASH, FLUID_BLOOD); break; default: break; } if(splash) { g_game.internalAddItem(NULL, tile, splash, INDEX_WHEREEVER, FLAG_NOLIMIT); g_game.startDecay(splash); } g_game.internalAddItem(NULL, tile, corpse, INDEX_WHEREEVER, FLAG_NOLIMIT); dropLoot(corpse->getContainer()); g_game.startDecay(corpse); }
void Monster::onAttackedCreatureDisappear(bool) { #ifdef __DEBUG__ std::clog << "Attacked creature disappeared." << std::endl; #endif attackTicks = 0; extraMeleeAttack = true; if(g_config.getBool(ConfigManager::MONSTER_SPAWN_WALKBACK)) g_game.internalTeleport(this, getMasterPosition(), false); }
void ProtocolManager::addLogLine(LogType_t type, std::string message) { if(!g_config.getBool(ConfigManager::MANAGER_LOGS)) return; std::string tmp = "MANAGER"; if(getIP()) tmp += " " + convertIPAddress(getIP()); LOG_MESSAGE(type, message, tmp) }
uint16_t Admin::getPolicy() const { uint16_t policy = 0; if(g_config.getBool(ConfigManager::ADMIN_REQUIRE_LOGIN)) policy |= REQUIRE_LOGIN; if(m_encrypted) policy |= REQUIRE_ENCRYPTION; return policy; }
bool Houses::reloadPrices() { if(g_config.getBool(ConfigManager::HOUSE_RENTASPRICE)) return true; const uint32_t tilePrice = g_config.getNumber(ConfigManager::HOUSE_PRICE); for(HouseMap::iterator it = houseMap.begin(); it != houseMap.end(); ++it) it->second->setPrice(tilePrice * it->second->getTilesCount(), true); return true; }
DatabaseMySQL::DatabaseMySQL() : m_timeoutTask(0) { m_connected = false; if(!mysql_init(&m_handle)) { std::clog << std::endl << "Failed to initialize MySQL connection handler." << std::endl; return; } uint32_t timeout = g_config.getNumber(ConfigManager::MYSQL_READ_TIMEOUT); if(timeout) mysql_options(&m_handle, MYSQL_OPT_READ_TIMEOUT, (const char*)&timeout); timeout = g_config.getNumber(ConfigManager::MYSQL_WRITE_TIMEOUT); if(timeout) mysql_options(&m_handle, MYSQL_OPT_WRITE_TIMEOUT, (const char*)&timeout); my_bool reconnect = true; mysql_options(&m_handle, MYSQL_OPT_RECONNECT, &reconnect); if(!mysql_real_connect(&m_handle, g_config.getString(ConfigManager::SQL_HOST).c_str(), g_config.getString( ConfigManager::SQL_USER).c_str(), g_config.getString(ConfigManager::SQL_PASS).c_str(), g_config.getString( ConfigManager::SQL_DB).c_str(), g_config.getNumber(ConfigManager::SQL_PORT), NULL, 0)) { std::clog << "Failed connecting to database - MYSQL ERROR: " << mysql_error(&m_handle) << " (" << mysql_errno(&m_handle) << ")" << std::endl; return; } m_connected = true; if(mysql_get_client_version() <= 50019) //MySQL servers <= 5.0.19 have a bug where MYSQL_OPT_RECONNECT option is reset by mysql_real_connect calls. //Read this http://dev.mysql.com/doc/refman/5.0/en/mysql-options.html for more information. std::clog << std::endl << "> WARNING: Outdated MySQL server detected, consider upgrading to a newer version." << std::endl; timeout = g_config.getNumber(ConfigManager::SQL_KEEPALIVE) * 1000; if(timeout) m_timeoutTask = Scheduler::getInstance().addEvent(createSchedulerTask(timeout, boost::bind(&DatabaseMySQL::keepAlive, this))); if(!g_config.getBool(ConfigManager::HOUSE_STORAGE)) return; //we cannot lock mutex here :) DBResult* result = storeQuery("SHOW variables LIKE 'max_allowed_packet';"); if(!result) return; if(result->getDataLong("Value") < 16776192) std::clog << std::endl << "> WARNING: max_allowed_packet might be set too low for binary map storage." << std::endl << "Use the following query to raise max_allow_packet: SET GLOBAL max_allowed_packet = 16776192;" << std::endl; result->free(); }
bool Houses::payRent(Player* player, House* house, uint32_t bid, time_t _time/* = 0*/) { if(rentPeriod == RENTPERIOD_NEVER || !house->getOwner() || house->getPaidUntil() > _time || !house->getRent() || player->hasCustomFlag(PlayerCustomFlag_IgnoreHouseRent)) return true; Town* town = Towns::getInstance()->getTown(house->getTownId()); if(!town) return false; bool paid = false; uint32_t amount = house->getRent() + bid; if(g_config.getBool(ConfigManager::BANK_SYSTEM) && player->balance >= amount) { player->balance -= amount; paid = true; } else if(DepotChest* depotChest = player->getDepotChest(town->getID(), true)) paid = g_game.removeMoney(depotChest, amount, FLAG_NOLIMIT); if(!paid) return false; if(!_time) _time = time(NULL); uint32_t paidUntil = _time; switch(rentPeriod) { case RENTPERIOD_DAILY: paidUntil += 86400; break; case RENTPERIOD_WEEKLY: paidUntil += 7 * 86400; break; case RENTPERIOD_MONTHLY: paidUntil += 30 * 86400; break; case RENTPERIOD_YEARLY: paidUntil += 365 * 86400; break; default: break; } house->setLastWarning(0); house->setRentWarnings(0); house->setPaidUntil(paidUntil); return true; }
bool Combat::isProtected(Player* attacker, Player* target) { if(attacker->hasFlag(PlayerFlag_CannotAttackPlayer)) return true; if(attacker->hasCustomFlag(PlayerCustomFlag_GamemasterPrivileges)) return false; if(attacker->getZone() == ZONE_HARDCORE && target->getZone() == ZONE_HARDCORE && g_config.getBool(ConfigManager::PVP_TILE_IGNORE_PROTECTION)) return false; return target->isProtected() || attacker->isProtected() || (attacker->checkLoginDelay() && !attacker->hasBeenAttacked(target->getID())); }
void Combat::doCombatDispel(Creature* caster, Creature* target, const CombatParams& params, bool check/* = true*/) { if(check && params.isAggressive && (caster == target || Combat::canDoCombat(caster, target, true) != RET_NOERROR)) return; CombatDispelFunc(caster, target, params, NULL); if(params.targetCallback) params.targetCallback->onTargetCombat(caster, target); if(params.effects.impact != MAGIC_EFFECT_NONE && (!caster || !caster->isGhost() || g_config.getBool(ConfigManager::GHOST_SPELL_EFFECTS))) g_game.addMagicEffect(target->getPosition(), params.effects.impact); if(caster && params.effects.distance != SHOOT_EFFECT_NONE) addDistanceEffect(caster, caster->getPosition(), target->getPosition(), params.effects.distance); }
bool Creature::hasCondition(ConditionType_t type, int32_t subId/* = 0*/, bool checkTime/* = true*/) const { if(isSuppress(type)) return false; for(ConditionList::const_iterator it = conditions.begin(); it != conditions.end(); ++it) { if((*it)->getType() != type || (subId != -1 && (*it)->getSubId() != (uint32_t)subId)) continue; if(!checkTime || g_config.getBool(ConfigManager::OLD_CONDITION_ACCURACY) || !(*it)->getEndTime() || (*it)->getEndTime() >= OTSYS_TIME()) return true; } return false; }
bool BedItem::canUse(Player* player) { if(!house || !player || player->isRemoved() || (!player->isPremium() && g_config.getBool( ConfigManager::BED_REQUIRE_PREMIUM)) || player->hasCondition(CONDITION_INFIGHT)) return false; if(!sleeper || house->getHouseAccessLevel(player) == HOUSE_OWNER) return isBed(); Player* _player = g_game.getPlayerByGuidEx(sleeper); if(!_player) return isBed(); bool ret = house->getHouseAccessLevel(_player) <= house->getHouseAccessLevel(player); if(_player->isVirtual()) delete _player; return ret; }
void Combat::doCombatDefault(Creature* caster, Creature* target, const CombatParams& params) { if(params.isAggressive && (caster == target || Combat::canDoCombat(caster, target, true) != RET_NOERROR)) return; const SpectatorVec& list = g_game.getSpectators(target->getTile()->getPosition()); CombatNullFunc(caster, target, params, NULL); combatTileEffects(list, caster, target->getTile(), params); if(params.targetCallback) params.targetCallback->onTargetCombat(caster, target); if(params.effects.impact != MAGIC_EFFECT_NONE && (!caster || !caster->isGhost() || g_config.getBool(ConfigManager::GHOST_SPELL_EFFECTS))) g_game.addMagicEffect(target->getPosition(), params.effects.impact); if(caster && params.effects.distance != SHOOT_EFFECT_NONE) addDistanceEffect(caster, caster->getPosition(), target->getPosition(), params.effects.distance); }
bool Connection::send(OutputMessage_ptr msg) { #ifdef __DEBUG_NET_DETAIL__ std::clog << "Connection::send init" << std::endl; #endif m_connectionLock.lock(); if(m_connectionState != CONNECTION_STATE_OPEN || m_writeError) { m_connectionLock.unlock(); return false; } TRACK_MESSAGE(msg); if(!m_pendingWrite) { if(msg->getProtocol()) msg->getProtocol()->onSendMessage(msg); #ifdef __DEBUG_NET_DETAIL__ std::clog << "Connection::send " << msg->size() << std::endl; #endif internalSend(msg); } else if(m_pendingWrite > 100 && g_config.getBool(ConfigManager::FORCE_CLOSE_SLOW_CONNECTION)) { std::clog << "NOTICE: Forcing slow connection to disconnect!" << std::endl; close(); } else { #ifdef __DEBUG_NET__ std::clog << "Connection::send Adding to queue " << msg->size() << std::endl; #endif OutputMessagePool::getInstance()->autoSend(msg); } m_connectionLock.unlock(); return true; }
bool IOMapSerialize::loadMap(Map* map) { bool result = false; if(g_config.getBool(ConfigManager::HOUSE_STORAGE)) result = loadMapBinary(map); else result = loadMapRelational(map); if(!result) return false; for(HouseMap::iterator it = Houses::getInstance()->getHouseBegin(); it != Houses::getInstance()->getHouseEnd(); ++it) { if(!it->second->hasSyncFlag(House::HOUSE_SYNC_UPDATE)) continue; it->second->resetSyncFlag(House::HOUSE_SYNC_UPDATE); it->second->updateDoorDescription(); } return true; }
void IOGuild::checkWars() { if(!g_config.getBool(ConfigManager::EXTERNAL_GUILD_WARS_MANAGEMENT)) return; Database* db = Database::getInstance(); DBResult* result; DBQuery query; // I don't know if there any easier way to make it right. // If exists other solution just let me know. // NOTE: // status states 6,7,8,9 are additional only for external management, do not anything in talkaction, those states make possible to manage wars for example from webpage // status 6 means accepted invite, it's before proper start of war // status 7 means 'mend fences', related to signed an armistice declaration by enemy // status 8 means ended up, when guild ended up war without signed an armistice declaration by enemy // status 9 means signed an armistice declaration by enemy std::stringstream s; uint32_t tmpInterval = (uint32_t) (EVENT_WARSINTERVAL/1000)+10; //+10 for sure query << "SELECT `g`.`name` as `guild_name`, `e`.`name` as `enemy_name`, `guild_wars`.`frags` as `frags` FROM `guild_wars` LEFT JOIN `guilds` as `g` ON `guild_wars`.`guild_id` = `g`.`id` LEFT JOIN `guilds` as `e` ON `guild_wars`.`enemy_id` = `e`.`id` WHERE (`begin` > 0 AND (`begin` + " << tmpInterval << ") > UNIX_TIMESTAMP()) AND `status` IN (0, 6)"; if((result = db->storeQuery(query.str()))) { do { s << result->getDataString("guild_name") << " has invited " << result->getDataString("enemy_name") << " to war till " << result->getDataInt("frags") << " frags."; g_game.broadcastMessage(s.str().c_str(), MSG_EVENT_ADVANCE); s.str(""); } while(result->next()); result->free(); } query.str(""); query << "UPDATE `guild_wars` SET `begin` = UNIX_TIMESTAMP(), `end` = ((`end` - `begin`) + UNIX_TIMESTAMP()), `status` = 1 WHERE `status` = 6"; db->query(query.str()); query.str(""); query << "SELECT `g`.`name` as `guild_name`, `e`.`name` as `enemy_name`, `g`.`id` as `guild_id`, `e`.`id` as `enemy_id`, `guild_wars`.* FROM `guild_wars` LEFT JOIN `guilds` as `g` ON `guild_wars`.`guild_id` = `g`.`id` LEFT JOIN `guilds` as `e` ON `guild_wars`.`enemy_id` = `e`.`id` WHERE (`begin` > 0 AND (`begin` + " << tmpInterval << ") > UNIX_TIMESTAMP()) AND `status` = 1"; if((result = db->storeQuery(query.str()))) { do { s << result->getDataString("enemy_name") << " accepted " << result->getDataString("guild_name") << " invitation to war."; g_game.broadcastMessage(s.str().c_str(), MSG_EVENT_ADVANCE); s.str(""); War_t tmp; tmp.war = result->getDataInt("id"); tmp.ids[WAR_GUILD] = result->getDataInt("guild_id"); tmp.ids[WAR_ENEMY] = result->getDataInt("enemy_id"); for(AutoList<Player>::iterator it = Player::autoList.begin(); it != Player::autoList.end(); ++it) { if(it->second->isRemoved()) continue; bool update = false; if(it->second->getGuildId() == tmp.ids[WAR_GUILD]) { tmp.type = WAR_ENEMY; it->second->addEnemy(tmp.ids[WAR_ENEMY], tmp); update = true; } else if(it->second->getGuildId() == tmp.ids[WAR_ENEMY]) { tmp.type = WAR_ENEMY; it->second->addEnemy(tmp.ids[WAR_GUILD], tmp); update = true; } if(update) g_game.updateCreatureEmblem(it->second); } } while(result->next()); result->free(); } query.str(""); query << "SELECT `g`.`name` as `guild_name`, `e`.`name` as `enemy_name` FROM `guild_wars` LEFT JOIN `guilds` as `g` ON `guild_wars`.`guild_id` = `g`.`id` LEFT JOIN `guilds` as `e` ON `guild_wars`.`enemy_id` = `e`.`id` WHERE (`end` > 0 AND (`end` + " << tmpInterval << ") > UNIX_TIMESTAMP()) AND `status` = 2"; if((result = db->storeQuery(query.str()))) { do { s << result->getDataString("enemy_name") << " rejected " << result->getDataString("guild_name") << " invitation to war."; g_game.broadcastMessage(s.str().c_str(), MSG_EVENT_ADVANCE); s.str(""); } while(result->next()); result->free(); } query.str(""); query << "SELECT `g`.`name` as `guild_name`, `e`.`name` as `enemy_name` FROM `guild_wars` LEFT JOIN `guilds` as `g` ON `guild_wars`.`guild_id` = `g`.`id` LEFT JOIN `guilds` as `e` ON `guild_wars`.`enemy_id` = `e`.`id` WHERE (`end` > 0 AND (`end` + " << tmpInterval << ") > UNIX_TIMESTAMP()) AND `status` = 3"; if((result = db->storeQuery(query.str()))) { do { s << result->getDataString("guild_name") << " canceled invitation to a war with " << result->getDataString("enemy_name") << "."; g_game.broadcastMessage(s.str().c_str(), MSG_EVENT_ADVANCE); s.str(""); } while(result->next()); result->free(); } query.str(""); query << "SELECT `g`.`name` as `guild_name`, `e`.`name` as `enemy_name`, `guild_wars`.`status` as `status`, `g`.`id` as `guild_id`, `e`.`id` as `enemy_id`, `guild_wars`.* FROM `guild_wars` LEFT JOIN `guilds` as `g` ON `guild_wars`.`guild_id` = `g`.`id` LEFT JOIN `guilds` as `e` ON `guild_wars`.`enemy_id` = `e`.`id` WHERE (`end` > 0 AND (`end` + " << tmpInterval << ") > UNIX_TIMESTAMP()) AND `status` IN (7,8)"; if((result = db->storeQuery(query.str()))) { do { if(result->getDataInt("status") == 7) s << result->getDataString("guild_name") << " has mend fences with " << result->getDataString("enemy_name") << "."; else s << result->getDataString("guild_name") << " has ended up a war with " << result->getDataString("enemy_name") << "."; War_t tmp; tmp.war = result->getDataInt("id"); tmp.ids[WAR_GUILD] = result->getDataInt("guild_id"); tmp.ids[WAR_ENEMY] = result->getDataInt("enemy_id"); for(AutoList<Player>::iterator it = Player::autoList.begin(); it != Player::autoList.end(); ++it) { if(it->second->isRemoved()) continue; bool update = false; if(it->second->getGuildId() == tmp.ids[WAR_GUILD]) { it->second->removeEnemy(tmp.ids[WAR_ENEMY]); update = true; } else if(it->second->getGuildId() == tmp.ids[WAR_ENEMY]) { it->second->removeEnemy(tmp.ids[WAR_GUILD]); update = true; } if(update) g_game.updateCreatureEmblem(it->second); } g_game.broadcastMessage(s.str().c_str(), MSG_EVENT_ADVANCE); s.str(""); } while(result->next()); result->free(); } query.str(""); query << "UPDATE `guild_wars` SET `end` = UNIX_TIMESTAMP(), `status` = 5 WHERE `status` IN (7,8)"; db->query(query.str()); query.str(""); }
bool Houses::payHouse(House* house, time_t _time, uint32_t bid) { if(rentPeriod == RENTPERIOD_NEVER || !house->getOwner() || house->getPaidUntil() > _time || !house->getRent()) return true; Town* town = Towns::getInstance()->getTown(house->getTownId()); if(!town) return false; uint32_t owner = house->getOwner(); if(house->isGuild() && !IOGuild::getInstance()->swapGuildIdToOwner(owner)) { house->setOwnerEx(0, true); return false; } std::string name; if(!IOLoginData::getInstance()->getNameByGuid(owner, name)) { house->setOwnerEx(0, true); return false; } Player* player = g_game.getPlayerByNameEx(name); if(!player) return false; if(!player->isPremium() && g_config.getBool(ConfigManager::HOUSE_NEED_PREMIUM)) { house->setOwnerEx(0, true); if(player->isVirtual()) delete player; return false; } int32_t loginClean = g_config.getNumber(ConfigManager::HOUSE_CLEAN_OLD); if(loginClean && _time >= (player->getLastLogin() + loginClean)) { house->setOwnerEx(0, true); if(player->isVirtual()) delete player; return false; } if(payRent(player, house, bid, _time) || _time < (house->getLastWarning() + 86400)) { if(player->isVirtual()) { IOLoginData::getInstance()->savePlayer(player); delete player; } return true; } uint32_t warningsLimit = 7; switch(rentPeriod) { case RENTPERIOD_DAILY: warningsLimit = 1; break; case RENTPERIOD_WEEKLY: warningsLimit = 3; break; case RENTPERIOD_YEARLY: warningsLimit = 14; break; default: break; } uint32_t warnings = house->getRentWarnings(); if(warnings >= warningsLimit) { house->setOwnerEx(0, true); if(player->isVirtual()) delete player; return false; } if(Item* letter = Item::CreateItem(ITEM_LETTER_STAMPED)) { if(g_game.internalAddItem(NULL, player->getInbox(), letter, INDEX_WHEREEVER, FLAG_NOLIMIT) == RET_NOERROR) { letter->setWriter(g_config.getString(ConfigManager::SERVER_NAME)); letter->setDate(std::time(NULL)); std::stringstream s; s << "Warning!\nThe "; switch(rentPeriod) { case RENTPERIOD_DAILY: s << "daily"; break; case RENTPERIOD_WEEKLY: s << "weekly"; break; case RENTPERIOD_MONTHLY: s << "monthly"; break; case RENTPERIOD_YEARLY: s << "annual"; break; default: break; } s << " rent of " << house->getRent() << " gold for your " << (house->isGuild() ? "guild hall" : "house") << " \"" << house->getName() << "\" has to be paid. Have it within " << (warningsLimit - warnings) << " days or you will lose your " << (house->isGuild() ? "guild hall" : "house") << "."; letter->setText(s.str().c_str()); if(player->isVirtual()) IOLoginData::getInstance()->savePlayer(player); } else g_game.freeThing(letter); } house->setLastWarning(_time); house->setRentWarnings(++warnings); if(player->isVirtual()) delete player; return false; }
bool Chat::talkToChannel(Player* player, MessageClasses type, const std::string& text, uint16_t channelId) { if(text.empty()) return false; ChatChannel* channel = getChannel(player, channelId); if(!channel) return false; if(!player->hasFlag(PlayerFlag_CannotBeMuted)) { if(!channel->hasFlag(CHANNELFLAG_ACTIVE)) { player->sendTextMessage(MSG_STATUS_SMALL, "You may not speak into this channel."); return true; } if(player->getLevel() < channel->getLevel()) { char buffer[100]; sprintf(buffer, "You may not speak into this channel as long as you are on level %d.", channel->getLevel()); player->sendCancel(buffer); return true; } if(channel->getConditionId() >= 0 && player->hasCondition(CONDITION_MUTED, channel->getConditionId())) { player->sendCancel(channel->getConditionMessage().c_str()); return true; } } if(isPublicChannel(channelId)) Manager::getInstance()->talk(player->getID(), channelId, type, text); if(channelId != CHANNEL_GUILD || !g_config.getBool(ConfigManager::INGAME_GUILD_MANAGEMENT) || (text[0] != '!' && text[0] != '/')) { if(channelId == CHANNEL_GUILD) { switch(player->getGuildLevel()) { case GUILDLEVEL_VICE: return channel->talk(player, MSG_CHANNEL_HIGHLIGHT, text); // SPEAK_CHANNEL_O case GUILDLEVEL_LEADER: return channel->talk(player, MSG_GAMEMASTER_CHANNEL, text); // SPEAK_CHANNEL_RN default: break; } } return channel->talk(player, type, text); } if(!player->getGuildId()) { player->sendCancel("You are not in a guild."); return true; } if(!IOGuild::getInstance()->guildExists(player->getGuildId())) { player->sendCancel("It seems like your guild does not exist anymore."); return true; } char buffer[350]; if(text.substr(1) == "disband") { if(player->getGuildLevel() == GUILDLEVEL_LEADER) { IOGuild::getInstance()->disbandGuild(player->getGuildId()); channel->talk(player, MSG_CHANNEL, "The guild has been disbanded."); } else player->sendCancel("You are not the leader of your guild."); } else if(text.substr(1, 6) == "invite") { if(player->getGuildLevel() > GUILDLEVEL_MEMBER) { if(text.length() > 7) { std::string param = text.substr(8); trimString(param); Player* paramPlayer = NULL; if(g_game.getPlayerByNameWildcard(param, paramPlayer) == RET_NOERROR) { if(paramPlayer->getGuildId() == 0) { if(!paramPlayer->isGuildInvited(player->getGuildId())) { sprintf(buffer, "%s has invited you to join the guild, %s. You may join this guild by writing: !joinguild %s", player->getName().c_str(), player->getGuildName().c_str(), player->getGuildName().c_str()); paramPlayer->sendTextMessage(MSG_INFO_DESCR, buffer); sprintf(buffer, "%s has invited %s to the guild.", player->getName().c_str(), paramPlayer->getName().c_str()); channel->talk(player, MSG_CHANNEL, buffer); paramPlayer->invitationsList.push_back(player->getGuildId()); } else player->sendCancel("A player with that name has already been invited to your guild."); } else player->sendCancel("A player with that name is already in a guild."); } else if(IOLoginData::getInstance()->playerExists(param)) { uint32_t guid; IOLoginData::getInstance()->getGuidByName(guid, param); if(!IOGuild::getInstance()->hasGuild(guid)) { if(!IOGuild::getInstance()->isInvited(player->getGuildId(), guid)) { if(IOGuild::getInstance()->guildExists(player->getGuildId())) { IOGuild::getInstance()->invitePlayer(player->getGuildId(), guid); sprintf(buffer, "%s has invited %s to the guild.", player->getName().c_str(), param.c_str()); channel->talk(player, MSG_CHANNEL, buffer); } else player->sendCancel("Your guild does not exist anymore."); } else player->sendCancel("A player with that name has already been invited to your guild."); } else player->sendCancel("A player with that name is already in a guild."); } else player->sendCancel("A player with that name does not exist."); } else player->sendCancel("Invalid guildcommand parameters."); } else player->sendCancel("You don't have rights to invite players to your guild."); } else if(text.substr(1, 5) == "leave") { if(player->getGuildLevel() < GUILDLEVEL_LEADER) { #ifdef __WAR_SYSTEM__ if(!player->hasEnemy()) { #endif sprintf(buffer, "%s has left the guild.", player->getName().c_str()); channel->talk(player, MSG_CHANNEL, buffer); player->leaveGuild(); #ifdef __WAR_SYSTEM__ } else player->sendCancel("Your guild is currently at war, you cannot leave it right now."); #endif } else player->sendCancel("You cannot leave your guild because you are the leader of it, you have to pass the leadership to another member of your guild or disband the guild."); } else if(text.substr(1, 6) == "revoke") { if(player->getGuildLevel() > GUILDLEVEL_MEMBER) { if(text.length() > 7) { std::string param = text.substr(8); trimString(param); Player* paramPlayer = NULL; if(g_game.getPlayerByNameWildcard(param, paramPlayer) == RET_NOERROR) { if(paramPlayer->getGuildId() == 0) { InvitationsList::iterator it = std::find(paramPlayer->invitationsList.begin(), paramPlayer->invitationsList.end(), player->getGuildId()); if(it != paramPlayer->invitationsList.end()) { sprintf(buffer, "%s has revoked your invite to %s guild.", player->getName().c_str(), (player->getSex(false) ? "his" : "her")); paramPlayer->sendTextMessage(MSG_INFO_DESCR, buffer); sprintf(buffer, "%s has revoked the guildinvite of %s.", player->getName().c_str(), paramPlayer->getName().c_str()); channel->talk(player, MSG_CHANNEL, buffer); paramPlayer->invitationsList.erase(it); return true; } else player->sendCancel("A player with that name is not invited to your guild."); } else player->sendCancel("A player with that name is already in a guild."); } else if(IOLoginData::getInstance()->playerExists(param)) { uint32_t guid; IOLoginData::getInstance()->getGuidByName(guid, param); if(IOGuild::getInstance()->isInvited(player->getGuildId(), guid)) { if(IOGuild::getInstance()->guildExists(player->getGuildId())) { sprintf(buffer, "%s has revoked the guildinvite of %s.", player->getName().c_str(), param.c_str()); channel->talk(player, MSG_CHANNEL, buffer); IOGuild::getInstance()->revokeInvite(player->getGuildId(), guid); } else player->sendCancel("It seems like your guild does not exist anymore."); } else player->sendCancel("A player with that name is not invited to your guild."); } else player->sendCancel("A player with that name does not exist."); } else player->sendCancel("Invalid guildcommand parameters."); } else player->sendCancel("You don't have rights to revoke an invite of someone in your guild."); } else if(text.substr(1, 7) == "promote" || text.substr(1, 6) == "demote" || text.substr(1, 14) == "passleadership" || text.substr(1, 4) == "kick") { if(player->getGuildLevel() == GUILDLEVEL_LEADER) { std::string param; uint32_t length = 0; if(text[2] == 'r') length = 9; else if(text[2] == 'e') length = 7; else if(text[2] == 'a') length = 16; else length = 6; if(text.length() < length) { player->sendCancel("Invalid guildcommand parameters."); return true; } param = text.substr(length); trimString(param); Player* paramPlayer = NULL; if(g_game.getPlayerByNameWildcard(param, paramPlayer) == RET_NOERROR) { if(paramPlayer->getGuildId()) { if(IOGuild::getInstance()->guildExists(paramPlayer->getGuildId())) { if(player->getGuildId() == paramPlayer->getGuildId()) { if(text[2] == 'r') { if(paramPlayer->getGuildLevel() == GUILDLEVEL_MEMBER) { if(paramPlayer->isPremium()) { paramPlayer->setGuildLevel(GUILDLEVEL_VICE); sprintf(buffer, "%s has promoted %s to %s.", player->getName().c_str(), paramPlayer->getName().c_str(), paramPlayer->getRankName().c_str()); channel->talk(player, MSG_CHANNEL, buffer); } else player->sendCancel("A player with that name does not have a premium account."); } else player->sendCancel("You can only promote Members to Vice-Leaders."); } else if(text[2] == 'e') { if(paramPlayer->getGuildLevel() == GUILDLEVEL_VICE) { paramPlayer->setGuildLevel(GUILDLEVEL_MEMBER); sprintf(buffer, "%s has demoted %s to %s.", player->getName().c_str(), paramPlayer->getName().c_str(), paramPlayer->getRankName().c_str()); channel->talk(player, MSG_CHANNEL, buffer); } else player->sendCancel("You can only demote Vice-Leaders to Members."); } else if(text[2] == 'a') { if(paramPlayer->getGuildLevel() == GUILDLEVEL_VICE) { const uint32_t levelToFormGuild = g_config.getNumber(ConfigManager::LEVEL_TO_FORM_GUILD); if(paramPlayer->getLevel() >= levelToFormGuild) { paramPlayer->setGuildLevel(GUILDLEVEL_LEADER); player->setGuildLevel(GUILDLEVEL_VICE); IOGuild::getInstance()->updateOwnerId(paramPlayer->getGuildId(), paramPlayer->getGUID()); sprintf(buffer, "%s has passed the guild leadership to %s.", player->getName().c_str(), paramPlayer->getName().c_str()); channel->talk(player, MSG_CHANNEL, buffer); } else { sprintf(buffer, "The new guild leader has to be at least Level %d.", levelToFormGuild); player->sendCancel(buffer); } } else player->sendCancel("A player with that name is not a Vice-Leader."); } else { if(player->getGuildLevel() > paramPlayer->getGuildLevel()) { #ifdef __WAR_SYSTEM__ if(!player->hasEnemy()) { #endif sprintf(buffer, "%s has been kicked from the guild by %s.", paramPlayer->getName().c_str(), player->getName().c_str()); channel->talk(player, MSG_CHANNEL, buffer); paramPlayer->leaveGuild(); #ifdef __WAR_SYSTEM__ } else player->sendCancel("Your guild is currently at war, you cannot kick right now."); #endif } else player->sendCancel("You may only kick players with a guild rank below your."); } } else player->sendCancel("You are not in the same guild as a player with that name."); } else player->sendCancel("Could not find the guild of a player with that name."); } else player->sendCancel("A player with that name is not in a guild."); } else if(IOLoginData::getInstance()->playerExists(param)) { uint32_t guid; IOLoginData::getInstance()->getGuidByName(guid, param); if(IOGuild::getInstance()->hasGuild(guid)) { if(player->getGuildId() == IOGuild::getInstance()->getGuildId(guid)) { if(text[2] == 'r') { if(IOGuild::getInstance()->getGuildLevel(guid) == GUILDLEVEL_MEMBER) { if(IOLoginData::getInstance()->isPremium(guid)) { IOGuild::getInstance()->setGuildLevel(guid, GUILDLEVEL_VICE); sprintf(buffer, "%s has promoted %s to %s.", player->getName().c_str(), param.c_str(), IOGuild::getInstance()->getRank(guid).c_str()); channel->talk(player, MSG_CHANNEL, buffer); } else player->sendCancel("A player with that name does not have a premium account."); } else player->sendCancel("You can only promote Members to Vice-Leaders."); } else if(text[2] == 'e') { if(IOGuild::getInstance()->getGuildLevel(guid) == GUILDLEVEL_VICE) { IOGuild::getInstance()->setGuildLevel(guid, GUILDLEVEL_MEMBER); sprintf(buffer, "%s has demoted %s to %s.", player->getName().c_str(), param.c_str(), IOGuild::getInstance()->getRank(guid).c_str()); channel->talk(player, MSG_CHANNEL, buffer); } else player->sendCancel("You can only demote Vice-Leaders to Members."); } else if(text[2] == 'a') { if(IOGuild::getInstance()->getGuildLevel(guid) == GUILDLEVEL_VICE) { const uint32_t levelToFormGuild = g_config.getNumber(ConfigManager::LEVEL_TO_FORM_GUILD); if(IOLoginData::getInstance()->getLevel(guid) >= levelToFormGuild) { IOGuild::getInstance()->setGuildLevel(guid, GUILDLEVEL_LEADER); player->setGuildLevel(GUILDLEVEL_VICE); sprintf(buffer, "%s has passed the guild leadership to %s.", player->getName().c_str(), param.c_str()); channel->talk(player, MSG_CHANNEL, buffer); } else { sprintf(buffer, "The new guild leader has to be at least Level %d.", levelToFormGuild); player->sendCancel(buffer); } } else player->sendCancel("A player with that name is not a Vice-Leader."); } else { sprintf(buffer, "%s has been kicked from the guild by %s.", param.c_str(), player->getName().c_str()); channel->talk(player, MSG_CHANNEL, buffer); IOLoginData::getInstance()->resetGuildInformation(guid); } } } else player->sendCancel("A player with that name is not in a guild."); } else player->sendCancel("A player with that name does not exist."); } else player->sendCancel("You are not the leader of your guild."); } else if(text.substr(1, 4) == "nick" && text.length() > 5) { StringVec params = explodeString(text.substr(6), ","); if(params.size() >= 2) { std::string param1 = params[0], param2 = params[1]; trimString(param1); trimString(param2); Player* paramPlayer = NULL; if(g_game.getPlayerByNameWildcard(param1, paramPlayer) == RET_NOERROR) { if(paramPlayer->getGuildId()) { if(param2.length() > 2) { if(param2.length() < 21) { if(isValidName(param2, false)) { if(IOGuild::getInstance()->guildExists(paramPlayer->getGuildId())) { if(player->getGuildId() == paramPlayer->getGuildId()) { if(paramPlayer->getGuildLevel() < player->getGuildLevel() || (player == paramPlayer && player->getGuildLevel() > GUILDLEVEL_MEMBER)) { paramPlayer->setGuildNick(param2); if(player != paramPlayer) sprintf(buffer, "%s has set the guildnick of %s to \"%s\".", player->getName().c_str(), paramPlayer->getName().c_str(), param2.c_str()); else sprintf(buffer, "%s has set %s guildnick to \"%s\".", player->getName().c_str(), (player->getSex(false) ? "his" : "her"), param2.c_str()); channel->talk(player, MSG_CHANNEL, buffer); } else player->sendCancel("You may only change the guild nick of players that have a lower rank than you."); } else player->sendCancel("A player with that name is not in your guild."); } else player->sendCancel("A player with that name's guild could not be found."); } else player->sendCancel("That guildnick is not valid."); } else player->sendCancel("That guildnick is too long, please select a shorter one."); } else player->sendCancel("That guildnick is too short, please select a longer one."); } else player->sendCancel("A player with that name is not in a guild."); } else if(IOLoginData::getInstance()->playerExists(param1)) { uint32_t guid; IOLoginData::getInstance()->getGuidByName(guid, (std::string&)param1); if(IOGuild::getInstance()->hasGuild(guid)) { if(param2.length() > 2) { if(param2.length() < 21) { if(isValidName(param2, false)) { if(IOGuild::getInstance()->guildExists(guid)) { if(player->getGuildId() == IOGuild::getInstance()->getGuildId(guid)) { if(IOGuild::getInstance()->getGuildLevel(guid) < player->getGuildLevel()) { IOGuild::getInstance()->setGuildNick(guid, param2); sprintf(buffer, "%s has set the guildnick of %s to \"%s\".", player->getName().c_str(), param1.c_str(), param2.c_str()); channel->talk(player, MSG_CHANNEL, buffer); } else player->sendCancel("You may only change the guild nick of players that have a lower rank than you."); } else player->sendCancel("A player with that name is not in your guild."); } else player->sendCancel("A player with that name's guild could not be found."); } else player->sendCancel("That guildnick is not valid."); } else player->sendCancel("That guildnick is too long, please select a shorter one."); } else player->sendCancel("That guildnick is too short, please select a longer one."); } else player->sendCancel("A player with that name is not in any guild."); } else player->sendCancel("A player with that name does not exist."); } else player->sendCancel("Invalid guildcommand parameters."); } else if(text.substr(1, 11) == "setrankname" && text.length() > 12) { StringVec params = explodeString(text.substr(13), ","); if(params.size() >= 2) { std::string param1 = params[0], param2 = params[1]; trimString(param1); trimString(param2); if(player->getGuildLevel() == GUILDLEVEL_LEADER) { if(param2.length() > 2) { if(param2.length() < 21) { if(isValidName(param2, false)) { if(IOGuild::getInstance()->getRankIdByName(player->getGuildId(), param1)) { if(!IOGuild::getInstance()->getRankIdByName(player->getGuildId(), param2)) { IOGuild::getInstance()->changeRank(player->getGuildId(), param1, param2); sprintf(buffer, "%s has renamed the guildrank: \"%s\", to: \"%s\".", player->getName().c_str(), param1.c_str(), param2.c_str()); channel->talk(player, MSG_CHANNEL, buffer); } else player->sendCancel("There is already a rank in your guild with that name."); } else player->sendCancel("There is no such rankname in your guild."); } else player->sendCancel("The new guildrank contains invalid characters."); } else player->sendCancel("The new rankname is too long."); } else player->sendCancel("The new rankname is too short."); } else player->sendCancel("You are not the leader of your guild."); } else player->sendCancel("Invalid guildcommand parameters"); } else if(text.substr(1, 7) == "setmotd") { if(player->getGuildLevel() == GUILDLEVEL_LEADER) { if(text.length() > 8) { std::string param = text.substr(9); trimString(param); if(param.length() > 2) { if(param.length() < 225) { IOGuild::getInstance()->setMotd(player->getGuildId(), param); sprintf(buffer, "%s has set the Message of the Day to: %s", player->getName().c_str(), param.c_str()); channel->talk(player, MSG_CHANNEL, buffer); } else player->sendCancel("That motd is too long."); } else player->sendCancel("That motd is too short."); } else player->sendCancel("Invalid guildcommand parameters."); } else player->sendCancel("Only the leader of your guild can set the guild motd."); } else if(text.substr(1, 9) == "cleanmotd") { if(player->getGuildLevel() == GUILDLEVEL_LEADER) { IOGuild::getInstance()->setMotd(player->getGuildId(), ""); sprintf(buffer, "%s has cleaned the Message of the Day.", player->getName().c_str()); channel->talk(player, MSG_CHANNEL, buffer); } else player->sendCancel("Only the leader of your guild can clean the guild motd."); } else if(text.substr(1, 8) == "commands") player->sendToChannel(player, MSG_CHANNEL, "Guild commands with parameters: disband, invite[name], leave, kick[name], revoke[name], demote[name], promote[name], passleadership[name], nick[name, nick], setrankname[oldName, newName], setmotd[text] and cleanmotd.", CHANNEL_GUILD); else return false; return true; }
bool Houses::loadFromXml(std::string filename) { xmlDocPtr doc = xmlParseFile(filename.c_str()); if(!doc) { std::clog << "[Warning - Houses::loadFromXml] Cannot load houses file." << std::endl; std::clog << getLastXMLError() << std::endl; return false; } xmlNodePtr houseNode, root = xmlDocGetRootElement(doc); if(xmlStrcmp(root->name,(const xmlChar*)"houses")) { std::clog << "[Error - Houses::loadFromXml] Malformed houses file." << std::endl; xmlFreeDoc(doc); return false; } int32_t intValue; std::string strValue; houseNode = root->children; while(houseNode) { if(xmlStrcmp(houseNode->name,(const xmlChar*)"house")) { houseNode = houseNode->next; continue; } int32_t houseId = 0; if(!readXMLInteger(houseNode, "houseid", houseId)) { std::clog << "[Error - Houses::loadFromXml] Could not read houseId" << std::endl; xmlFreeDoc(doc); return false; } House* house = Houses::getInstance()->getHouse(houseId); if(!house) { std::clog << "[Error - Houses::loadFromXml] Unknown house with id: " << houseId << std::endl; xmlFreeDoc(doc); return false; } Position entry(0, 0, 0); if(readXMLInteger(houseNode, "entryx", intValue)) entry.x = intValue; if(readXMLInteger(houseNode, "entryy", intValue)) entry.y = intValue; if(readXMLInteger(houseNode, "entryz", intValue)) entry.z = intValue; if(readXMLString(houseNode, "name", strValue)) house->setName(strValue); else house->resetSyncFlag(House::HOUSE_SYNC_NAME); house->setEntry(entry); if(!entry.x || !entry.y) { std::clog << "[Warning - Houses::loadFromXml] House entry not set for: " << house->getName() << " (" << houseId << ")" << std::endl; } if(readXMLInteger(houseNode, "townid", intValue)) house->setTownId(intValue); else house->resetSyncFlag(House::HOUSE_SYNC_TOWN); if(readXMLInteger(houseNode, "size", intValue)) house->setSize(intValue); else house->resetSyncFlag(House::HOUSE_SYNC_SIZE); if(readXMLString(houseNode, "guildhall", strValue)) house->setGuild(booleanString(strValue)); else house->resetSyncFlag(House::HOUSE_SYNC_GUILD); uint32_t rent = 0; if(readXMLInteger(houseNode, "rent", intValue)) rent = intValue; uint32_t price = (house->getSize() + house->getBedsCount()) * g_config.getNumber(ConfigManager::HOUSE_PRICE); // we should let players to pay only for walkable tiles + beds as single units not two items. if(g_config.getBool(ConfigManager::HOUSE_RENTASPRICE) && rent) price = rent; house->setPrice(price); if(g_config.getBool(ConfigManager::HOUSE_PRICEASRENT)) house->setRent(price); else house->setRent(rent); house->setOwner(0); houseNode = houseNode->next; } xmlFreeDoc(doc); return true; }
bool House::isGuild() const { return g_config.getBool(ConfigManager::GUILD_HALLS) && guild; }
bool Houses::payHouses() { if(rentPeriod == RENTPERIOD_NEVER) { return true; } uint32_t currentTime = std::time(NULL); for(HouseMap::iterator it = houseMap.begin(); it != houseMap.end(); ++it){ House* house = it->second; if(house->getHouseOwner() != 0 && house->getPaidUntil() < currentTime && house->getRent() != 0){ uint32_t ownerid = house->getHouseOwner(); Town* town = Towns::getInstance().getTown(house->getTownId()); if(!town){ #ifdef __DEBUG_HOUSES__ std::cout << "Warning: [Houses::payHouses] town = NULL, townid = " << house->getTownId() << ", houseid = " << house->getHouseId() << std::endl; #endif continue; } std::string name; if(!IOPlayer::instance()->getNameByGuid(ownerid, name)){ //player doesnt exist, remove it as house owner? //house->setHouseOwner(0); continue; } Player* player = g_game.getPlayerByName(name); if(!player){ player = new Player(name, NULL); if(!IOPlayer::instance()->loadPlayer(player, name)){ #ifdef __DEBUG__ std::cout << "Failure: [Houses::payHouses], can not load player: " << name << std::endl; #endif delete player; continue; } } Depot* depot = player->getDepot(town->getTownID(), true); // savePlayerHere is an ugly hack // to avoid saving 2 times a not online player // when items are transferred to his depot bool savePlayerHere = true; if(depot){ //get money from depot bool useAccBalance = g_config.getBool(ConfigManager::USE_ACCBALANCE) != 0; bool hasEnoughMoney = false; if(useAccBalance){ if(player->balance >= house->getRent()){ player->balance -= house->getRent(); hasEnoughMoney = true; } } else{ hasEnoughMoney = g_game.removeMoney(depot, house->getRent(), FLAG_NOLIMIT); } if(hasEnoughMoney){ uint32_t paidUntil = currentTime; switch(rentPeriod){ case RENTPERIOD_DAILY: paidUntil += 24 * 60 * 60; break; case RENTPERIOD_WEEKLY: paidUntil += 24 * 60 * 60 * 7; break; case RENTPERIOD_MONTHLY: paidUntil += 24 * 60 * 60 * 30; break; case RENTPERIOD_YEARLY: paidUntil += 24 * 60 * 60 * 365; case RENTPERIOD_NEVER: break; } house->setPaidUntil(paidUntil); } else if(currentTime >= house->getLastWarning() + 24 * 60 * 60){ if(house->getPayRentWarnings() >= 7){ house->setHouseOwner(0); // setHouseOwner will load the player, // transfer house items to his depot and then // will save it, so here should not be saved // again savePlayerHere = false; } else{ int daysLeft = 7 - house->getPayRentWarnings(); Item* letter = Item::CreateItem(ITEM_LETTER_STAMPED); std::string period = ""; switch(rentPeriod){ case RENTPERIOD_DAILY: period = "daily"; break; case RENTPERIOD_WEEKLY: period = "weekly"; break; case RENTPERIOD_MONTHLY: period = "monthly"; break; case RENTPERIOD_YEARLY: period = "annual"; break; case RENTPERIOD_NEVER: // break; } std::stringstream warningText; warningText << "Warning! \n" << "The " << period << " rent of " << house->getRent() << " gold for your house \"" << house->getName() << "\" is payable. Have it available within " << daysLeft << " days, or you will lose this house."; letter->setText(warningText.str()); g_game.internalAddItem(depot, letter, INDEX_WHEREEVER, FLAG_NOLIMIT); house->setPayRentWarnings(house->getPayRentWarnings() + 1); house->setLastWarning(currentTime); } } } if(player->isOffline()){ if(savePlayerHere){ IOPlayer::instance()->savePlayer(player); } delete player; } } } return true; }
int main(int argc, char *argv[]) { 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); #endif std::set_new_handler(allocationHandler); ServiceManager servicer; g_config.startup(); #ifdef __OTSERV_ALLOCATOR_STATS__ boost::thread(boost::bind(&allocatorStatsThread, (void*)NULL)); // TODO: destruct this thread... #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); #if !defined(WINDOWS) || defined(__CONSOLE__) std::string outPath = g_config.getString(ConfigManager::OUT_LOG), errPath = g_config.getString(ConfigManager::ERROR_LOG); if(outPath.length() < 3) outPath = ""; else if(outPath[0] != '/' && outPath[1] != ':') { outPath = getFilePath(FILE_TYPE_LOG, outPath); std::cout << "> Logging output to file: " << outPath << std::endl; } if(errPath.length() < 3) errPath = ""; else if(errPath[0] != '/' && errPath[1] != ':') { errPath = getFilePath(FILE_TYPE_LOG, errPath); std::cout << "> Logging errors to file: " << errPath << std::endl; } if(outPath != "") { boost::shared_ptr<std::ofstream> outFile; outFile.reset(new std::ofstream(outPath.c_str(), (g_config.getBool(ConfigManager::TRUNCATE_LOGS) ? std::ios::trunc : std::ios::app) | std::ios::out)); if(!outFile->is_open()) startupErrorMessage("Could not open output log file for writing!"); std::cout.rdbuf(outFile->rdbuf()); } if(errPath != "") { boost::shared_ptr<std::ofstream> errFile; errFile.reset(new std::ofstream(errPath.c_str(), (g_config.getBool(ConfigManager::TRUNCATE_LOGS) ? std::ios::trunc : std::ios::app) | std::ios::out)); if(!errFile->is_open()) startupErrorMessage("Could not open error log file for writing!"); std::cerr.rdbuf(errFile->rdbuf()); } #endif if(servicer.isRunning()) { std::cout << ">> " << 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)">> Status: Online!"); GUI::getInstance()->m_connections = true; #endif servicer.run(); } else { std::cout << ">> " << 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)">> Status: Offline!"); GUI::getInstance()->m_connections = true; #endif } #ifdef __EXCEPTION_TRACER__ mainExceptionHandler.RemoveHandler(); #endif #if !defined(WINDOWS) || defined(__CONSOLE__) return 0; #endif }
ReturnValue Spells::onPlayerSay(Player* player, const std::string& words) { std::string reWords = words; trimString(reWords); InstantSpell* instantSpell = getInstantSpell(reWords); if(!instantSpell) return RET_NOTPOSSIBLE; size_t size = instantSpell->getWords().length(); std::string param = reWords.substr(size, reWords.length() - size), reParam = ""; if(instantSpell->getHasParam() && !param.empty() && param[0] == ' ') { size_t quote = param.find('"', 1); if(quote != std::string::npos) { size_t tmp = param.find('"', quote + 1); if(tmp == std::string::npos) tmp = param.length(); reParam = param.substr(quote + 1, tmp - quote - 1); } else if(param.find(' ', 1) == std::string::npos) reParam = param.substr(1, param.length()); trimString(reParam); } Position pos = player->getPosition(); if(!instantSpell->castInstant(player, reParam)) return RET_NEEDEXCHANGE; SpeakClasses type = SPEAK_SAY; if(g_config.getBool(ConfigManager::EMOTE_SPELLS)) type = SPEAK_MONSTER_SAY; if(!g_config.getBool(ConfigManager::SPELL_NAME_INSTEAD_WORDS)) { if(g_config.getBool(ConfigManager::UNIFIED_SPELLS)) { reWords = instantSpell->getWords(); if(instantSpell->getHasParam()) reWords += " \"" + param + "\""; } return g_game.internalCreatureSay(player, type, reWords, player->isGhost()) ? RET_NOERROR : RET_NOTPOSSIBLE; } std::string ret = instantSpell->getName(); if(param.length()) { trimString(param); size_t tmp = 0, rtmp = param.length(); if(param[0] == '"') tmp = 1; if(param[rtmp] == '"') rtmp -= 1; ret += ": " + param.substr(tmp, rtmp); } return g_game.internalCreatureSay(player, type, ret, player->isGhost(), NULL, &pos) ? RET_NOERROR : RET_NOTPOSSIBLE; }
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 ProtocolLogin::onRecvFirstMessage(NetworkMessage& msg) { if( #if defined(WINDOWS) && !defined(_CONSOLE) !GUI::getInstance()->m_connections || #endif g_game.getGameState() == GAMESTATE_SHUTDOWN) { getConnection()->close(); return; } uint32_t clientIp = getConnection()->getIP(); msg.get<uint16_t>(); uint16_t version = msg.get<uint16_t>(); msg.skip(12); #ifdef _MULTIPLATFORM77 if(!RSA_decrypt(msg)) { getConnection()->close(); return; } uint32_t key[4] = {msg.get<uint32_t>(), msg.get<uint32_t>(), msg.get<uint32_t>(), msg.get<uint32_t>()}; enableXTEAEncryption(); setXTEAKey(key); #endif uint32_t name = msg.get<uint32_t>(); std::string password = msg.getString(); if(!name) { if(!g_config.getBool(ConfigManager::ACCOUNT_MANAGER)) { disconnectClient(0x0A, "Invalid account name."); return; } name = 1; password = "******"; } if(!g_config.getBool(ConfigManager::MANUAL_ADVANCED_CONFIG)) { if(version < CLIENT_VERSION_MIN || version > CLIENT_VERSION_MAX) { disconnectClient(0x0A, CLIENT_VERSION_STRING); return; } else if(version < g_config.getNumber(ConfigManager::VERSION_MIN) || version > g_config.getNumber(ConfigManager::VERSION_MAX)) { disconnectClient(0x0A, g_config.getString(ConfigManager::VERSION_MSG).c_str()); return; } } #ifdef CLIENT_VERSION_DATA if(sprSignature != CLIENT_VERSION_SPR) { disconnectClient(0x0A, CLIENT_VERSION_DATA); return; } if(datSignature != CLIENT_VERSION_DAT) { disconnectClient(0x0A, CLIENT_VERSION_DATA); return; } if(picSignature != CLIENT_VERSION_PIC) { disconnectClient(0x0A, CLIENT_VERSION_DATA); return; } #endif if(g_game.getGameState() < GAMESTATE_NORMAL) { disconnectClient(0x0A, "Server is just starting up, please wait."); return; } if(g_game.getGameState() == GAMESTATE_MAINTAIN) { disconnectClient(0x0A, "Server is under maintenance, please re-connect in a while."); return; } if(ConnectionManager::getInstance()->isDisabled(clientIp, protocolId)) { disconnectClient(0x0A, "Too many connections attempts from your IP address, please try again later."); return; } if(IOBan::getInstance()->isIpBanished(clientIp)) { disconnectClient(0x0A, "Your IP is banished!"); return; } uint32_t id = 1; if(!IOLoginData::getInstance()->getAccountId(name, id)) { ConnectionManager::getInstance()->addAttempt(clientIp, protocolId, false); disconnectClient(0x0A, "Invalid account id."); return; } Account account = IOLoginData::getInstance()->loadAccount(id); if(!encryptTest(account.salt + password, account.password)) { ConnectionManager::getInstance()->addAttempt(clientIp, protocolId, false); disconnectClient(0x0A, "Invalid password."); return; } Ban ban; ban.value = account.number; ban.type = BAN_ACCOUNT; if(IOBan::getInstance()->getData(ban) && !IOLoginData::getInstance()->hasFlag(account.number, PlayerFlag_CannotBeBanned)) { bool deletion = ban.expires < 0; std::string name_ = "Automatic "; if(!ban.adminId) name_ += (deletion ? "deletion" : "banishment"); else IOLoginData::getInstance()->getNameByGuid(ban.adminId, name_, true); std::stringstream ss; ss << "Your account has been " << (deletion ? "deleted" : "banished") << " at:\n" << formatDateEx(ban.added, "%d %b %Y").c_str() << " by: " << name_.c_str() << "\nReason:\n" << getReason(ban.reason).c_str() << ".\nComment:\n" << ban.comment.c_str() << ".\nYour " << (deletion ? "account won't be undeleted" : "banishment will be lifted at:\n") << (deletion ? "" : formatDateEx(ban.expires).c_str()); disconnectClient(0x0A, ss.str().c_str()); return; } // remove premium days #ifndef __LOGIN_SERVER__ IOLoginData::getInstance()->removePremium(account); if(!g_config.getBool(ConfigManager::ACCOUNT_MANAGER) && !account.charList.size()) { disconnectClient(0x0A, std::string("This account does not contain any character yet.\nCreate a new character on the " + g_config.getString(ConfigManager::SERVER_NAME) + " website at " + g_config.getString(ConfigManager::URL) + ".").c_str()); return; } #else Characters charList; for(Characters::iterator it = account.charList.begin(); it != account.charList.end(); ++it) { if(version >= it->second.server->getVersionMin() && version <= it->second.server->getVersionMax()) charList[it->first] = it->second; } IOLoginData::getInstance()->removePremium(account); if(!g_config.getBool(ConfigManager::ACCOUNT_MANAGER) && !charList.size()) { disconnectClient(0x0A, std::string("This account does not contain any character on this client yet.\nCreate a new character on the " + g_config.getString(ConfigManager::SERVER_NAME) + " website at " + g_config.getString(ConfigManager::URL) + ".").c_str()); return; } #endif ConnectionManager::getInstance()->addAttempt(clientIp, protocolId, true); if(OutputMessage_ptr output = OutputMessagePool::getInstance()->getOutputMessage(this, false)) { TRACK_MESSAGE(output); output->put<char>(0x14); uint32_t serverIp = serverIps.front().first; for(std::list<std::pair<uint32_t, uint32_t> >::iterator it = serverIps.begin(); it != serverIps.end(); ++it) { if((it->first & it->second) != (clientIp & it->second)) continue; serverIp = it->first; break; } char motd[1300]; sprintf(motd, "%d\n%s", g_game.getMotdId(), g_config.getString(ConfigManager::MOTD).c_str()); output->putString(motd); //Add char list output->put<char>(0x64); if(g_config.getBool(ConfigManager::ACCOUNT_MANAGER) && account.number != 1) { output->put<char>(account.charList.size() + 1); output->putString("Account Manager"); output->putString(g_config.getString(ConfigManager::SERVER_NAME)); output->put<uint32_t>(serverIp); output->put<uint16_t>(g_config.getNumber(ConfigManager::GAME_PORT)); } else output->put<char>((uint8_t)account.charList.size()); #ifndef __LOGIN_SERVER__ for(Characters::iterator it = account.charList.begin(); it != account.charList.end(); ++it) { output->putString((*it)); if(g_config.getBool(ConfigManager::ON_OR_OFF_CHARLIST) && !g_config.getBool(ConfigManager::CHARLIST_INFO)) { if(g_game.getPlayerByName((*it))) output->putString("Online"); else output->putString("Offline"); } else if(g_config.getBool(ConfigManager::CHARLIST_INFO)) { std::stringstream str; Player *player = g_game.getPlayerByName((*it)); bool v = false; if(g_config.getBool(ConfigManager::ON_OR_OFF_CHARLIST)) { if(player) str << "On"; else str << "Off"; str << "/"; } if(!player) { v = true; player = g_game.getPlayerByNameEx((*it)); } str << player->getLevel(); str << "/"; str << player->getVocation()->getName(); output->putString(str.str()); if(v) delete player; } else output->putString(g_config.getString(ConfigManager::SERVER_NAME)); output->put<uint32_t>(serverIp); output->put<uint16_t>(g_config.getNumber(ConfigManager::GAME_PORT)); } #else for(Characters::iterator it = charList.begin(); it != charList.end(); ++it) { output->putString(it->second.name); if(!g_config.getBool(ConfigManager::ON_OR_OFF_CHARLIST) || it->second.status < 0) output->putString(it->second.server->getName()); else if(it->second.status) output->putString("Online"); else output->putString("Offline"); output->put<uint32_t>(it->second.server->getAddress()); IntegerVec games = it->second.server->getPorts(); output->put<uint16_t>(games[random_range(0, games.size() - 1)]); } #endif //Add premium days if(g_config.getBool(ConfigManager::FREE_PREMIUM)) output->put<uint16_t>(GRATIS_PREMIUM); else output->put<uint16_t>(account.premiumDays); OutputMessagePool::getInstance()->send(output); } getConnection()->close(); }