[Help] Database script

Hello, I am having some problems with this script I’m making for my server.
I’ll first post the resource and then the error with the explanation. Somehow I can’t get around it!

CLIENT SIDE

Citizen.CreateThread(function()
	while true do
		Wait(1)
		if IsPedDeadOrDying(GetPlayerPed(-1)) then
			Wait(2000)
			coords = GetEntityCoords(GetPlayerPed(-1))
			if not IsEntityInWater(GetPlayerPed(-1)) then
				Wait(1000)
				SetEntityCoords(GetPlayerPed(-1), coords, 0, 0, 0, 1)
			end
			SaveCoords(table.unpack(coords))
		end
		if IsPlayerLoggingInNp() then
			Wait(10000)
			TriggerServerEvent('ReadSavegame', source)
			SetEntityCoords(GetPlayerPed(-1), tonumber(coordsx), tonumber(coordsy), tonumber(coordsz), 0, 0, 0, 1)
		end
	end
end)

function SaveCoords(x,y,z)
	TriggerServerEvent('WriteSavegame', source, 1, x)
	TriggerServerEvent('WriteSavegame', source, 2, y)
	TriggerServerEvent('WriteSavegame', source, 3, z)
end

SERVER SIDE

databasedir = 'database'

RegisterServerEvent('ReadSavegame')
RegisterServerEvent('WriteSavegame')


AddEventHandler('ReadSavegame', function(source)
	if GetIdFromSource("steam", source) ~= nil then
		id = GetIdFromSource("steam", source)
	else
		id = 'common'
	end
	savename = databasedir.. '/' ..id.. '.txt'
	local data = LoadSavegame(savename)
		stringsplit(data, ',')
	
	
	coordsx = data[1]
	coordsy = data[2]
	coordsz = data[3]
end)

AddEventHandler('WriteSavegame', function(source, datatype, writeme)
	if GetIdFromSource("steam", source) ~= nil then
		id = GetIdFromSource("steam", source)
	else
		id = 'common'
	end
	savename = databasedir.. '/' ..id.. '.txt'
	local data = LoadSavegame(savename)
		stringsplit(data, ',')
	
	
	towrite[1] = data[1]	-- X
	towrite[2] = data[2]	-- Y
	towrite[3] = data[3]	-- Z
	--ADD HERE FURTHER DATATYPES
	towrite[tonumber(datatype)] = writeme
	UploadSavegame(savename, towrite[1].. ',' ..towrite[2].. ',' ..towrite[3])
end)




-- FUNCTIONS

function LoadSavegame(path)
	if fileExists(path) then
		local file = io.open(path, 'w+')
		local buffer = file:read("*a")
		file:close()
		return buffer
	else
		return false
	end
end

function UploadSavegame(path, data)
	local file = io.open(path, 'w+')
	file:write(tostring(data))
	file:flush()
	file:close()
end

function fileExists(path)
	local file = io.open(path, "rb")
	if file then
		file:close()
	end
	return file ~= nil
end

function stringsplit(inputstr, sep)
    if sep == nil then
        sep = "%s"
    end
    local t={} ; i=1
    for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
        t[i] = str
        i = i + 1
    end
    return t
end

function GetIdFromSource(Type, ID)
    local IDs = GetPlayerIdentifiers(ID)
    for k, CurrentID in pairs(IDs) do
        local ID = stringsplit(CurrentID, ":")
        if (ID[1] == string.lower(Type)) then
            return ID[2]
        end
    end
    return nil
end

ERROR ON THE CONSOLE

cfx> InvokeNative: execution failed: Argument at index 0 was null.
Error running system event handling function for resource database: citizen:/scripting/lua/scheduler.lua:41: Failed to execute thread: Execution of native 00000000ff7f66ab in script host failed.
stack traceback:
        [C]: in upvalue '_in'
        citizen:/scripting/lua/natives_server.lua:154: in function 'GetNumPlayerIdentifiers'
        citizen:/scripting/lua/scheduler.lua:294: in function 'GetPlayerIdentifiers'
        @database/sv_database.lua:86: in function 'GetIdFromSource'
        @database/sv_database.lua:24: in upvalue 'handler'
        citizen:/scripting/lua/scheduler.lua:219: in function <citizen:/scripting/lua/scheduler.lua:218>
stack traceback:
        [C]: in function 'error'
        citizen:/scripting/lua/scheduler.lua:41: in field 'CreateThreadNow'
        citizen:/scripting/lua/scheduler.lua:218: in function <citizen:/scripting/lua/scheduler.lua:182>

This happens every time I die ingame, when the resource is supposed to write the savegame but obviously doesn’t!
Please explain me this the easy way if you could, I’m still learning the basics of lua :stuck_out_tongue:

I’m not sure but maybe don’t do that

towrite[1] = data[1]	-- X
towrite[2] = data[2]	-- Y
towrite[3] = data[3]	-- Z

You can like, try something like that way

local spawn = {
    {x=-199.496, y=-1603.920, z=34.665, h=247.891}, -- groove spawn #1
    {x=-161.586, y=-1638.290, z=34.028, h=0.00249}, -- groove spawn #2
    {x=-147.991, y=-1688.230, z=32.872, h=119.422}  -- groove spawn #3
}
nameofFunction(spawn.x, spawn.y, spawn.z)

Mhh that doesn’t actually allow me to do what I was trying to.

towrite[1] = data[1]	-- X
towrite[2] = data[2]	-- Y
towrite[3] = data[3]	-- Z
towrite[tonumber(datatype)] = writeme

was used to actually rewrite every single data as I just read it. But changing the data (writeme) I want to change in the savegame (determined by the datatype).
But I’m not still 100% sure that works.

This would simply do the job

	local data = LoadSavegame(savename)
		stringsplit(data, ',')
	
	data[tonumber(datatype)] = writeme
	UploadSavegame(savename, data[1].. ',' ..data[2].. ',' ..data[3])

You don’t need to pass ‘source’ as a variable at all when triggering events. This is just a global variable on the server, it won’t work on client scripts.

So

TriggerServerEvent('WriteSavegame', source, 1, x)

Can just turn into this

TriggerServerEvent('WriteSavegame', 1, x)

When you’re handling the event, you don’t need to pass in ‘source’ as a parameter either. This has always confused me. I can’t really tell you why this is the way it is, but I’m sure someone else can :smiley:

1 Like