Jump to content

[HELP] Table


iAxel

Recommended Posts

Hello everyone!

Please help with the decision

I am using a table to change the data

Table:

  
Table = { 
    need = { 
        {'Test1', 100}, 
        {'Test2', 100} 
    }, 
    stat = { 
        {'Test3', false}, 
        {'Test4', false} 
    }, 
    item = { 
        {'Test5', 0}, 
        {'Test6', 0} 
    } 
} 
  

When registering:

  
--Version 1 
for i, data in ipairs(Table.need) do 
    source:setData(data[1], data[2]) 
end 
for i, data in ipairs(Table.stat) do 
    source:setData(data[1], data[2]) 
end 
for i, data in ipairs(Table.item) do 
    source:setData(data[1], data[2]) 
end 
--Version 2 
for _, v in pairs(Table) do 
    for _, v2 in pairs(v) do 
        source:setData(v2[1], v2[2]) 
    end 
end 
  

When loading(MySQL):

  
--Version 1 
local needs = fromJSON(data[1]['needs']) 
local status = fromJSON(data[1]['status']) 
local items = fromJSON(data[1]['items']) 
for i, data in ipairs(Table.need) do 
    source:setData(data[1], needs[i]) 
end 
for i, data in ipairs(Table.stat) do 
    source:setData(data[1], status[i]) 
end 
for i, data in ipairs(Table.item) do 
    source:setData(data[1], items[i]) 
end 
--Version 2 not : ( 
  

Question - is there any other optimized version?

P.S I need an optimized version.

Link to comment

To save, I use mysql

Load player date:

  
addEvent('onLogged', true) 
function onLogged(player) 
    local serial = player:getSerial() 
    local name = player:getName() 
    local query = getDB():query('SELECT * FROM `accounts` WHERE `serial` = "'..serial..'" LIMIT 1') 
    if (query) then 
        local data = query:poll(-1) 
        local pos = fromJSON(data[1]['pos']) 
        local needs, status, items = fromJSON(data[1]['needs']), fromJSON(data[1]['status']), fromJSON(data[1]['items']) 
        player:spawn(pos[1], pos[2], pos[3]) 
        player:setHealth(data[1]['health']) 
        player:fadeCamera(true) 
        player:setCameraTarget() 
        for i, data in ipairs(Table.need) do 
            player:setData(data[1], needs[i]) 
        end 
        for i, data in ipairs(Table.stat) do 
            player:setData(data[1], stats[i]) 
        end 
        for i, data in ipairs(Table.item) do 
            player:setData(data[1], items[i]) 
        end 
    end 
end 
addEventHandler('onLogged', root, onLogged) 
  

Save player date:

  
function onSave(player) 
    local serial = player:getSerial() 
    local name = player:getName() 
    local health = player:getHealth() 
    local x, y, z = getElementPosition(player) 
    local pos = toJSON({x, y, z}) 
    local needs, status, items = {}, {}, {} 
    for i, data in ipairs(Table.need) do 
        needs[i] = player:getData(data[1]) 
    end 
    for i, data in ipairs(Table.stat) do 
        status[i] = player:getData(data[1]) 
    end 
    for i, data in ipairs(Table.item) do 
        items[i] = player:getData(data[1]) 
    end 
    player:setData('Logged', false) 
    needs, status, items = toJSON(needs), toJSON(status), toJSON(items) 
    getDB():exec('UPDATE `accounts` SET `login` = "'..name..'", `health` = "'..health..'", `pos` = "'..pos..'", `needs` = "'..needs..'", `status` = "'..status..'", `items` = "'..items..'", `lastdate` = NOW() WHERE `serial` = "'..serial..'" LIMIT 1') 
    outputDebugString('Account Name: '..name..' was saved automatically.') 
end 
  

Register player:

  
addEvent('onRegister', true) 
function onRegister(player) 
    local iRand = math.random(#spawnPos) 
    player:spawn(spawnPos[iRand][1], spawnPos[iRand][2], spawnPos[iRand][3]) 
    player:fadeCamera(true) 
    player:setCameraTarget() 
    for _, data in pairs(Table) do 
        for _, value in pairs(data) do 
            player:setData(value[1], value[2]) 
        end 
    end 
end 
addEventHandler('onRegister', root, onRegister) 
  

I need an optimized version of the data load

Link to comment

Himself solved the problem

  
for k, v in pairs(Table) do 
    for i, data in pairs(v) do 
        if (k == 'need') then 
            player:setData(data[1], needs[i]) 
        elseif (k == 'stat') then 
            player:setData(data[1], status[i]) 
        elseif (k == 'item') then 
            player:setData(data[1], items[i]) 
        end 
    end 
end 
  

The next question is - It's not like will not affect the performance?

P.S Answer at least this time ...

Link to comment
  • Moderators
The next question is - It's not like will not affect the performance?

Just make sure you don't access the database too much, or your server might crash.

Of course you can loop through all the players and store the data when you shut down the server.

It will peak your cpu usage, but it must not be constantly like that.

Link to comment

Just make sure you don't access the database too much, or your server might crash.

Of course you can loop through all the players and store the data when you shut down the server.

It will peak your cpu usage, but it must not be constantly like that.

Thank you so much, but all the same table used in the loop is not effective? And can a couple of examples of optimization

Link to comment
  • Moderators

Looping through a table which uses custom indexes(something else then numbers) isn't very efficient, but sometimes you have to. I am more worried about the functions(especially database functions) than the loops you are using.

When I take a look at your examples, I assume example 2 is more efficient then example 1.

Because when you start a loop, the code inside it will be temporary saved in to the ram, which will speed up when the loop executed more then one time.

Link to comment

When I take a look at your examples, I assume example 2 is more efficient then example 1.

Because when you start a loop, the code inside it will be temporary saved in to the ram, which will speed up when the loop executed more then one time.

Variant 1

  
for i, data in ipairs(Table.need) do 
    source:setData(data[1], data[2]) 
end 
for i, data in ipairs(Table.stat) do 
    source:setData(data[1], data[2]) 
end 
for i, data in ipairs(Table.item) do 
    source:setData(data[1], data[2]) 
end 
  

Variant 2

  
for _, v in pairs(Table) do 
    for _, v2 in pairs(v) do 
        source:setData(v2[1], v2[2]) 
    end 
end 
  

2 variant mean effective than 1?

Looping through a table which uses custom indexes(something else then numbers) isn't very efficient, but sometimes you have to. I am more worried about the functions(especially database functions) than the loops you are using.

I did not understand, but if you talk about the connection to the database or save data

  
local connect = nil 
local db = { 
    type = 'mysql', 
    base = 'mta', 
    host = '127.0.0.1', 
    name = 'root', 
    pass = '' 
} 
-- 
function getDB() 
    if (not reconnect) then 
        return connect 
    else 
        Timer(getDB, 150, 1) 
    end 
end 
-- 
addEventHandler('onResourceStart', resourceRoot, 
    function () 
        connect = Connection(db.type, 'dbname='..db.base..';host='..db.host, db.name, db.pass) 
        if (not connect) then 
            outputServerLog('MySQL connection is not established!') 
        else 
            outputServerLog('MySQL connection is established!') 
        end 
    end 
) 
-- 
addEventHandler('onResourceStop', resourceRoot, 
    function () 
        for i, player in ipairs(getElementsByType('player')) do 
            if (isLogged(player)) then 
                onSave(player) 
            end 
        end 
        for i, vehicle in ipairs(getElementsByType('vehicle')) do 
            if (isVehicle(vehicle)) then 
                onVehSave(vehicle) 
            end 
        end 
        if (isElement(connect)) then 
            connect:destroy() 
        end 
    end 
) 
  

Save

  
function onSave(player) 
    local serial = player:getSerial() 
    local name = player:getName() 
    local health = player:getHealth() 
    local x, y, z = getElementPosition(player) 
    local pos = toJSON({x, y, z}) 
    local needs, status, items = {}, {}, {} 
    for k, v in pairs(Table) do 
        for i, data in pairs(v) do 
            if (k == 'need') then 
                needs[i] = player:getData(data[1]) 
            elseif (k == 'stat') then 
                status[i] = player:getData(data[1]) 
            elseif (k == 'item') then 
                items[i] = player:getData(data[1]) 
            end 
        end 
    end 
    player:setData('logged', false) 
    needs, status, items = toJSON(needs), toJSON(status), toJSON(items) 
    getDB():exec('UPDATE `accounts` SET `login` = ?, `health` = ?, `pos` = ?, `needs` = ?, `status` = ?, `items` = ?, `lastdate` = NOW() WHERE `serial` = ? LIMIT 1', name, health, pos, needs, status, items, serial) 
    outputServerLog('Account Name: '..name..' was saved automatically.') 
end 
  

If there is an error please correct it, I'm still a noob, I'm just learning)

And thank you for the answer, then if not strange ignore or remain silent

Link to comment
  • Moderators

ah your OOP functions are elementdata instead of accountdata. I am not using OOP functions, so I wasn't sure which it was.

I am using no OOP functions because I know a lot of mta functions out of my head.

function onSave(player) 
    if isElement(player) then 
        local serial = player:getSerial() or "" -- just in case 
        local name = player:getName()  or "" -- just in case 
        local health = player:getHealth() or 100 -- just in case 
        local x, y, z = getElementPosition(player) 
        local pos = toJSON({x, y, z}) 
        local needs, status, items = {}, {}, {} 
        for k, v in pairs(Table) do 
            for i, data in pairs(v) do 
                if (k == 'need') then 
                    needs[#needs+1] = player:getData(data[1]) -- [#needs+1] < making sure it starts from the first index. 
                elseif (k == 'stat') then 
                    status[#status+1] = player:getData(data[1]) 
                elseif (k == 'item') then 
                    items[#items+1] = player:getData(data[1]) 
                end 
            end 
        end 
        player:setData('logged', false) 
        needs, status, items = toJSON(needs), toJSON(status), toJSON(items) 
        getDB():exec('UPDATE `accounts` SET `login` = ?, `health` = ?, `pos` = ?, `needs` = ?, `status` = ?, `items` = ?, `lastdate` = NOW() WHERE `serial` = ? LIMIT 1', name, health, pos, needs, status, items, serial) 
        outputServerLog('Account Name: '..name..' was saved automatically.')  
    end 
end 

Anyway take a closer look at my notes.

Also on what are the accounts based? Name or serial?

Because you can never rely on the player his name.

Link to comment
ah your OOP functions are elementdata instead of accountdata. I am not using OOP functions, so I wasn't sure which it was.

I am using no OOP functions because I know a lot of mta functions out of my head.

function onSave(player) 
    if isElement(player) then 
        local serial = player:getSerial() or "" -- just in case 
        local name = player:getName()  or "" -- just in case 
        local health = player:getHealth() or 100 -- just in case 
        local x, y, z = getElementPosition(player) 
        local pos = toJSON({x, y, z}) 
        local needs, status, items = {}, {}, {} 
        for k, v in pairs(Table) do 
            for i, data in pairs(v) do 
                if (k == 'need') then 
                    needs[#needs+1] = player:getData(data[1]) -- [#needs+1] < making sure it starts from the first index. 
                elseif (k == 'stat') then 
                    status[#status+1] = player:getData(data[1]) 
                elseif (k == 'item') then 
                    items[#items+1] = player:getData(data[1]) 
                end 
            end 
        end 
        player:setData('logged', false) 
        needs, status, items = toJSON(needs), toJSON(status), toJSON(items) 
        getDB():exec('UPDATE `accounts` SET `login` = ?, `health` = ?, `pos` = ?, `needs` = ?, `status` = ?, `items` = ?, `lastdate` = NOW() WHERE `serial` = ? LIMIT 1', name, health, pos, needs, status, items, serial) 
        outputServerLog('Account Name: '..name..' was saved automatically.')  
    end 
end 

Anyway take a closer look at my notes.

Also on what are the accounts based? Name or serial?

Because you can never rely on the player his name.

Thank you very much, I do not use SQLite, I use MySQL for him and not to used setAccountData.

Data is saved to check the serial

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...