• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

C++ send item to offline player depot

mattch

New Member
Joined
Jun 15, 2013
Messages
13
Solutions
1
Reaction score
3
Hello.
I'm trying to make a function that send the item to the player depot, even if he are not online.

Thats the function that i created. Its only working if the player is online.
C++:
int LuaScriptInterface::luaSendPlayerDepotItem(lua_State* L)
{
    //sendPlayerDepotItem(guid, item[, depotId = 0])
    uint32_t guid = getNumber<uint32_t>(L, 1);
    Item* item = getScriptEnv()->getItemByUID(getNumber<uint32_t>(L, 2));
    if (!item) {
        lua_pushnil(L);
        return 1;
    }

    uint32_t depotId = getNumber<uint32_t>(L, 3, 0);
    Player* player = g_game.getPlayerByGUID(guid);
    if (!player) {
        Player tmpPlayer(nullptr);
        if(!IOLoginData::loadPlayerById(&tmpPlayer, guid)) {
            lua_pushnil(L);
            return 1;
        }
        DepotChest* depotChest = (&tmpPlayer)->getDepotChest(depotId, true);
        pushBoolean(L, g_game.internalAddItem(depotChest, item) == RETURNVALUE_NOERROR);
        IOLoginData::savePlayer(&tmpPlayer);
    } else {
        DepotChest* depotChest = player->getDepotChest(depotId, true);
        pushBoolean(L, g_game.internalAddItem(depotChest, item) == RETURNVALUE_NOERROR);
    }

    return 1;
}

I want to know whats wrong and what i have to do to make it work.
 
Solution
Tested both functions internalMoveItem and internalAddItem, but did not work.

Anyway i just solved my problem doing this:
C++:
bool IOLoginData::sendPlayerDepotItem(Player* player, uint32_t depotId, Item* sendItem) {
    if (depotId >= 100) {
        return false;
    }

    ItemBlockList itemList;
    PropWriteStream propWriteStream;

    Database* db = Database::getInstance();
    std::ostringstream query;

    query << "DELETE FROM `player_depotitems` WHERE `player_id` = " << player->getGUID();
    db->executeQuery(query.str());

    DBInsert depotQuery("INSERT INTO `player_depotitems` (`player_id`, `pid`, `sid`, `itemtype`, `count`, `attributes`) VALUES ");

    bool added = false;
    for (const auto& it ...
Hello.
I'm trying to make a function that send the item to the player depot, even if he are not online.

Thats the function that i created. Its only working if the player is online.
C++:
int LuaScriptInterface::luaSendPlayerDepotItem(lua_State* L)
{
    //sendPlayerDepotItem(guid, item[, depotId = 0])
    uint32_t guid = getNumber<uint32_t>(L, 1);
    Item* item = getScriptEnv()->getItemByUID(getNumber<uint32_t>(L, 2));
    if (!item) {
        lua_pushnil(L);
        return 1;
    }

    uint32_t depotId = getNumber<uint32_t>(L, 3, 0);
    Player* player = g_game.getPlayerByGUID(guid);
    if (!player) {
        Player tmpPlayer(nullptr);
        if(!IOLoginData::loadPlayerById(&tmpPlayer, guid)) {
            lua_pushnil(L);
            return 1;
        }
        DepotChest* depotChest = (&tmpPlayer)->getDepotChest(depotId, true);
        pushBoolean(L, g_game.internalAddItem(depotChest, item) == RETURNVALUE_NOERROR);
        IOLoginData::savePlayer(&tmpPlayer);
    } else {
        DepotChest* depotChest = player->getDepotChest(depotId, true);
        pushBoolean(L, g_game.internalAddItem(depotChest, item) == RETURNVALUE_NOERROR);
    }

    return 1;
}

I want to know whats wrong and what i have to do to make it work.

Hello,

If the player is offline you need to temporary load him from database, add item to depot and save back to database. Look to Mailbox code, it looks similiar with receiving parcels.
 
Hello,

If the player is offline you need to temporary load him from database, add item to depot and save back to database. Look to Mailbox code, it looks similiar with receiving parcels.

i have tried it, but yet no success
 
This is the mailbox code, just change tmpPlayer.getInbox() to whatever you want.
C++:
bool Mailbox::sendItem(Item* item) const
{
    std::string receiver;
    if (!getReceiver(item, receiver)) {
        return false;
    }

    /**No need to continue if its still empty**/
    if (receiver.empty()) {
        return false;
    }

    Player* player = g_game.getPlayerByName(receiver);
    if (player) {
        if (g_game.internalMoveItem(item->getParent(), player->getInbox(), INDEX_WHEREEVER,
                                    item, item->getItemCount(), nullptr, FLAG_NOLIMIT) == RET_NOERROR) {
            g_game.transformItem(item, item->getID() + 1);
            player->onReceiveMail();
            return true;
        }
    } else {
        Player tmpPlayer(nullptr);
        if (!IOLoginData::loadPlayerByName(&tmpPlayer, receiver)) {
            return false;
        }

        if (g_game.internalMoveItem(item->getParent(), tmpPlayer.getInbox(), INDEX_WHEREEVER,
                                    item, item->getItemCount(), nullptr, FLAG_NOLIMIT) == RET_NOERROR) {
            g_game.transformItem(item, item->getID() + 1);
            IOLoginData::savePlayer(&tmpPlayer);
            return true;
        }
    }
    return false;
}
 
Tested both functions internalMoveItem and internalAddItem, but did not work.

Anyway i just solved my problem doing this:
C++:
bool IOLoginData::sendPlayerDepotItem(Player* player, uint32_t depotId, Item* sendItem) {
    if (depotId >= 100) {
        return false;
    }

    ItemBlockList itemList;
    PropWriteStream propWriteStream;

    Database* db = Database::getInstance();
    std::ostringstream query;

    query << "DELETE FROM `player_depotitems` WHERE `player_id` = " << player->getGUID();
    db->executeQuery(query.str());

    DBInsert depotQuery("INSERT INTO `player_depotitems` (`player_id`, `pid`, `sid`, `itemtype`, `count`, `attributes`) VALUES ");

    bool added = false;
    for (const auto& it : player->depotChests) {
        if (it.first == depotId) {
            itemList.emplace_back(it.first, sendItem);
            added = true;
        }
        DepotChest* depotChest = it.second;
        for (Item* item : depotChest->getItemList()) {
            itemList.emplace_back(it.first, item);
        }
    }

    if (!added) {
        itemList.emplace_back(depotId, sendItem);
    }

    if (!saveItems(player, itemList, depotQuery, propWriteStream)) {
        return false;
    }

    return true;
}
I don't know if its the best way, but at least its working.

Thanks for you help.
 
Solution
Tested both functions internalMoveItem and internalAddItem, but did not work.

Anyway i just solved my problem doing this:
C++:
bool IOLoginData::sendPlayerDepotItem(Player* player, uint32_t depotId, Item* sendItem) {
    if (depotId >= 100) {
        return false;
    }

    ItemBlockList itemList;
    PropWriteStream propWriteStream;

    Database* db = Database::getInstance();
    std::ostringstream query;

    query << "DELETE FROM `player_depotitems` WHERE `player_id` = " << player->getGUID();
    db->executeQuery(query.str());

    DBInsert depotQuery("INSERT INTO `player_depotitems` (`player_id`, `pid`, `sid`, `itemtype`, `count`, `attributes`) VALUES ");

    bool added = false;
    for (const auto& it : player->depotChests) {
        if (it.first == depotId) {
            itemList.emplace_back(it.first, sendItem);
            added = true;
        }
        DepotChest* depotChest = it.second;
        for (Item* item : depotChest->getItemList()) {
            itemList.emplace_back(it.first, item);
        }
    }

    if (!added) {
        itemList.emplace_back(depotId, sendItem);
    }

    if (!saveItems(player, itemList, depotQuery, propWriteStream)) {
        return false;
    }

    return true;
}
I don't know if its the best way, but at least its working.

Thanks for you help.



have example for use? i like your function. what version tfs is?
 
have example for use? i like your function. what version tfs is?
This?
C++:
int LuaScriptInterface::luaSendPlayerDepotItem(lua_State* L)
{
    //sendPlayerDepotItem(guid, item[, depotId = 0])
    uint32_t guid = getNumber<uint32_t>(L, 1);
    Item* item = getUserdata<Item>(L, 2);
    if (!item) {
        reportErrorFunc(getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND));
        pushBoolean(L, false);
        return 1;
    }

    if (item->getParent() != VirtualCylinder::virtualCylinder) {
        reportErrorFunc("Item already has a parent");
        pushBoolean(L, false);
        return 1;
    }

    Player* player = g_game.getPlayerByGUID(guid);
    uint32_t depotId = getNumber<uint32_t>(L, 3, 0);
    if (!player) {
        Player tmpPlayer(nullptr);
        if(!IOLoginData::loadPlayerById(&tmpPlayer, guid)) {
            reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND));
            pushBoolean(L, false);
            return 1;
        }

        if (IOLoginData::sendPlayerDepotItem(&tmpPlayer, depotId, item)) {
            ScriptEnvironment::removeTempItem(item);
            pushBoolean(L, true);
        } else {
            pushBoolean(L, false);
        }
    } else {
        DepotChest* depotChest = player->getDepotChest(depotId, true);
        ReturnValue ret = g_game.internalAddItem(depotChest, item, INDEX_WHEREEVER, FLAG_NOLIMIT);
        if (ret == RETURNVALUE_NOERROR) {
            ScriptEnvironment::removeTempItem(item);
        }
        pushBoolean(L, ret == RETURNVALUE_NOERROR);
    }

    return 1;
}

TFS 1.2
 
Could anyone explain how to make it work with mailbox.cpp? I managed to remove inbox and make parcels/letters/house items reach depot, but only if player is online, otherwise they are gone (table player_inboxitems remains empty).
 
Back
Top