Skip to content

Commit

Permalink
fix: house transfer owner only in startup
Browse files Browse the repository at this point in the history
  • Loading branch information
dudantas committed Sep 19, 2023
1 parent 3fbbd46 commit bb9e300
Show file tree
Hide file tree
Showing 16 changed files with 223 additions and 50 deletions.
2 changes: 1 addition & 1 deletion data-otservbr-global/lib/compat/compat.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1231,7 +1231,7 @@ end

function setHouseOwner(id, guid)
local h = House(id)
return h and h:setOwnerGuid(guid) or false
return h and h:setHouseOwner(guid) or false
end

function getHouseRent(id)
Expand Down
4 changes: 3 additions & 1 deletion data-otservbr-global/migrations/39.lua
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
function onUpdateDatabase()
return false -- true = There are others migrations file | false = this is the last migration file
logger.info("Updating database to version 39 (house transfer ownership on startup)")
db.query("ALTER TABLE `houses` ADD `new_owner` int(11) NOT NULL DEFAULT '-1';")
return true
end
3 changes: 3 additions & 0 deletions data-otservbr-global/migrations/40.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
function onUpdateDatabase()
return false -- true = There are others migrations file | false = this is the last migration file
end
4 changes: 2 additions & 2 deletions data/scripts/talkactions/god/house_owner.lua
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ function houseOwner.onSay(player, words, param)
end

if param == "" or param == "none" then
house:setOwnerGuid(0)
house:setHouseOwner(0)
return true
end

Expand All @@ -22,7 +22,7 @@ function houseOwner.onSay(player, words, param)
return true
end

house:setOwnerGuid(targetPlayer:getGuid())
house:setHouseOwner(targetPlayer:getGuid())
return true
end

Expand Down
2 changes: 1 addition & 1 deletion data/scripts/talkactions/player/buy_house.lua
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ function buyHouse.onSay(player, words, param)
return false
end

house:setOwnerGuid(player:getGuid())
house:setHouseOwner(player:getGuid())
player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have successfully bought this house, be sure to have the money for the rent in the bank.")
return false
end
Expand Down
8 changes: 7 additions & 1 deletion data/scripts/talkactions/player/leave_house.lua
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ function leaveHouse.onSay(player, words, param)
return false
end

if house:haveNewOwnership() then
player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You cannot leave this house. Ownership is already scheduled to be transferred upon the next server restart.")
playerPosition:sendMagicEffect(CONST_ME_POFF)
return false
end

-- Move hireling back to lamp
local tiles = house:getTiles()
if tiles then
Expand All @@ -30,7 +36,7 @@ function leaveHouse.onSay(player, words, param)
end
end

house:setOwnerGuid(0)
house:setNewOwnerGuid(0)
player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have successfully left your house.")
playerPosition:sendMagicEffect(CONST_ME_POFF)
return false
Expand Down
1 change: 1 addition & 0 deletions schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,7 @@ CREATE TABLE IF NOT EXISTS `guild_membership` (
CREATE TABLE IF NOT EXISTS `houses` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`owner` int(11) NOT NULL,
`new_owner` int(11) NOT NULL DEFAULT '-1',
`paid` int(10) UNSIGNED NOT NULL DEFAULT '0',
`warnings` int(11) NOT NULL DEFAULT '0',
`name` varchar(255) NOT NULL,
Expand Down
1 change: 1 addition & 0 deletions src/canary_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ int CanaryServer::run() {
g_game().setGameState(GAME_STATE_INIT);

setupHousesRent();
g_game().transferHouseItemsToDepot();

IOMarket::checkExpiredOffers();
IOMarket::getInstance().updateStatistics();
Expand Down
37 changes: 37 additions & 0 deletions src/game/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9854,6 +9854,43 @@ const std::unique_ptr<IOWheel> &Game::getIOWheel() const {
return m_IOWheel;
}

void Game::transferHouseItemsToDepot() {
if (transferHouseItemsToPlayer.size() != 0) {
g_logger().info("Initializing house transfer items");
}

uint16_t transferSuccess = 0;
for (const auto &[houseId, playerGuid] : transferHouseItemsToPlayer) {
House* house = map.houses.getHouse(houseId);
if (house) {
auto offlinePlayer = new Player(nullptr);
if (!IOLoginData::loadPlayerById(offlinePlayer, playerGuid)) {
delete offlinePlayer;
continue;
}

if (!offlinePlayer) {
continue;
}

g_logger().info("Tranfering items to the inbox from player '{}'", offlinePlayer->getName());
if (house->tryTransferOwnership(offlinePlayer, false)) {
transferSuccess++;
house->setNewOwnerGuid(-1, true);
}
}
}
if (transferSuccess > 0) {
g_logger().info("Finished house transfer items from '{}' players", transferSuccess);
transferHouseItemsToPlayer.clear();
map.save();
}
}

void Game::setTransferPlayerHouseItems(uint32_t houseId, uint32_t playerId) {
transferHouseItemsToPlayer[houseId] = playerId;
}

template <typename T>
phmap::parallel_flat_hash_set<T> setDifference(const phmap::parallel_flat_hash_set<T> &setA, const phmap::parallel_flat_hash_set<T> &setB) {
phmap::parallel_flat_hash_set<T> setResult;
Expand Down
5 changes: 5 additions & 0 deletions src/game/game.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,9 @@ class Game {
std::unique_ptr<IOWheel> &getIOWheel();
const std::unique_ptr<IOWheel> &getIOWheel() const;

void setTransferPlayerHouseItems(uint32_t houseId, uint32_t playerId);
void transferHouseItemsToDepot();

private:
std::map<uint32_t, int32_t> forgeMonsterEventIds;
std::set<uint32_t> fiendishMonsters;
Expand Down Expand Up @@ -769,6 +772,8 @@ class Game {
std::map<uint32_t, Monster*> monsters;
std::vector<uint32_t> forgeableMonsters;

std::map<uint32_t, uint32_t> transferHouseItemsToPlayer;

std::map<uint32_t, TeamFinder*> teamFinderMap; // [leaderGUID] = TeamFinder*

// list of items that are in trading state, mapped to the player
Expand Down
3 changes: 2 additions & 1 deletion src/io/iologindata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,8 @@ bool IOLoginData::loadPlayerByName(Player* player, const std::string &name, bool

bool IOLoginData::loadPlayer(Player* player, DBResult_ptr result, bool disable /* = false*/) {
if (!result || !player) {
g_logger().warn("[IOLoginData::loadPlayer] - Player or Resultnullptr: {}", __FUNCTION__);
std::string nullptrType = !result ? "Result" : "Player";
g_logger().warn("[{}] - {} is nullptr", __FUNCTION__, nullptrType);
return false;
}

Expand Down
22 changes: 19 additions & 3 deletions src/io/iomapserialize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "pch.hpp"

#include "io/iomapserialize.hpp"
#include "io/iologindata.hpp"
#include "game/game.hpp"
#include "items/bed.hpp"

Expand Down Expand Up @@ -259,15 +260,30 @@ void IOMapSerialize::saveTile(PropWriteStream &stream, const Tile* tile) {
bool IOMapSerialize::loadHouseInfo() {
Database &db = Database::getInstance();

DBResult_ptr result = db.storeQuery("SELECT `id`, `owner`, `paid`, `warnings` FROM `houses`");
DBResult_ptr result = db.storeQuery("SELECT `id`, `owner`, `new_owner`, `paid`, `warnings` FROM `houses`");
if (!result) {
return false;
}

do {
House* house = g_game().map.houses.getHouse(result->getNumber<uint32_t>("id"));
auto houseId = result->getNumber<uint32_t>("id");
House* house = g_game().map.houses.getHouse(houseId);
if (house) {
house->setOwner(result->getNumber<uint32_t>("owner"), false);
uint32_t owner = result->getNumber<uint32_t>("owner");
int32_t newOwner = result->getNumber<int32_t>("new_owner");
// Transfer house owner
if (newOwner >= 0) {
g_game().setTransferPlayerHouseItems(houseId, owner);
if (newOwner == 0) {
g_logger().debug("Removing house id '{}' owner", houseId);
house->setOwner(0);
} else {
g_logger().debug("Setting house id '{}' owner to player GUID '{}'", houseId, newOwner);
house->setOwner(newOwner);
}
} else {
house->setOwner(owner, false);
}
house->setPaidUntil(result->getNumber<time_t>("paid"));
house->setPayRentWarnings(result->getNumber<uint32_t>("warnings"));
}
Expand Down
46 changes: 44 additions & 2 deletions src/lua/functions/map/house_functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,8 @@ int HouseFunctions::luaHouseGetOwnerGuid(lua_State* L) {
return 1;
}

int HouseFunctions::luaHouseSetOwnerGuid(lua_State* L) {
// house:setOwnerGuid(guid[, updateDatabase = true])
int HouseFunctions::luaHouseSetHouseOwner(lua_State* L) {
// house:setHouseOwner(guid[, updateDatabase = true])
House* house = getUserdata<House>(L, 1);
if (house) {
uint32_t guid = getNumber<uint32_t>(L, 2);
Expand All @@ -128,6 +128,41 @@ int HouseFunctions::luaHouseSetOwnerGuid(lua_State* L) {
return 1;
}

int HouseFunctions::luaHouseSetNewOwnerGuid(lua_State* L) {
// house:setNewOwnerGuid(guid)
House* house = getUserdata<House>(L, 1);
if (house) {
if (house->haveNewOwnership()) {
Player* player = g_game().getPlayerByGUID(house->getOwner());
if (player) {
player->sendTextMessage(MESSAGE_EVENT_ADVANCE, "You cannot leave this house. Ownership is already scheduled to be transferred upon the next server restart.");
}
lua_pushnil(L);
return 1;
}

uint32_t guid = getNumber<uint32_t>(L, 2, 0);
house->setNewOwnerGuid(guid, false);
pushBoolean(L, true);
} else {
lua_pushnil(L);
}
return 1;
}

int HouseFunctions::luaHouseHaveNewOwnership(lua_State* L) {
// house:haveNewOwnership(guid)
House* house = getUserdata<House>(L, 1);
if (!house) {
reportErrorFunc("House not found");
lua_pushnil(L);
return 1;
}

pushBoolean(L, house->haveNewOwnership());
return 1;
}

int HouseFunctions::luaHouseStartTrade(lua_State* L) {
// house:startTrade(player, tradePartner)
House* house = getUserdata<House>(L, 1);
Expand Down Expand Up @@ -165,6 +200,13 @@ int HouseFunctions::luaHouseStartTrade(lua_State* L) {
return 1;
}

if (house->haveNewOwnership()) {
tradePartner->sendTextMessage(MESSAGE_EVENT_ADVANCE, "You cannot buy this house. Ownership is already scheduled to be transferred upon the next server restart.");
player->sendTextMessage(MESSAGE_EVENT_ADVANCE, "You cannot sell this house. Ownership is already scheduled to be transferred upon the next server restart.");
lua_pushnumber(L, RETURNVALUE_YOUCANNOTTRADETHISHOUSE);
return 1;
}

transferItem->getParent()->setParent(player);
if (!g_game().internalStartTrade(player, tradePartner, transferItem)) {
house->resetTransferItem();
Expand Down
8 changes: 6 additions & 2 deletions src/lua/functions/map/house_functions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ class HouseFunctions final : LuaScriptInterface {
registerMethod(L, "House", "getPrice", HouseFunctions::luaHouseGetPrice);

registerMethod(L, "House", "getOwnerGuid", HouseFunctions::luaHouseGetOwnerGuid);
registerMethod(L, "House", "setOwnerGuid", HouseFunctions::luaHouseSetOwnerGuid);
registerMethod(L, "House", "setHouseOwner", HouseFunctions::luaHouseSetHouseOwner);
registerMethod(L, "House", "setNewOwnerGuid", HouseFunctions::luaHouseSetNewOwnerGuid);
registerMethod(L, "House", "haveNewOwnership", HouseFunctions::luaHouseHaveNewOwnership);
registerMethod(L, "House", "startTrade", HouseFunctions::luaHouseStartTrade);

registerMethod(L, "House", "getBeds", HouseFunctions::luaHouseGetBeds);
Expand Down Expand Up @@ -58,7 +60,9 @@ class HouseFunctions final : LuaScriptInterface {
static int luaHouseGetPrice(lua_State* L);

static int luaHouseGetOwnerGuid(lua_State* L);
static int luaHouseSetOwnerGuid(lua_State* L);
static int luaHouseSetHouseOwner(lua_State* L);
static int luaHouseSetNewOwnerGuid(lua_State* L);
static int luaHouseHaveNewOwnership(lua_State* L);
static int luaHouseStartTrade(lua_State* L);

static int luaHouseGetBeds(lua_State* L);
Expand Down
Loading

0 comments on commit bb9e300

Please sign in to comment.