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

TFS 1.2 Market Crash

@Tbol
TFS 1.2 Market Crash
What server do you use? otservbr-global based on TFS 1.2? Canary?

In TFS 1.2 Game::playerCancelMarketOffer is processed 100% in C++:
and there is no CreatureEvents::marketEnter event that starts some Lua script in CreatureEvents::marketEnter in:

Did you server crash itself or it frozen and you had to kill process to make it restart?

There is report from Canary about ContainerIterator::advance going into infinite loop/crash and fix for that:
 
@Tbol
TFS 1.2 Market Crash
What server do you use? otservbr-global based on TFS 1.2? Canary?

In TFS 1.2 Game::playerCancelMarketOffer is processed 100% in C++:
and there is no CreatureEvents::marketEnter event that starts some Lua script in CreatureEvents::marketEnter in:

Did you server crash itself or it frozen and you had to kill process to make it restart?

There is report from Canary about ContainerIterator::advance going into infinite loop/crash and fix for that:
I use a really old one - GitHub - dbjorkholm/forgottenserver at 8.6 (https://github.com/dbjorkholm/forgottenserver/tree/8.6)

creaturevent.cpp
C++:
bool CreatureEvents::marketEnter(Player* player, Item* item, std::string tooltip) const
{
    //fire global event if is registered
    for (const auto& it : creatureEvents) {
        if (it.second->getEventType() == CREATURE_EVENT_MARKET_ENTER) {
            if (!it.second->executeMarketEnter(player, item, tooltip)) {
                return false;
            }
        }
    }
    return true;
}

C++:
void Game::playerCancelMarketOffer(uint32_t playerId, uint32_t timestamp, uint16_t counter)
{
    Player* player = getPlayerByID(playerId);
    if (!player) {
        return;
    }

//    if (!player->isInMarket()) {
//        return;
    //}

    MarketOfferEx offer = IOMarket::getOfferByCounter(timestamp, counter);
    if (offer.id == 0 || offer.playerId != player->getGUID()) {
        return;
    }

    if (offer.type == MARKETACTION_BUY) {
        if (offer.premium_points){
            IOLoginData::changePremiumPoints(player->getAccount(), static_cast<uint64_t>(offer.price) * offer.amount);
        } else {
            player->bankBalance += static_cast<uint64_t>(offer.price) * offer.amount;
        }
        g_creatureEvents->marketEnter(player);
    } else {
        const ItemType& it = Item::items[offer.itemId];
        if (it.id == 0) {
            return;
        }

        if (it.stackable) {
            uint16_t tmpAmount = offer.amount;
            while (tmpAmount > 0) {
                int32_t stackCount = std::min<int32_t>(100, tmpAmount);
                Item* item = Item::CreateItem(it.id, stackCount);
                if (internalAddItem(player->getInbox(), item, INDEX_WHEREEVER, FLAG_NOLIMIT) != RETURNVALUE_NOERROR) {
                    delete item;
                    break;
                }

                tmpAmount -= stackCount;
            }
        } else {
            int32_t subType;
            if (it.charges != 0) {
                subType = it.charges;
            } else {
                subType = -1;
            }

            for (uint16_t i = 0; i < offer.amount; ++i) {
                Item* item = Item::CreateItem(it.id, subType);
                g_creatureEvents->marketEdit(item, offer.tooltip_compare);
                if (internalAddItem(player->getInbox(), item, INDEX_WHEREEVER, FLAG_NOLIMIT) != RETURNVALUE_NOERROR) {
                    delete item;
                    break;
                }
            }
        }
    }

    IOMarket::moveOfferToHistory(offer.id, OFFERSTATE_CANCELLED);
    offer.amount = 0;
    offer.timestamp += g_config.getNumber(ConfigManager::MARKET_OFFER_DURATION);
    player->sendMarketCancelOffer(offer);
    g_creatureEvents->marketEnter(player);
}

It crashed itself
 
There is no market on branch 8.6 and on master branch there is TFS 1.2 market, which is 100% in C++.
You got some custom code for market in Lua that is called from CreatureEvents::marketEnter.
We can't help you, if we can't view your code.
It is custom otcv8 related market system. Maybe this in creaturescript
LUA:
function table_eq(table1, table2)
   local avoid_loops = {}
   local function recurse(t1, t2)
      -- compare value types
      if type(t1) ~= type(t2) then return false end
      -- Base case: compare simple values
      if type(t1) ~= "table" then return t1 == t2 end
      -- Now, on to tables.
      -- First, let's avoid looping forever.
      if avoid_loops[t1] then return avoid_loops[t1] == t2 end
      avoid_loops[t1] = t2
      -- Copy keys from t2
      local t2keys = {}
      local t2tablekeys = {}
      for k, _ in pairs(t2) do
         if type(k) == "table" then table.insert(t2tablekeys, k) end
         t2keys[k] = true
      end
      -- Let's iterate keys from t1
      for k1, v1 in pairs(t1) do
         local v2 = t2[k1]
         if type(k1) == "table" then
            -- if key is a table, we need to find an equivalent one.
            local ok = false
            for i, tk in ipairs(t2tablekeys) do
               if table_eq(k1, tk) and recurse(v1, t2[tk]) then
                  table.remove(t2tablekeys, i)
                  t2keys[tk] = nil
                  ok = true
                  break
               end
            end
            if not ok then return false end
         else
            -- t1 has a key which t2 doesn't have, fail.
            if v2 == nil then return false end
            t2keys[k1] = nil
            if not recurse(v1, v2) then return false end
         end
      end
      -- if t2 has a key which t1 doesn't have, fail.
      if next(t2keys) then return false end
      return true
   end
   return recurse(table1, table2)
end


local sellableI = 0

function marketEdit(itemCheck, tooltipCheck)
    if itemCheck and itemCheck ~= nil then
        local getTooltip = json.decode(tooltipCheck)
        itemCheck:setCustomAttribute("upgradeLevel", getTooltip.itemLevel)
        for i,child in pairs(getTooltip.attr) do
            if child[2] > 0 then
                for _i, _child in pairs(nameAttributes) do
                    if _child[2] == i then
                        itemCheck:setCustomAttribute(_i, child[2])
                    end
                end
            end
        end
    end
end

local availableItems
function marketEnter(player, itemCheck, tooltipCheck)

    if itemCheck and itemCheck ~= nil then
   
        if table_eq(itemCheck:buildTooltip(json.decode(tooltipCheck).uid), json.decode(tooltipCheck)) then
            return true
        else
            return false
        end
       
    else
   
        local sellableItems = {}
        local getDepot = player:getDepotChest(1)
        local getContainer = player:getSlotItem(CONST_SLOT_BACKPACK)
       
        if not availableItems then
            availableItems = {}
            for i = 100,30000 do
                local itemType = ItemType(i)
                if itemType and itemType:isPickupable() then
                    table.insert(availableItems,itemType:buildTooltip(8999999+i))
                end
            end
        end
       
        if getDepot then
            for i,child in pairs(getDepot:getItems(true)) do
                sellableI = sellableI + 1
                local itemType = ItemType(child:getId())
                if itemType then
                    if table_eq(itemType:buildTooltip(9999999+sellableI),child:buildTooltip(9999999+sellableI)) then
                        sellableItems[tostring(itemType:getClientId())] = (sellableItems[tostring(itemType:getClientId())] or 0) + child:getCount()
                    else
                    if not sellableItems[tostring(9999999+itemType:getClientId())] then sellableItems[tostring(9999999+itemType:getClientId())] = {} end
                        table.insert(sellableItems[tostring(9999999+itemType:getClientId())], child:buildTooltip(9999999+sellableI))
                    end
                end
            end
        end
       
        if getContainer then
            for i,child in pairs(getContainer:getItems(true)) do
                sellableI = sellableI + 1
                local itemType = ItemType(child:getId())
                if itemType then
                    if table_eq(itemType:buildTooltip(9999999+sellableI),child:buildTooltip(9999999+sellableI)) then
                        sellableItems[tostring(itemType:getClientId())] = (sellableItems[tostring(itemType:getClientId())] or 0) + child:getCount()
                    else
                    if not sellableItems[tostring(9999999+itemType:getClientId())] then sellableItems[tostring(9999999+itemType:getClientId())] = {} end
                        table.insert(sellableItems[tostring(9999999+itemType:getClientId())], child:buildTooltip(9999999+sellableI))
                    end
                end
            end
        end
        if player:isUsingOtClient() then
            msg = NetworkMessage()
            msg:addByte(0xF6)
            msg:addU64(player:getBankBalance())
            msg:addU64(player:getPremiumPoints())
            msg:addByte(player:marketOfferCount())
            msg:addString(json.encode(sellableItems))
            msg:sendToPlayer(player)
            if player:getGroup():getAccess() then
                local file,err = io.open("availableItems.txt",'w')
                if file then
                    file:write(json.encode(availableItems))
                    file:close()
                else
                    print("availableItems file error:", err)
                end
            end
        else
            player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Market is available only on otclient!")
        end
    end
   
    return true
end
 
is it a sigsegv error? If so it should be that you are trying to access C++ memory that is not allocated, or accessing freed memory or an array that is out of bounds etc.
 
is it a sigsegv error? If so it should be that you are trying to access C++ memory that is not allocated, or accessing freed memory or an array that is out of bounds etc.
At the top of crash dumb yea it says Signal caught: SIGSEGV
 
Back
Top