Jump to content

[HELP] How can i remove a data from my table?


Turbesz

Recommended Posts

  • Moderators
5 minutes ago, Turbesz said:

uh that's true, my bad!

now i don't get any errors or warnings, and the file was created, but does not insert the script any data to that file, i just get only "<root></root>" as a result in my .xml file

You also have to apply my feedback from before that:

 

9 hours ago, IIYAMA said:

That is why I gave you a function for reformatting:




xml:xmlSaveData("save", reformatToArray(menteshez), false, true) 

 

(don't forget to modify the key)

 

And after that it is variable debugging time.

 

----

+

And you might also need to encode the account name, so that all special characters are escaped:

https://wiki.multitheftauto.com/wiki/Base64Encode

 

Edited by IIYAMA
Link to comment
7 minutes ago, IIYAMA said:

You also have to apply my feedback from before that:

 

(don't forget to modify the key)

 

And after that it is variable debugging time.

 

----

+

And you might also need to encode the account name, so that all special characters are escaped:

https://wiki.multitheftauto.com/wiki/Base64Encode

 

i tried to modify 'menteshez' to 'reformatToArray(menteshez)' but then i get this error: bad argument #1 to 'pairs' (table expected got nil)

the error refers to this loop in 'reformatToArray' func:  

	for k, data in pairs(theTable) do
		table.insert(array, data)
	end

 

Link to comment
11 minutes ago, IIYAMA said:

Are you 100000% sure that `menteshez`contains a table?

Um, yes(?)

This is my current code of save func: 

local menteshez = {}
local xml = exports.xmldata

function teszt(thePlayer)
    local object=getElementsByType("object")
    local theAcc = getPlayerAccount(thePlayer)
    local accname = getAccountName(theAcc)

    
    local menteshez = xml:xmlLoadData("save" .. accname, true)
    if not menteshez then
        xml:xmlSaveData("save" .. accname, {}, false, true)  
        return
    end

    for k, v in ipairs(object) do
        if getElementData(v,"owner") == accname then
            local x,y,z = getElementPosition(v)
            local id = getElementModel(v)
            local owner = getElementData(v,"owner") or getAccountName(theAcc)
            local int = getElementInterior(v)
            local dim = getElementDimension(v)
            local Rx,Ry,Rz = getElementRotation ( v )
            outputChatBox("mentve")
            menteshez[v] = {x,y,z,id,owner,int,dim,Rx,Ry,Rz}
            setCustomData(thePlayer, "menteshez", menteshez, true)
        end
    end
    local menteshez = getCustomData(thePlayer, "menteshez", true) 

    local account = getPlayerAccount(thePlayer)
    local accountName = getAccountName(account)
    
    xml:xmlSaveData("save" .. accountName, reformatToArray(menteshez), false, true)

end

addCommandHandler("save",teszt)

 

Link to comment
  • Moderators
1 minute ago, Turbesz said:

Um, yes(?)

Nope it did not.

 

Let me simplify it a bit, remove all tools that you are currently not using, since we get no-were otherwise.

 

local xml = exports.xmldata

function teszt(thePlayer)
    local object=getElementsByType("object")
    local theAcc = getPlayerAccount(thePlayer)
    local accname = getAccountName(theAcc)

    local menteshez = {} -- reset and fill up again

    for k, v in ipairs(object) do
        if getElementData(v,"owner") == accname then
            local x,y,z = getElementPosition(v)
            local id = getElementModel(v)
            local owner = getElementData(v,"owner") or accname
            local int = getElementInterior(v)
            local dim = getElementDimension(v)
            local Rx,Ry,Rz = getElementRotation ( v )

            menteshez[#menteshez + 1] = {x,y,z,id,owner,int,dim,Rx,Ry,Rz}
            
        end
    end
    
    xml:xmlSaveData("save" .. base64Encode(accname), menteshez, false, true)

end

addCommandHandler("save",teszt)

 

 

 

 

Link to comment
10 hours ago, IIYAMA said:

Nope it did not.

 

Let me simplify it a bit, remove all tools that you are currently not using, since we get no-were otherwise.

 


local xml = exports.xmldata

function teszt(thePlayer)
    local object=getElementsByType("object")
    local theAcc = getPlayerAccount(thePlayer)
    local accname = getAccountName(theAcc)

    local menteshez = {} -- reset and fill up again

    for k, v in ipairs(object) do
        if getElementData(v,"owner") == accname then
            local x,y,z = getElementPosition(v)
            local id = getElementModel(v)
            local owner = getElementData(v,"owner") or accname
            local int = getElementInterior(v)
            local dim = getElementDimension(v)
            local Rx,Ry,Rz = getElementRotation ( v )

            menteshez[#menteshez + 1] = {x,y,z,id,owner,int,dim,Rx,Ry,Rz}
            
        end
    end
    
    xml:xmlSaveData("save" .. base64Encode(accname), menteshez, false, true)

end

addCommandHandler("save",teszt)

 

 

 

 

Thank you, save and load working fine now :D 

Btw, can't that cause some issues that it's saving the XML file on the server and not on the players PC? Because over time it can be up to more than 1000, or 2000 XML file (if we look at that my server has ~4000 registered account, and every player can register only one)

Link to comment
  • Moderators
1 hour ago, Turbesz said:

Btw, can't that cause some issues that it's saving the XML file on the server and not on the players PC? Because over time it can be up to more than 1000, or 2000 XML file (if we look at that my server has ~4000 registered account, and every player can register only one)

That can become an issue, here is a list that current method is lacking:

- Not able to use a-sync + queueing

- Not able to saving/loading data by using a different thread.

- XML uses more filespace

- There is no cleaner for older account data / There is no archive system that moves account data that isn't used for a while to a separated environment.

 

You can also decide to backup the data on to the clients their pc's. That way you can freely clean data on the server when accounts aren't used for more than a year.

The client has a copy of the data and can upload it back to the server when the server has deleted it. (but more sure that it can't be abused, by encrypting the file)

 

Clientside only datastorage would be a better a better solution to be honest, but then again if the client crashes... auto save might be recommended.

 

 

 

 

 

 

Edited by IIYAMA
Link to comment
  • Moderators
2 minutes ago, Turbesz said:

Or how can i easily move the save and load funcs to client side?

There is no `easy` in doing that.

 

For the example code, I will be using my library, so that I do not have to write so much code. Feel free to replace them with trigger events.

Note: I did not test this, but it will at least give you an idea how it could be done.

 

Server

local xml = exports.xmldata

function teszt(thePlayer)
    local object=getElementsByType("object")
    local theAcc = getPlayerAccount(thePlayer)
    local accname = getAccountName(theAcc)

    local menteshez = {} -- reset and fill up again

    for k, v in ipairs(object) do
        if getElementData(v,"owner") == accname then
            local x,y,z = getElementPosition(v)
            local id = getElementModel(v)
            local owner = getElementData(v,"owner") or accname
            local int = getElementInterior(v)
            local dim = getElementDimension(v)
            local Rx,Ry,Rz = getElementRotation ( v )

            menteshez[#menteshez + 1] = {x,y,z,id,owner,int,dim,Rx,Ry,Rz}
            
        end
    end
    callClientAwait(thePlayer, "saveMapData", "save" .. base64Encode(accname), menteshez, 
    function (successState) 
		outputChatBox(client, "Map data has been saved.")
    end)
    

end

addCommandHandler("save",teszt)

	

 

 

function testLoad (thePlayer)
    local theAcc = getPlayerAccount(thePlayer)
    local accname = getAccountName(theAcc)
    callClientAwait(thePlayer, "loadMapData", "save" .. base64Encode(accname), menteshez, 
    function (data) 
		outputChatBox(client, "Map data is here available, if it has been saved before")
    end)
end
addCommandHandler("load",testLoad)

 

Client

local xml = exports.xmldata
function saveMapData (fileName, data)
	return xml:xmlSaveData(fileName, data, true, false, true)
end
function loadMapData (fileName)
	return xml:xmlLoadData ( fileName, true,  true)
end

 

 

 

 

Link to comment
24 minutes ago, IIYAMA said:

There is no `easy` in doing that.

 

For the example code, I will be using my library, so that I do not have to write so much code. Feel free to replace them with trigger events.

Note: I did not test this, but it will at least give you an idea how it could be done.

 

Server


local xml = exports.xmldata

function teszt(thePlayer)
    local object=getElementsByType("object")
    local theAcc = getPlayerAccount(thePlayer)
    local accname = getAccountName(theAcc)

    local menteshez = {} -- reset and fill up again

    for k, v in ipairs(object) do
        if getElementData(v,"owner") == accname then
            local x,y,z = getElementPosition(v)
            local id = getElementModel(v)
            local owner = getElementData(v,"owner") or accname
            local int = getElementInterior(v)
            local dim = getElementDimension(v)
            local Rx,Ry,Rz = getElementRotation ( v )

            menteshez[#menteshez + 1] = {x,y,z,id,owner,int,dim,Rx,Ry,Rz}
            
        end
    end
    callClientAwait(thePlayer, "saveMapData", "save" .. base64Encode(accname), menteshez, 
    function (successState) 
		outputChatBox(client, "Map data has been saved.")
    end)
    

end

addCommandHandler("save",teszt)

	

 

 


function testLoad (thePlayer)
    local theAcc = getPlayerAccount(thePlayer)
    local accname = getAccountName(theAcc)
    callClientAwait(thePlayer, "loadMapData", "save" .. base64Encode(accname), menteshez, 
    function (data) 
		outputChatBox(client, "Map data is here available, if it has been saved before")
    end)
end
addCommandHandler("load",testLoad)

 

Client


local xml = exports.xmldata

function saveMapData (fileName, data)
	return xml:xmlSaveData(fileName, data, true, false, true)
end

function loadMapData (fileName)
	return xml:xmlLoadData ( fileName, true,  true)
end

 

 

 

 

okay, i replaced them with trigger events, and triggers are working fine

but how can i get datas in load func?

function testLoad (thePlayer)
    local theAcc = getPlayerAccount(thePlayer)
    local accname = getAccountName(theAcc)

    triggerClientEvent(thePlayer,"sbetolt", thePlayer, "save"..base64Encode(accname), menteshez)

end
addCommandHandler("load",testLoad)

 

Link to comment
  • Moderators
2 minutes ago, Turbesz said:

but how can i get datas in load func?

By keeping a function alive within the testLoad function, until the message is send back.

And how do you do that? Well, you can look at the source code of my library and see if you could replicate a part of it. Or just use the library.

 

Or you can also not do it and return it in to a different function, that would be the easiest way without library.

 

Link to comment
37 minutes ago, IIYAMA said:

By keeping a function alive within the testLoad function, until the message is send back.

And how do you do that? Well, you can look at the source code of my library and see if you could replicate a part of it. Or just use the library.

 

Or you can also not do it and return it in to a different function, that would be the easiest way without library.

 

i tried make a new trigger to load from client to server, and then create the objects, but does not work

server:

function testLoad (thePlayer)
    local theAcc = getPlayerAccount(thePlayer)
    local accname = getAccountName(theAcc)

    triggerClientEvent(thePlayer,"sbetolt", thePlayer, "save"..base64Encode(accname), menteshez)

end
addCommandHandler("load",testLoad)

function teszt2(thePlayer,x,y,z,id,owner,int,dim,Rx,Ry,Rz)

    local object=getElementsByType("object")
    local theAcc = getPlayerAccount(thePlayer)
    local accname = getAccountName(theAcc)

    for i,v in ipairs(getElementsByType("object")) do 
        if getElementData(v,"owner") == owner then
        destroyElement(v)
        end
    end
        if owner == accname then
        id = id+1
        
            local x, y, z = getElementPosition(thePlayer)
            local theAcc = getPlayerAccount(thePlayer)
            local accname = getAccountName(theAcc)
        
        targy = createObject(id, x, y,z)
        
        setElementData(targy, "owner", accname)
        setElementData(targy,"id",id)
        setElementInterior(targy,int)
        setElementDimension(targy,dim)
        setElementRotation(targy,Rx,Ry,Rz)
        setElementData(thePlayer,"torles",getElementData(targy,"id") or 0)
        outputChatBox("betöltve")

        end
end

addEvent("load2",true)
addEventHandler("load2",root,teszt2)

client:

function loadMapData (fileName)
	local menteshez = xml:xmlLoadData ( fileName, true,  true)

	for k, v in ipairs(menteshez) do
		--outputChatBox(v[1])
		local x = v[1]
		local y = v[2]
		local z = v[3]
		local id = v[4]
		local owner = v[5]
		local int = v[6]
		local dim = v[7]
		local Rx = v[8]
		local Ry = v[9]
		local Rz = v[10]
		triggerServerEvent("load2",localPlayer,playerSource,x,y,z,id,owner,int,dim,Rx,Ry,Rz)
	end
end
addEvent("sbetolt",true)
addEventHandler("sbetolt",root,loadMapData)

what wrong?

Link to comment
  • Moderators
8 minutes ago, Turbesz said:

what wrong?

Your code does this:

  • Loop
    1. send over 1 object (network)
    2. delete all objects
    3. create 1 object
       
    4. send over 1 object (network)
    5. delete all objects (included the one you just created)
    6. create 1 object
       
    7. send over 1 object (network)
    8. delete all objects
    9. create 1 object

      etc. etc. etc.

 

Just send over the whole menteshez table > loop, else you will also kill your network.

 

 

Edited by IIYAMA
Link to comment
7 minutes ago, IIYAMA said:

Your code does this:

  • Loop
    1. send over 1 object
    2. delete all objects
    3. create 1 object
       
    4. send over 1 object
    5. delete all objects (included the one you just created)
    6. create 1 object
       
    7. send over 1 object
    8. delete all objects
    9. create 1 object

      etc. etc. etc.

 

Just send over the whole menteshez table > loop, else you will also kill your network.

 

 

Um i send now the whole table, and i get these warnings:
Bad argument @ 'getPlayerAccount' [Expected element at argument 1, got nil]
Bad argument @ 'getAccountName' [Expected element at argument 1, got nil]

client:

function loadMapData (fileName)
	local menteshez = xml:xmlLoadData ( fileName, true,  true)


		triggerServerEvent("load2",localPlayer,playerSource,menteshez)
end
addEvent("sbetolt",true)
addEventHandler("sbetolt",root,loadMapData)

server:

function teszt2(thePlayer,menteshez)
    local account = getPlayerAccount(thePlayer)
    local accountName = getAccountName(account)
    
    local object=getElementsByType("object")
    local theAcc = getPlayerAccount(thePlayer)
    local accname = getAccountName(theAcc)

    for i,v in ipairs(getElementsByType("object")) do 
        if getElementData(v,"owner") == accname then
        destroyElement(v)
        end
    end
    setTimer(function()
    for k, v in ipairs(menteshez) do
        if v[5] == accname then
        id = id+1
        
            local x, y, z = getElementPosition(thePlayer)
            local theAcc = getPlayerAccount(thePlayer)
            local accname = getAccountName(theAcc)
        
        targy = createObject(v[4], v[1], v[2], v[3])
        
        setElementData(targy, "owner", accname)
        setElementData(targy,"id",id)
        setElementInterior(targy,v[6])
        setElementDimension(targy,v[7])
        setElementRotation(targy,v[8],v[9],v[10])
        setElementData(thePlayer,"torles",getElementData(targy,"id") or 0)
        outputChatBox("betöltve")

        end
    end
end,500,1)
end

addEvent("load2",true)
addEventHandler("load2",root,teszt2)

why do i get those warnings?

Edited by Turbesz
Link to comment
  • Moderators
33 minutes ago, Turbesz said:

if i use localPlayer, then the objects are visible to the local player only?

no,


If you only want to see your objects, I recommend to set all objects to another dimension than the players.

And for every object you create:

triggerClientEvent > Clientside: setElementDimension (to your own dimension)

Edited by IIYAMA
  • Thanks 1
Link to comment
18 hours ago, IIYAMA said:

no,


If you only want to see your objects, I recommend to set all objects to another dimension than the players.

And for every object you create:

triggerClientEvent > Clientside: setElementDimension (to your own dimension)

thank you very much for all the help, and your patience :D 

at least I just learned something new :D 

  • Like 1
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...