Making a XP system and saving only works if the server has not restarted.

So I’ve been working on a XP system and the saving system works when you leave and come back but after a server restart it does not any ideas?


local meta = FindMetaTable("Player")

// Setters

function meta:SetLevel(level)
    if (CLIENT) then return end
    local PlayerFile = "level_system/" .. self:UniqueID() .. ".txt"

	if (file.Exists(PlayerFile, "DATA")) then
		local PlayerData = util.JSONToTable(file.Read(PlayerFile, "DATA"))
        self:SetNWInt("PlayerLevel", level)
        PlayerData.Level = level

		file.Write(PlayerFile, util.TableToJSON(PlayerData, true))
	end
end

function meta:SetXP(amount)
    if (CLIENT) then return end
    local PlayerFile = "level_system/" .. self:UniqueID() .. ".txt"

	if (file.Exists(PlayerFile, "DATA")) then
		local PlayerData = util.JSONToTable(file.Read(PlayerFile, "DATA"))
        self:SetNWInt("PlayerXP", amount)
        PlayerData.XP = amount

		file.Write(PlayerFile, util.TableToJSON(PlayerData, true))
	end
end

// Getters

function meta:GetLevel()
    if (CLIENT) then
        return self:GetNWInt("PlayerLevel")
    end

    if (SERVER) then
        local PlayerFile = "level_system/" .. self:UniqueID() .. ".txt"
    	if (file.Exists(PlayerFile, "DATA")) then
    		local PlayerData = util.JSONToTable(file.Read(PlayerFile, "DATA"))

            return PlayerData.Level
    	end
    end
end

function meta:GetXP()
    if (CLIENT) then
        return self:GetNWInt("PlayerXP")
    end

    if (SERVER) then
        local PlayerFile = "level_system/" .. self:UniqueID() .. ".txt"
    	if (file.Exists(PlayerFile, "DATA")) then
    		local PlayerData = util.JSONToTable(file.Read(PlayerFile, "DATA"))

            return PlayerData.XP
    	end
    end
end




function InitializeLevelSystem()
    if (!file.IsDir("level_system", "DATA")) then
        file.CreateDir("level_system", "DATA")
    end
end
hook.Add("Initialize", "InitializeLevelSystem", InitializeLevelSystem)

function LoadPlayerData(ply)
    local PlayerFile = "level_system/" .. ply:UniqueID() .. ".txt"
    if (file.Exists(PlayerFile, "DATA")) then
        local PlayerData = util.JSONToTable(file.Read(PlayerFile, "DATA"))
        // Update the player's stats (if u want to)
        file.Write(PlayerFile, util.TableToJSON(PlayerData, true))
    else
        // Write the player's stats for the first time
        data = {
            SteamID = ply:SteamID(),
            Level = 0,
            XP = 0
        }
        file.Write(PlayerFile, util.TableToJSON(data, true))
    end
end
hook.Add("PlayerInitialSpawn", "LoadPlayerData", LoadPlayerData)

-whoops-

Are you calling a GetLevel/<something> on the client before you call it on the server? GetNWInt won’t be set until you set the XP or level.

I have no clue im new to gLua i put this in the share and it works when the server hasnt restarted but the player has rejoined but if the server restarts it resets like it doesnt save the JSON file or smthn

GM:ShutDown

posting a wiki link without context is less than helpful.

If you read the page, it’s a hook called before the game shuts down.
You need to update everyone’s information when this hook is called.
This is also explicitly said on the wiki’s article for JSON file storage (https://wiki.garrysmod.com/page/File_Based_Storage)

oh hey I made that page, glad to see it getting referenced :smiley:
To make things a bit clearer - You should only use

file.Write inside the ShutDown and PlayerDisconnected hooks. When using SetLevel/XP, you should use SetNWInt, and when using GetLevel/XP, you should only use GetNWInt.
But if all you’re saving is XP and a Level, you don’t need to use JSON, you could make it as simple as a file containing 2 numbers and a semicolon (e.g. “4;253”. Level 4, 253 XP points).
I’d also discourage using UniqueID, but rather use SteamID or SteamID64,

How about this alternative:

Use PData instead and save yourself the hassle of having to open, read, write, close files.

Thanks ill check that out.