• 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!

UPDATE TO 10.97 TFS

There are more bytes in the store. In store history you need to change. I use store in c++ but I hope you can edit in lua too.
Code:
msg.add<uint16_t>(page);
msg.AddByte((storeHistory.size() > entriesPerPage) ? 0x01 : 0x00);
to
msg.add<uint32_t>(page);
msg.add<uint32_t>((storeHistory.size() > entriesPerPage) ? 0x01 : 0x00);

and

msg.add<uint32_t>(offer.getPrice());
to
msg.add<uint32_t>(offer.getPrice());
msg.AddByte(0);
 
There are more bytes in the store. In store history you need to change. I use store in c++ but I hope you can edit in lua too.
Code:
msg.add<uint16_t>(page);
msg.AddByte((storeHistory.size() > entriesPerPage) ? 0x01 : 0x00);
to
msg.add<uint32_t>(page);
msg.add<uint32_t>((storeHistory.size() > entriesPerPage) ? 0x01 : 0x00);

and

msg.add<uint32_t>(offer.getPrice());
to
msg.add<uint32_t>(offer.getPrice());
msg.AddByte(0);
yo bro, you know what byte use to show the "orange" offers? the new status ? I use the c++ too... but I did not find this :mad:
 
yo bro, you know what byte use to show the "orange" offers? the new status ? I use the c++ too... but I did not find this :mad:
Yes there is new message type for that I will post later cuz I am not on my working PC now.

@silveralol
Actually you can use the bytes I described upper.
Code:
msg.add<uint32_t>(offer.getPrice());
to
msg.add<uint32_t>(offer.getPrice());
msg.AddByte(0x01);
msg.AddByte(time(nullptr) + 3600); // time where offer expires
msg.add<uint32_t>(offer.getPrice() + 10) // base price for offer

You need to edit it to fit your needs.
 
Last edited by a moderator:
There are more bytes in the store. In store history you need to change. I use store in c++ but I hope you can edit in lua too.
Code:
msg.add<uint16_t>(page);
msg.AddByte((storeHistory.size() > entriesPerPage) ? 0x01 : 0x00);
to
msg.add<uint32_t>(page);
msg.add<uint32_t>((storeHistory.size() > entriesPerPage) ? 0x01 : 0x00);

and

msg.add<uint32_t>(offer.getPrice());
to
msg.add<uint32_t>(offer.getPrice());
msg.AddByte(0);
Also one question from me. How do u find these changes ?
 
@gunz

Code:
void ProtocolGame::sendStoreOffers(StoreCategory& category)
{
    NetworkMessage msg;
    msg.addByte(0xFC);

    msg.addString(category.getName());
    
    msg.add<uint16_t>(category.getOffers().size());
    for (auto& offer : category.getOffers()) {
        msg.add<uint32_t>(offer.getId());
        msg.addString(offer.getName());
        msg.addString(offer.getDescription());

        msg.add<uint32_t>(offer.getPrice());
        msg.addByte(offer.getState());
        msg.addByte(!g_store->executeOnRender(player, &offer));

        msg.addByte(offer.getIcons().size());
        for (const auto& icon : offer.getIcons()) {
            msg.addString(icon);
        }

        msg.add<uint16_t>(offer.getSubOffers().size());
        for (auto& subOffer : offer.getSubOffers()) {
            msg.addString(subOffer.getName());
            msg.addString(subOffer.getDescription());

            msg.addByte(subOffer.getIcons().size());
            for (const auto& icon : subOffer.getIcons()) {
                msg.addString(icon);
            }

            msg.addString(subOffer.getParent()); //serviceType
        }
    }

    writeToOutputBuffer(msg);
}
 
@gunz

Code:
void ProtocolGame::sendStoreOffers(StoreCategory& category)
{
    NetworkMessage msg;
    msg.addByte(0xFC);

    msg.addString(category.getName());
   
    msg.add<uint16_t>(category.getOffers().size());
    for (auto& offer : category.getOffers()) {
        msg.add<uint32_t>(offer.getId());
        msg.addString(offer.getName());
        msg.addString(offer.getDescription());

        msg.add<uint32_t>(offer.getPrice());
        msg.addByte(offer.getState());
        msg.addByte(!g_store->executeOnRender(player, &offer));

        msg.addByte(offer.getIcons().size());
        for (const auto& icon : offer.getIcons()) {
            msg.addString(icon);
        }

        msg.add<uint16_t>(offer.getSubOffers().size());
        for (auto& subOffer : offer.getSubOffers()) {
            msg.addString(subOffer.getName());
            msg.addString(subOffer.getDescription());

            msg.addByte(subOffer.getIcons().size());
            for (const auto& icon : subOffer.getIcons()) {
                msg.addString(icon);
            }

            msg.addString(subOffer.getParent()); //serviceType
        }
    }

    writeToOutputBuffer(msg);
}

I dont see you implemented new changes. Im on phone now so I cant help you
 
@gunz
Oh you need with ur changes (I tested with ur changes)

Code:
void ProtocolGame::sendStoreOffers(StoreCategory& category)
{
    NetworkMessage msg;
    msg.addByte(0xFC);

    msg.addString(category.getName());
    
    msg.add<uint16_t>(category.getOffers().size());
    for (auto& offer : category.getOffers()) {
        msg.add<uint32_t>(offer.getId());
        msg.addString(offer.getName());
        msg.addString(offer.getDescription());

        msg.add<uint32_t>(offer.getPrice());
        
        msg.addByte(0);
        msg.addByte(offer.getState());
        msg.addByte(!g_store->executeOnRender(player, &offer));

        msg.addByte(offer.getIcons().size());
        for (const auto& icon : offer.getIcons()) {
            msg.addString(icon);
        }

        msg.add<uint16_t>(offer.getSubOffers().size());
        for (auto& subOffer : offer.getSubOffers()) {
            msg.addString(subOffer.getName());
            msg.addString(subOffer.getDescription());

            msg.addByte(subOffer.getIcons().size());
            for (const auto& icon : subOffer.getIcons()) {
                msg.addString(icon);
            }

            msg.addString(subOffer.getParent()); //serviceType
        }
    }

    writeToOutputBuffer(msg);
}
 
@gunz please man I think ur store is equal look:

Code:
void ProtocolGame::parseStoreOpen()
{
    return sendStore();
}

void ProtocolGame::parseStoreSelectCategory(NetworkMessage& msg)
{
    std::string categoryName = msg.getString();

    for (auto& category : g_store->getCategories()) {
        if (category.getName() == categoryName) {
            return g_dispatcher.addTask(createTask(std::bind(&ProtocolGame::sendStoreOffers, getThis(), category)));
        }
    }   
}

void ProtocolGame::parseStoreBuyOffer(NetworkMessage& msg)
{
    uint32_t offerId = msg.get<uint32_t>();
    StoreOfferType_t offerType = static_cast<StoreOfferType_t>(msg.getByte());
    std::string param;
    
    if (offerType == STORE_OFFERTYPE_NAMECHANGE) {
        param = msg.getString();
    }

    auto offer = g_store->getOfferById(offerId);
    if (!offer) {
        sendStoreError(STORE_ERROR_PURCHASE, "Offer not found. Please reopen the store and try again.");
        return;
    }

    if ((strcasecmp(offer->getName().c_str(), "name change") == 0) && offerType != STORE_OFFERTYPE_NAMECHANGE) {
        requestPurchaseData(offerId, STORE_OFFERTYPE_NAMECHANGE);
        return;
    }

    addGameTask(&Game::playerPurchaseStoreOffer, player->getID(), offerId, param);   
}   

void ProtocolGame::parseStoreOpenHistory(NetworkMessage& msg)
{
    storeHistoryEntriesPerPage = msg.getByte();

    g_dispatcher.addTask(createTask(std::bind(&ProtocolGame::sendStoreHistory, getThis(), 0, storeHistoryEntriesPerPage)));
}

void ProtocolGame::parseStoreRequestHistory(NetworkMessage& msg)
{
    uint16_t page = msg.get<uint16_t>();

    g_dispatcher.addTask(createTask(std::bind(&ProtocolGame::sendStoreHistory, getThis(), page, storeHistoryEntriesPerPage)));
}

void ProtocolGame::parseTransferCoins(NetworkMessage& msg)
{
    std::string recipient = msg.getString();
    uint16_t amount = msg.get<uint16_t>();

    addGameTask(&Game::playerTransferCoins, player->getID(), recipient, amount);
}

void ProtocolGame::sendStoreError(StoreError_t errorType, const std::string& message)
{
    NetworkMessage msg;
    msg.addByte(0xE0);

    msg.addByte(errorType);
    msg.addString(message);

    writeToOutputBuffer(msg);
}

void ProtocolGame::requestPurchaseData(uint32_t offerId, StoreOfferType_t offerType)
{
    NetworkMessage msg;
    msg.addByte(0xE1);

    msg.add<uint32_t>(offerId);
    msg.addByte(offerType);

    writeToOutputBuffer(msg);
}

void ProtocolGame::sendCoinBalance()
{
    NetworkMessage msg;
    msg.addByte(0xF2);
    msg.addByte(0x01);

    msg.addByte(0xDF);
    msg.addByte(0x01);

    msg.add<uint32_t>(player->coinBalance); //total coins
    msg.add<uint32_t>(player->coinBalance); //transferable coins

    writeToOutputBuffer(msg);
}

void ProtocolGame::updateCoinBalance()
{
    NetworkMessage msg;
    msg.addByte(0xF2);
    msg.addByte(0x00);

    writeToOutputBuffer(msg);

    g_dispatcher.addTask(
        createTask(std::bind([](ProtocolGame_ptr client) {
            auto coinBalance = IOAccount::getCoinBalance(client->player->getAccount());
            client->player->coinBalance = coinBalance;

            client->sendCoinBalance();
        }, getThis()))
    );
}

void ProtocolGame::sendStore()
{
    NetworkMessage msg;
    msg.addByte(0xFB);

    msg.addByte(0x00);
    //msg.add<uint32_t>(player->coinBalance);
    //msg.add<uint32_t>(player->coinBalance);

    msg.add<uint16_t>(g_store->getCategories().size());
    for (auto& category : g_store->getCategories()) {
        msg.addString(category.getName());
        msg.addString(category.getDescription());

        msg.addByte(category.getIcons().size());
        for (const auto& icon : category.getIcons()) {
            msg.addString(icon);
        }

        msg.addString(category.getParent());
    }   

    writeToOutputBuffer(msg);   

    updateCoinBalance();
}

void ProtocolGame::sendStoreOffers(StoreCategory& category)
{
    NetworkMessage msg;
    msg.addByte(0xFC);

    msg.addString(category.getName());
    
    msg.add<uint16_t>(category.getOffers().size());
    for (auto& offer : category.getOffers()) {
        msg.add<uint32_t>(offer.getId());
        msg.addString(offer.getName());
        msg.addString(offer.getDescription());

        msg.add<uint32_t>(offer.getPrice());
        msg.AddByte(0x01);
        msg.AddByte(time(nullptr) + 3600); // time where offer expires
        msg.add<uint32_t>(offer.getPrice() + 10) // base price for offer
        msg.AddByte(0);
        msg.addByte(offer.getState());
        msg.addByte(!g_store->executeOnRender(player, &offer));

        msg.addByte(offer.getIcons().size());
        for (const auto& icon : offer.getIcons()) {
            msg.addString(icon);
        }

        msg.add<uint16_t>(offer.getSubOffers().size());
        for (auto& subOffer : offer.getSubOffers()) {
            msg.addString(subOffer.getName());
            msg.addString(subOffer.getDescription());

            msg.addByte(subOffer.getIcons().size());
            for (const auto& icon : subOffer.getIcons()) {
                msg.addString(icon);
            }

            msg.addString(subOffer.getParent()); //serviceType
        }
    }

    writeToOutputBuffer(msg);
}

void ProtocolGame::sendStoreHistory(uint16_t page, uint32_t entriesPerPage)
{
    // dispatcher thread
    std::vector<StoreTransaction> storeHistory;
    g_store->getTransactionHistory(player->getAccount(), page, entriesPerPage, storeHistory);

    if (storeHistory.size() == 0) {
        return sendStoreError(STORE_ERROR_HISTORY, "No entries yet.");
    }

    NetworkMessage msg;
    msg.addByte(0xFD);

    msg.add<uint32_t>(page);
    msg.add<uint32_t>((storeHistory.size() > entriesPerPage) ? 0x01 : 0x00);

    uint8_t entries = std::min<uint8_t>(entriesPerPage, static_cast<uint32_t>(storeHistory.size()));
    msg.addByte(entries);
    size_t count = 0;
    for (const auto& entry : storeHistory) {
        if (count++ == entriesPerPage) {
            break;
        }

        msg.add<uint32_t>(entry.timestamp);
        msg.addByte(0x00); // product type
        msg.add<int32_t>(entry.coins);
        msg.addString(entry.description);
    }

    writeToOutputBuffer(msg);
}
 
@gunz please man I think ur store is equal look:

Code:
void ProtocolGame::parseStoreOpen()
{
    return sendStore();
}

void ProtocolGame::parseStoreSelectCategory(NetworkMessage& msg)
{
    std::string categoryName = msg.getString();

    for (auto& category : g_store->getCategories()) {
        if (category.getName() == categoryName) {
            return g_dispatcher.addTask(createTask(std::bind(&ProtocolGame::sendStoreOffers, getThis(), category)));
        }
    } 
}

void ProtocolGame::parseStoreBuyOffer(NetworkMessage& msg)
{
    uint32_t offerId = msg.get<uint32_t>();
    StoreOfferType_t offerType = static_cast<StoreOfferType_t>(msg.getByte());
    std::string param;
  
    if (offerType == STORE_OFFERTYPE_NAMECHANGE) {
        param = msg.getString();
    }

    auto offer = g_store->getOfferById(offerId);
    if (!offer) {
        sendStoreError(STORE_ERROR_PURCHASE, "Offer not found. Please reopen the store and try again.");
        return;
    }

    if ((strcasecmp(offer->getName().c_str(), "name change") == 0) && offerType != STORE_OFFERTYPE_NAMECHANGE) {
        requestPurchaseData(offerId, STORE_OFFERTYPE_NAMECHANGE);
        return;
    }

    addGameTask(&Game::playerPurchaseStoreOffer, player->getID(), offerId, param); 
} 

void ProtocolGame::parseStoreOpenHistory(NetworkMessage& msg)
{
    storeHistoryEntriesPerPage = msg.getByte();

    g_dispatcher.addTask(createTask(std::bind(&ProtocolGame::sendStoreHistory, getThis(), 0, storeHistoryEntriesPerPage)));
}

void ProtocolGame::parseStoreRequestHistory(NetworkMessage& msg)
{
    uint16_t page = msg.get<uint16_t>();

    g_dispatcher.addTask(createTask(std::bind(&ProtocolGame::sendStoreHistory, getThis(), page, storeHistoryEntriesPerPage)));
}

void ProtocolGame::parseTransferCoins(NetworkMessage& msg)
{
    std::string recipient = msg.getString();
    uint16_t amount = msg.get<uint16_t>();

    addGameTask(&Game::playerTransferCoins, player->getID(), recipient, amount);
}

void ProtocolGame::sendStoreError(StoreError_t errorType, const std::string& message)
{
    NetworkMessage msg;
    msg.addByte(0xE0);

    msg.addByte(errorType);
    msg.addString(message);

    writeToOutputBuffer(msg);
}

void ProtocolGame::requestPurchaseData(uint32_t offerId, StoreOfferType_t offerType)
{
    NetworkMessage msg;
    msg.addByte(0xE1);

    msg.add<uint32_t>(offerId);
    msg.addByte(offerType);

    writeToOutputBuffer(msg);
}

void ProtocolGame::sendCoinBalance()
{
    NetworkMessage msg;
    msg.addByte(0xF2);
    msg.addByte(0x01);

    msg.addByte(0xDF);
    msg.addByte(0x01);

    msg.add<uint32_t>(player->coinBalance); //total coins
    msg.add<uint32_t>(player->coinBalance); //transferable coins

    writeToOutputBuffer(msg);
}

void ProtocolGame::updateCoinBalance()
{
    NetworkMessage msg;
    msg.addByte(0xF2);
    msg.addByte(0x00);

    writeToOutputBuffer(msg);

    g_dispatcher.addTask(
        createTask(std::bind([](ProtocolGame_ptr client) {
            auto coinBalance = IOAccount::getCoinBalance(client->player->getAccount());
            client->player->coinBalance = coinBalance;

            client->sendCoinBalance();
        }, getThis()))
    );
}

void ProtocolGame::sendStore()
{
    NetworkMessage msg;
    msg.addByte(0xFB);

    msg.addByte(0x00);
    //msg.add<uint32_t>(player->coinBalance);
    //msg.add<uint32_t>(player->coinBalance);

    msg.add<uint16_t>(g_store->getCategories().size());
    for (auto& category : g_store->getCategories()) {
        msg.addString(category.getName());
        msg.addString(category.getDescription());

        msg.addByte(category.getIcons().size());
        for (const auto& icon : category.getIcons()) {
            msg.addString(icon);
        }

        msg.addString(category.getParent());
    } 

    writeToOutputBuffer(msg); 

    updateCoinBalance();
}

void ProtocolGame::sendStoreOffers(StoreCategory& category)
{
    NetworkMessage msg;
    msg.addByte(0xFC);

    msg.addString(category.getName());
  
    msg.add<uint16_t>(category.getOffers().size());
    for (auto& offer : category.getOffers()) {
        msg.add<uint32_t>(offer.getId());
        msg.addString(offer.getName());
        msg.addString(offer.getDescription());

        msg.add<uint32_t>(offer.getPrice());
        msg.AddByte(0x01);
        msg.AddByte(time(nullptr) + 3600); // time where offer expires
        msg.add<uint32_t>(offer.getPrice() + 10) // base price for offer
        msg.AddByte(0);
        msg.addByte(offer.getState());
        msg.addByte(!g_store->executeOnRender(player, &offer));

        msg.addByte(offer.getIcons().size());
        for (const auto& icon : offer.getIcons()) {
            msg.addString(icon);
        }

        msg.add<uint16_t>(offer.getSubOffers().size());
        for (auto& subOffer : offer.getSubOffers()) {
            msg.addString(subOffer.getName());
            msg.addString(subOffer.getDescription());

            msg.addByte(subOffer.getIcons().size());
            for (const auto& icon : subOffer.getIcons()) {
                msg.addString(icon);
            }

            msg.addString(subOffer.getParent()); //serviceType
        }
    }

    writeToOutputBuffer(msg);
}

void ProtocolGame::sendStoreHistory(uint16_t page, uint32_t entriesPerPage)
{
    // dispatcher thread
    std::vector<StoreTransaction> storeHistory;
    g_store->getTransactionHistory(player->getAccount(), page, entriesPerPage, storeHistory);

    if (storeHistory.size() == 0) {
        return sendStoreError(STORE_ERROR_HISTORY, "No entries yet.");
    }

    NetworkMessage msg;
    msg.addByte(0xFD);

    msg.add<uint32_t>(page);
    msg.add<uint32_t>((storeHistory.size() > entriesPerPage) ? 0x01 : 0x00);

    uint8_t entries = std::min<uint8_t>(entriesPerPage, static_cast<uint32_t>(storeHistory.size()));
    msg.addByte(entries);
    size_t count = 0;
    for (const auto& entry : storeHistory) {
        if (count++ == entriesPerPage) {
            break;
        }

        msg.add<uint32_t>(entry.timestamp);
        msg.addByte(0x00); // product type
        msg.add<int32_t>(entry.coins);
        msg.addString(entry.description);
    }

    writeToOutputBuffer(msg);
}

remove those 3 lines and it should work
Code:
       msg.AddByte(0x01);
        msg.AddByte(time(nullptr) + 3600); // time where offer expires
        msg.add<uint32_t>(offer.getPrice() + 10) // base price for offer
 
remove those 3 lines and it should work
Code:
       msg.AddByte(0x01);
        msg.AddByte(time(nullptr) + 3600); // time where offer expires
        msg.add<uint32_t>(offer.getPrice() + 10) // base price for offer

thanks, but I still got debbugs :(

HEy2htp.png


any other idea ? how is ur store code in protocolgame
 
Back
Top