bool IOMapSerialize::loadHouses() { Database* db = Database::getInstance(); DBQuery query; query << "SELECT * FROM `houses` WHERE `world_id` = " << g_config.getNumber(ConfigManager::WORLD_ID); DBResult* result; if(!(result = db->storeQuery(query.str()))) return false; House* house = NULL; do { if(!(house = Houses::getInstance()->getHouse(result->getDataInt("id")))) continue; house->setRentWarnings(result->getDataInt("warnings")); house->setLastWarning(result->getDataInt("lastwarning")); house->setPaidUntil(result->getDataInt("paid")); if(result->getDataInt("clear") == 1) house->setPendingTransfer(true); house->setOwner(result->getDataInt("owner")); if(house->getOwner() && house->hasSyncFlag(House::HOUSE_SYNC_UPDATE)) house->resetSyncFlag(House::HOUSE_SYNC_UPDATE); } while(result->next()); result->free(); for(HouseMap::iterator it = Houses::getInstance()->getHouseBegin(); it != Houses::getInstance()->getHouseEnd(); ++it) { if(!(house = it->second) || !house->getId() || !house->getOwner()) continue; query.str(""); query << "SELECT `listid`, `list` FROM `house_lists` WHERE `house_id` = " << house->getId(); query << " AND `world_id` = " << g_config.getNumber(ConfigManager::WORLD_ID); if(!(result = db->storeQuery(query.str()))) continue; do house->setAccessList(result->getDataInt("listid"), result->getDataString("list")); while(result->next()); result->free(); } return true; }
void Commands::sellHouse(Player& player, const std::string& param) { Player* tradePartner = g_game.getPlayerByName(param); if (!tradePartner || tradePartner == &player) { player.sendCancel("Trade player not found."); return; } if (!Position::areInRange<2, 2, 0>(tradePartner->getPosition(), player.getPosition())) { player.sendCancel("Trade player is too far away."); return; } if (!tradePartner->isPremium()) { player.sendCancel("Trade player does not have a premium account."); return; } HouseTile* houseTile = dynamic_cast<HouseTile*>(player.getTile()); if (!houseTile) { player.sendCancel("You must stand in your house to initiate the trade."); return; } House* house = houseTile->getHouse(); if (!house || house->getOwner() != player.getGUID()) { player.sendCancel("You don't own this house."); return; } if (Houses::getInstance().getHouseByPlayerId(tradePartner->getGUID())) { player.sendCancel("Trade player already owns a house."); return; } if (IOLoginData::hasBiddedOnHouse(tradePartner->getGUID())) { player.sendCancel("Trade player is currently the highest bidder of an auctioned house."); return; } Item* transferItem = house->getTransferItem(); if (!transferItem) { player.sendCancel("You can not trade this house."); return; } transferItem->getParent()->setParent(&player); if (!g_game.internalStartTrade(&player, tradePartner, transferItem)) { house->resetTransferItem(); } }
bool IOMapSerialize::loadMapBinaryTileBased(Map* map) { Database* db = Database::getInstance(); DBResult* result; DBQuery query; query << "SELECT `house_id`, `data` FROM `tile_store` WHERE `world_id` = " << g_config.getNumber(ConfigManager::WORLD_ID); if(!(result = db->storeQuery(query.str()))) return false; House* house = NULL; do { int32_t houseId = result->getDataInt("house_id"); house = Houses::getInstance()->getHouse(houseId); uint64_t attrSize = 0; const char* attr = result->getDataStream("data", attrSize); PropStream propStream; propStream.init(attr, attrSize); while(propStream.size()) { uint16_t x = 0, y = 0; uint8_t z = 0; propStream.getShort(x); propStream.getShort(y); propStream.getByte(z); uint32_t itemCount = 0; propStream.getLong(itemCount); Position pos(x, y, (int16_t)z); if(house && house->hasPendingTransfer()) { if(Player* player = g_game.getPlayerByGuidEx(house->getOwner())) { while(itemCount--) loadItem(propStream, player->getInbox(), true); if(player->isVirtual()) { IOLoginData::getInstance()->savePlayer(player); delete player; } } } else if(Tile* tile = map->getTile(pos)) { while(itemCount--) loadItem(propStream, tile, false); } else { std::clog << "[Error - IOMapSerialize::loadMapBinary] Unserialization of invalid tile" << " at position " << pos << std::endl; break; } } } while(result->next()); result->free(); return true; }
bool IOMapSerialize::loadMapRelational(Map* map) { Database* db = Database::getInstance(); DBQuery query; //lock mutex! House* house = NULL; for(HouseMap::iterator it = Houses::getInstance()->getHouseBegin(); it != Houses::getInstance()->getHouseEnd(); ++it) { if(!(house = it->second)) continue; query.str(""); query << "SELECT * FROM `tiles` WHERE `house_id` = " << house->getId() << " AND `world_id` = " << g_config.getNumber(ConfigManager::WORLD_ID); if(DBResult* result = db->storeQuery(query.str())) { do { query.str(""); query << "SELECT * FROM `tile_items` WHERE `tile_id` = " << result->getDataInt("id") << " AND `world_id` = " << g_config.getNumber(ConfigManager::WORLD_ID) << " ORDER BY `sid` DESC"; if(DBResult* itemsResult = db->storeQuery(query.str())) { if(house->hasPendingTransfer()) { if(Player* player = g_game.getPlayerByGuidEx(house->getOwner())) { loadItems(itemsResult, player->getInbox(), true); if(player->isVirtual()) { IOLoginData::getInstance()->savePlayer(player); delete player; } } } else { Position pos(result->getDataInt("x"), result->getDataInt("y"), result->getDataInt("z")); if(Tile* tile = map->getTile(pos)) loadItems(itemsResult, tile, false); else std::clog << "[Error - IOMapSerialize::loadMapRelational] Unserialization" << " of invalid tile at position "<< pos << std::endl; } itemsResult->free(); } } while(result->next()); result->free(); } else //backward compatibility { for(HouseTileList::iterator it = house->getHouseTileBegin(); it != house->getHouseTileEnd(); ++it) { query.str(""); query << "SELECT `id` FROM `tiles` WHERE `x` = " << (*it)->getPosition().x << " AND `y` = " << (*it)->getPosition().y << " AND `z` = " << (*it)->getPosition().z << " AND `world_id` = " << g_config.getNumber(ConfigManager::WORLD_ID) << " LIMIT 1"; if(DBResult* result = db->storeQuery(query.str())) { query.str(""); query << "SELECT * FROM `tile_items` WHERE `tile_id` = " << result->getDataInt("id") << " AND `world_id` = " << g_config.getNumber(ConfigManager::WORLD_ID) << " ORDER BY `sid` DESC"; if(DBResult* itemsResult = db->storeQuery(query.str())) { if(house->hasPendingTransfer()) { if(Player* player = g_game.getPlayerByGuidEx(house->getOwner())) { loadItems(itemsResult, player->getInbox(), true); if(player->isVirtual()) { IOLoginData::getInstance()->savePlayer(player); delete player; } } } else loadItems(itemsResult, (*it), false); itemsResult->free(); } result->free(); } } } } 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 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(); }