bool Houses::loadHousesXML(const std::string& filename) { pugi::xml_document doc; pugi::xml_parse_result result = doc.load_file(filename.c_str()); if (!result) { std::cout << "[Error - Houses::loadHousesXML] Failed to load " << filename << ": " << result.description() << std::endl; return false; } for (pugi::xml_node houseNode = doc.child("houses").first_child(); houseNode; houseNode = houseNode.next_sibling()) { pugi::xml_attribute houseIdAttribute = houseNode.attribute("houseid"); if (!houseIdAttribute) { return false; } int32_t _houseid = pugi::cast<int32_t>(houseIdAttribute.value()); House* house = Houses::getInstance().getHouse(_houseid); if (!house) { std::cout << "Error: [Houses::loadHousesXML] Unknown house, id = " << _houseid << std::endl; return false; } house->setName(houseNode.attribute("name").as_string()); Position entryPos( pugi::cast<uint16_t>(houseNode.attribute("entryx").value()), pugi::cast<uint16_t>(houseNode.attribute("entryy").value()), pugi::cast<uint16_t>(houseNode.attribute("entryz").value()) ); if (entryPos.x == 0 && entryPos.y == 0 && entryPos.z == 0) { std::cout << "[Warning - Houses::loadHousesXML] House entry not set" << " - Name: " << house->getName() << " - House id: " << _houseid << std::endl; } house->setEntryPos(entryPos); house->setRent(pugi::cast<uint32_t>(houseNode.attribute("rent").value())); house->setTownId(pugi::cast<uint32_t>(houseNode.attribute("townid").value())); house->setOwner(0, false); } return true; }
void Commands::getHouse(Player* player, const std::string& cmd, const std::string& param) { std::string name = param; uint32_t guid; if (!IOLoginData::getInstance()->getGuidByName(guid, name)) { return; } std::ostringstream str(name); House* house = Houses::getInstance().getHouseByPlayerId(guid); if (house) { str << " owns house: " << house->getName() << "."; } else { str << " does not own any house."; } player->sendTextMessage(MSG_STATUS_CONSOLE_BLUE, str.str()); }
bool Commands::getHouse(Creature* creature, const std::string& cmd, const std::string& param) { Player* player = creature->getPlayer(); if(!player) return false; std::string real_name = param; uint32_t guid; if(IOPlayer::instance()->getGuidByName(guid, real_name)){ House* house = Houses::getInstance().getHouseByPlayerId(guid); std::stringstream str; str << real_name; if(house){ str << " owns house: " << house->getName() << "."; } else{ str << " does not own any house."; } player->sendTextMessage(MSG_STATUS_CONSOLE_BLUE, str.str().c_str()); } return false; }
bool Houses::loadFromXml(std::string filename) { xmlDocPtr doc = xmlParseFile(filename.c_str()); if(!doc) { LOGe("[Houses::loadFromXml] Cannot load houses file: " << getLastXMLError()); return false; } xmlNodePtr houseNode, root = xmlDocGetRootElement(doc); if(xmlStrcmp(root->name,(const xmlChar*)"houses")) { LOGe("[Houses::loadFromXml] Malformed houses file."); 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)) { LOGe("[Houses::loadFromXml] Could not read houseId"); xmlFreeDoc(doc); return false; } House* house = Houses::getInstance()->getHouse(houseId); if(!house) { LOGe("[Houses::loadFromXml] Unknown house with id: " << houseId); 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; house->setEntry(entry); if(!entry.x || !entry.y) { LOGw("[Houses::loadFromXml] House entry not set for: " << house->getName() << " (" << houseId << ")"); } if(readXMLString(houseNode, "name", strValue)) house->setName(strValue); else house->resetSyncFlag(House::HOUSE_SYNC_NAME); 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->getTilesCount() * server.configManager().getNumber(ConfigManager::HOUSE_PRICE); if(server.configManager().getBool(ConfigManager::HOUSE_RENTASPRICE)) { uint32_t tmp = rent; if(!tmp) tmp = price; house->setPrice(tmp); } else house->setPrice(price); if(server.configManager().getBool(ConfigManager::HOUSE_PRICEASRENT)) house->setRent(price); else house->setRent(rent); house->setOwner(0); houseNode = houseNode->next; } xmlFreeDoc(doc); return true; }
bool IOMapSerialize::updateHouses() { Database* db = Database::getInstance(); DBQuery query; House* house = NULL; for(HouseMap::iterator it = Houses::getInstance()->getHouseBegin(); it != Houses::getInstance()->getHouseEnd(); ++it) { if(!(house = it->second)) continue; query << "SELECT `price` FROM `houses` WHERE `id` = " << house->getId() << " AND `world_id` = " << g_config.getNumber(ConfigManager::WORLD_ID) << " LIMIT 1"; if(DBResult* result = db->storeQuery(query.str())) { if((uint32_t)result->getDataInt("price") != house->getPrice()) house->setSyncFlag(House::HOUSE_SYNC_UPDATE); result->free(); query.str(""); query << "UPDATE `houses` SET "; if(house->hasSyncFlag(House::HOUSE_SYNC_NAME)) query << "`name` = " << db->escapeString(house->getName()) << ", "; if(house->hasSyncFlag(House::HOUSE_SYNC_TOWN)) query << "`town` = " << house->getTownId() << ", "; if(house->hasSyncFlag(House::HOUSE_SYNC_SIZE)) query << "`size` = " << house->getSize() << ", "; if(house->hasSyncFlag(House::HOUSE_SYNC_PRICE)) query << "`price` = " << house->getPrice() << ", "; if(house->hasSyncFlag(House::HOUSE_SYNC_RENT)) query << "`rent` = " << house->getRent() << ", "; query << "`doors` = " << house->getDoorsCount() << ", `beds` = " << house->getBedsCount() << ", `tiles` = " << house->getTilesCount(); if(house->hasSyncFlag(House::HOUSE_SYNC_GUILD)) query << ", `guild` = " << house->isGuild(); query << " WHERE `id` = " << house->getId() << " AND `world_id` = " << g_config.getNumber(ConfigManager::WORLD_ID) << db->getUpdateLimiter(); } else { query.str(""); query << "INSERT INTO `houses` (`id`, `world_id`, `owner`, `name`, `town`, `size`, `price`, `rent`, `doors`, `beds`, `tiles`, `guild`) VALUES (" << house->getId() << ", " << g_config.getNumber(ConfigManager::WORLD_ID) << ", 0, " //we need owner for compatibility reasons (field doesn't have a default value) << db->escapeString(house->getName()) << ", " << house->getTownId() << ", " << house->getSize() << ", " << house->getPrice() << ", " << house->getRent() << ", " << house->getDoorsCount() << ", " << house->getBedsCount() << ", " << house->getTilesCount() << ", " << house->isGuild() << ")"; } if(!db->query(query.str())) return false; query.str(""); } return true; }
bool Houses::payHouses() const { if (rentPeriod == RENTPERIOD_NEVER) { return true; } time_t currentTime = time(nullptr); for (const auto& it : houseMap) { House* house = it.second; if (house->getOwner() == 0) { continue; } const uint32_t rent = house->getRent(); if (rent == 0 || house->getPaidUntil() > currentTime) { continue; } const uint32_t ownerid = house->getOwner(); Town* town = Towns::getInstance().getTown(house->getTownId()); if (!town) { continue; } Player player(nullptr); if (!IOLoginData::loadPlayerById(&player, ownerid)) { //player doesnt exist, reset house owner house->setOwner(0); continue; } if (player.getBankBalance() >= rent) { player.setBankBalance(player.getBankBalance() - rent); time_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; break; default: break; } house->setPaidUntil(paidUntil); } else { if (house->getPayRentWarnings() < 7) { int32_t 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; default: break; } std::ostringstream ss; ss << "Warning! \nThe " << period << " rent of " << house->getRent() << " gold for your house \"" << house->getName() << "\" is payable. Have it within " << daysLeft << " days or you will lose this house."; letter->setText(ss.str()); g_game.internalAddItem(player.getInbox(), letter, INDEX_WHEREEVER, FLAG_NOLIMIT); house->setPayRentWarnings(house->getPayRentWarnings() + 1); } else { house->setOwner(0, true, &player); } } IOLoginData::savePlayer(&player); } 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 IOMapSerialize::saveHouseInfo() { Database& db = Database::getInstance(); DBTransaction transaction; if (!transaction.begin()) { return false; } if (!db.executeQuery("DELETE FROM `house_lists`")) { return false; } std::ostringstream query; for (const auto& it : g_game.map.houses.getHouses()) { House* house = it.second; query << "SELECT `id` FROM `houses` WHERE `id` = " << house->getId(); DBResult_ptr result = db.storeQuery(query.str()); if (result) { query.str(std::string()); query << "UPDATE `houses` SET `owner` = " << house->getOwner() << ", `paid` = " << house->getPaidUntil() << ", `warnings` = " << house->getPayRentWarnings() << ", `name` = " << db.escapeString(house->getName()) << ", `town_id` = " << house->getTownId() << ", `rent` = " << house->getRent() << ", `size` = " << house->getTiles().size() << ", `beds` = " << house->getBedCount() << " WHERE `id` = " << house->getId(); } else { query.str(std::string()); query << "INSERT INTO `houses` (`id`, `owner`, `paid`, `warnings`, `name`, `town_id`, `rent`, `size`, `beds`) VALUES (" << house->getId() << ',' << house->getOwner() << ',' << house->getPaidUntil() << ',' << house->getPayRentWarnings() << ',' << db.escapeString(house->getName()) << ',' << house->getTownId() << ',' << house->getRent() << ',' << house->getTiles().size() << ',' << house->getBedCount() << ')'; } db.executeQuery(query.str()); query.str(std::string()); } DBInsert stmt("INSERT INTO `house_lists` (`house_id` , `listid` , `list`) VALUES "); for (const auto& it : g_game.map.houses.getHouses()) { House* house = it.second; std::string listText; if (house->getAccessList(GUEST_LIST, listText) && !listText.empty()) { query << house->getId() << ',' << GUEST_LIST << ',' << db.escapeString(listText); if (!stmt.addRow(query)) { return false; } listText.clear(); } if (house->getAccessList(SUBOWNER_LIST, listText) && !listText.empty()) { query << house->getId() << ',' << SUBOWNER_LIST << ',' << db.escapeString(listText); if (!stmt.addRow(query)) { return false; } listText.clear(); } for (Door* door : house->getDoors()) { if (door->getAccessList(listText) && !listText.empty()) { query << house->getId() << ',' << door->getDoorId() << ',' << db.escapeString(listText); if (!stmt.addRow(query)) { return false; } listText.clear(); } } } if (!stmt.execute()) { return false; } return transaction.commit(); }
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; }
bool Houses::loadHousesXML(std::string filename) { xmlDocPtr doc = xmlParseFile(filename.c_str()); if(doc){ xmlNodePtr root, houseNode; root = xmlDocGetRootElement(doc); if(xmlStrcmp(root->name,(const xmlChar*)"houses") != 0){ xmlFreeDoc(doc); return false; } int intValue; std::string strValue; houseNode = root->children; while(houseNode){ if(xmlStrcmp(houseNode->name,(const xmlChar*)"house") == 0){ int _houseid = 0; Position entryPos(0, 0, 0); if(!readXMLInteger(houseNode, "houseid", _houseid)){ xmlFreeDoc(doc); return false; } House* house = Houses::getInstance().getHouse(_houseid); if(!house){ std::cout << "Error: [Houses::loadHousesXML] Unknown house, id = " << _houseid << std::endl; xmlFreeDoc(doc); return false; } if(readXMLString(houseNode, "name", strValue)){ house->setName(strValue); } if(readXMLInteger(houseNode, "entryx", intValue)){ entryPos.x = intValue; } if(readXMLInteger(houseNode, "entryy", intValue)){ entryPos.y = intValue; } if(readXMLInteger(houseNode, "entryz", intValue)){ entryPos.z = intValue; } if(entryPos.x == 0 && entryPos.y == 0 && entryPos.z == 0){ std::cout << "Warning: [Houses::loadHousesXML] House entry not set" << " - Name: " << house->getName() << " - House id: " << _houseid << std::endl; } house->setEntryPos(entryPos); if(readXMLInteger(houseNode, "rent", intValue)){ house->setRent(intValue); } if(readXMLInteger(houseNode, "townid", intValue)){ house->setTownId(intValue); } house->setHouseOwner(0); } houseNode = houseNode->next; } xmlFreeDoc(doc); return true; } return false; }
bool Houses::payHouses() { if (rentPeriod == RENTPERIOD_NEVER) { return true; } time_t currentTime = time(NULL); for (HouseMap::iterator it = houseMap.begin(); it != houseMap.end(); ++it) { House* house = it->second; if (house->getHouseOwner() != 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 (!IOLoginData::getInstance()->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 (!IOLoginData::getInstance()->loadPlayer(player, name)) { #ifdef __DEBUG__ std::cout << "Failure: [Houses::payHouses], can not load player: " << name << std::endl; #endif delete player; continue; } } bool paid = false; if (player->getBankBalance() >= house->getRent()) { player->setBankBalance(player->getBankBalance() - house->getRent()); paid = true; } if (paid) { time_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; break; default: break; } house->setPaidUntil(paidUntil); } else { if (house->getPayRentWarnings() < 7) { int32_t 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; default: break; } std::ostringstream ss; ss << "Warning! \nThe " << period << " rent of " << house->getRent() << " gold for your house \"" << house->getName() << "\" is payable. Have it within " << daysLeft << " days or you will lose this house."; letter->setText(ss.str()); g_game.internalAddItem(player->getInbox(), letter, INDEX_WHEREEVER, FLAG_NOLIMIT); house->setPayRentWarnings(house->getPayRentWarnings() + 1); } else { house->setHouseOwner(0, true, player); } } if (player->isOffline()) { IOLoginData::getInstance()->savePlayer(player); delete player; } } } return true; }