• 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 Lua Table Type in Opcode

zxmatzx

Advanced OT User
Joined
Dec 1, 2010
Messages
312
Solutions
27
Reaction score
155
Location
Brazil
GitHub
Mateuso8
Hello,
Im using opcode to pass info from server to client, but i need to pass a table. I tryed transform the table in string(opcode only accept strings) and transform back to table in client side, but don't worked. I need change opcode to send table type variable too, i think with table i can send all others variable types. How is a C++ change, i don't know how to do, wonder to know if someone can do this for me. I think will be needed change the function that send and recive the opcode in server and client.
Im using TFS 1.2 and last OTC files.

If have another way to pass data from/to server/client i would like to know.

Thanks for all help.
 
Solution
Use a serialize function:
Lua:
function table.size(t)
    local size = 0
    for k, v in pairs(t) do
        size = size + 1
    end
    return size
end

function serialize(s)
    local isTable = type(s) == 'table'
    local ret = {(isTable and "{" or nil)}
    local function doSerialize(s)
        if isTable then
            local size = table.size(s)
            local index = 0
            for k, v in pairs(s) do
                index = index + 1
                local key = (type(k) == 'string') and '"'..k..'"' or k
                local val = (type(v) == 'string') and '"'..v..'"' or v
                local comma = ((index < size) and ', ' or '')
                if type(v) == 'table' then
                    ret[#ret+1] = ('[%s] =...
Why don't you just break down that table into separated bytes and send them? This is what you are supposed to do most of the time.
 
Use a serialize function:
Lua:
function table.size(t)
    local size = 0
    for k, v in pairs(t) do
        size = size + 1
    end
    return size
end

function serialize(s)
    local isTable = type(s) == 'table'
    local ret = {(isTable and "{" or nil)}
    local function doSerialize(s)
        if isTable then
            local size = table.size(s)
            local index = 0
            for k, v in pairs(s) do
                index = index + 1
                local key = (type(k) == 'string') and '"'..k..'"' or k
                local val = (type(v) == 'string') and '"'..v..'"' or v
                local comma = ((index < size) and ', ' or '')
                if type(v) == 'table' then
                    ret[#ret+1] = ('[%s] = {'):format(key)
                    doSerialize(v)
                    ret[#ret+1] = ('}%s'):format(comma)
                else
                    ret[#ret+1] = ('[%s] = %s%s'):format(key, val, comma)
                end
            end
        else
            ret[#ret+1] = s
        end
    end
    doSerialize(s)
    return (table.concat(ret) .. (isTable and "}" or ""))
end

function unserialize(str)
    local f = loadstring("return ".. str)
    return f and f() or nil
end

Lua:
local t = {1, 2, 3}

local serialized_t = serialize(t) -- string {1, 2, 3}

local unserialized_t = unserialize(serialized_t) -- {1, 2, 3}
 
Solution
Why don't you just break down that table into separated bytes and send them? This is what you are supposed to do most of the time.
U mean NetworkMessage right? I was reading about it, when Delusion sended this function serialize(). I definitly will learn more about it, appears to be a great feature, thanks for answer.

Use a serialize function:
Lua:
function table.size(t)
    local size = 0
    for k, v in pairs(t) do
        size = size + 1
    end
    return size
end

function serialize(s)
    local isTable = type(s) == 'table'
    local ret = {(isTable and "{" or nil)}
    local function doSerialize(s)
        if isTable then
            local size = table.size(s)
            local index = 0
            for k, v in pairs(s) do
                index = index + 1
                local key = (type(k) == 'string') and '"'..k..'"' or k
                local val = (type(v) == 'string') and '"'..v..'"' or v
                local comma = ((index < size) and ', ' or '')
                if type(v) == 'table' then
                    ret[#ret+1] = ('[%s] = {'):format(key)
                    doSerialize(v)
                    ret[#ret+1] = ('}%s'):format(comma)
                else
                    ret[#ret+1] = ('[%s] = %s%s'):format(key, val, comma)
                end
            end
        else
            ret[#ret+1] = s
        end
    end
    doSerialize(s)
    return (table.concat(ret) .. (isTable and "}" or ""))
end

function unserialize(str)
    local f = loadstring("return ".. str)
    return f and f() or nil
end

Lua:
local t = {1, 2, 3}

local serialized_t = serialize(t) -- string {1, 2, 3}

local unserialized_t = unserialize(serialized_t) -- {1, 2, 3}
Using the serialize() function i got a error with table.size(s) i don't have this function on my server, and looked up for it, but don't found too... I changed to #s if only need to get the array size. Worked, But don't was getting the , at the value end. Then i changed the line local comma = ((index < size) and ', ' or '') to local comma = ((index < size) and ', ' or ',') and worked well, i don't know if i will have some problem with the changes, but is working for now, here is the full code after i change.

Lua:
function serialize(s)
    local isTable = type(s) == 'table'
    local ret = {(isTable and "{" or nil)}
    local function doSerialize(s)
        if isTable then
            local size = #s -- from -> table.size(s)
            local index = 0
            for k, v in pairs(s) do
                index = index + 1
                local key = (type(k) == 'string') and '"'..k..'"' or k
                local val = (type(v) == 'string') and '"'..v..'"' or v
                local comma = ((index < size) and ', ' or ',') --from -> local comma = ((index < size) and ', ' or '')
                if type(v) == 'table' then
                    ret[#ret+1] = ('[%s] = {'):format(key)
                    doSerialize(v)
                    ret[#ret+1] = ('}%s'):format(comma)
                else
                    ret[#ret+1] = ('[%s] = %s%s'):format(key, val, comma)
                end
            end
        else
            ret[#ret+1] = s
        end
    end
    doSerialize(s)
    return (table.concat(ret) .. (isTable and "}" or ""))
end

If u see any problem with, please tell me. But your answer solved my problem. Really thanks.
 
U mean NetworkMessage right? I was reading about it, when Delusion sended this function serialize(). I definitly will learn more about it, appears to be a great feature, thanks for answer.


Using the serialize() function i got a error with table.size(s) i don't have this function on my server, and looked up for it, but don't found too... I changed to #s if only need to get the array size. Worked, But don't was getting the , at the value end. Then i changed the line local comma = ((index < size) and ', ' or '') to local comma = ((index < size) and ', ' or ',') and worked well, i don't know if i will have some problem with the changes, but is working for now, here is the full code after i change.

Lua:
function serialize(s)
    local isTable = type(s) == 'table'
    local ret = {(isTable and "{" or nil)}
    local function doSerialize(s)
        if isTable then
            local size = #s -- from -> table.size(s)
            local index = 0
            for k, v in pairs(s) do
                index = index + 1
                local key = (type(k) == 'string') and '"'..k..'"' or k
                local val = (type(v) == 'string') and '"'..v..'"' or v
                local comma = ((index < size) and ', ' or ',') --from -> local comma = ((index < size) and ', ' or '')
                if type(v) == 'table' then
                    ret[#ret+1] = ('[%s] = {'):format(key)
                    doSerialize(v)
                    ret[#ret+1] = ('}%s'):format(comma)
                else
                    ret[#ret+1] = ('[%s] = %s%s'):format(key, val, comma)
                end
            end
        else
            ret[#ret+1] = s
        end
    end
    doSerialize(s)
    return (table.concat(ret) .. (isTable and "}" or ""))
end

If u see any problem with, please tell me. But your answer solved my problem. Really thanks.
I edited the post almost instantly to include the table.size function, don't use #s, use table.size. You must've caught it as soon as I posted the answer.
 
Back
Top