Server-Side Example

Examples Updated: Dec 10, 2025

Server-Side Example

Complete server-side code for an addon.

Database Setup

-- myaddon/sv_database.lua
MyAddon.DB = nil

hook.Add("MyAddon.Loaded", "MyAddon.Database", function()
    if not MyAddon.Config.Database then return end
    
    local cfg = MyAddon.Config.Database
    
    MyAddon.DB = cLib.MYSQL.f.ConnectDatabase({
        db_host = cfg.Host,
        db_port = cfg.Port,
        db_user = cfg.User,
        db_password = cfg.Password,
        db_name = cfg.Database
    }, function(db)
        print("[MyAddon] Database connected!")
        MyAddon.CreateTables()
    end, function(db, err)
        print("[MyAddon] Database error:", err)
    end)
end)

function MyAddon.CreateTables()
    cLib.MYSQL.f.Query(MyAddon.DB, [[
        CREATE TABLE IF NOT EXISTS myaddon_players (
            id INT AUTO_INCREMENT PRIMARY KEY,
            steamid VARCHAR(32) NOT NULL UNIQUE,
            data TEXT,
            created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
            updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
            INDEX idx_steamid (steamid)
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
    ]], {}, function()
        print("[MyAddon] Tables ready!")
    end)
end

Network Setup

-- myaddon/sv_network.lua
cLib.Net.SetPrefix("MyAddon.")

cLib.Net.RegisterMultiple({
    "OpenMenu",
    "SyncData",
    "SaveData",
    "RequestData"
})

-- Send data to player on spawn
hook.Add("PlayerInitialSpawn", "MyAddon.Sync", function(ply)
    timer.Simple(1, function()
        if not IsValid(ply) then return end
        
        MyAddon.LoadPlayerData(ply, function(data)
            cLib.Net.Send("SyncData", data, ply)
        end)
    end)
end)

-- Handle save request
cLib.Net.Receive("SaveData", function(data, ply)
    if not IsValid(ply) then return end
    
    MyAddon.SavePlayerData(ply, data, function(success)
        if success then
            cLib.Net.Send("SyncData", {success = true, message = "Saved!"}, ply)
        else
            cLib.Net.Send("SyncData", {success = false, message = "Failed to save"}, ply)
        end
    end)
end)

-- Handle data request
cLib.Net.Receive("RequestData", function(data, ply)
    if not IsValid(ply) then return end
    
    MyAddon.LoadPlayerData(ply, function(playerData)
        cLib.Net.Send("SyncData", playerData, ply)
    end)
end)

Server Functions

-- myaddon/sv_functions.lua

function MyAddon.LoadPlayerData(ply, callback)
    local steamid = ply:SteamID64()
    
    cLib.MYSQL.f.Query(MyAddon.DB,
        "SELECT * FROM myaddon_players WHERE steamid = ?",
        {steamid},
        function(results)
            if results and results[1] then
                local data = util.JSONToTable(results[1].data or "{}") or {}
                callback(data)
            else
                -- Create new player
                MyAddon.CreatePlayer(ply, function()
                    callback({})
                end)
            end
        end,
        function(err)
            cLib.Debug.Error("Failed to load player:", err)
            callback({})
        end
    )
end

function MyAddon.SavePlayerData(ply, data, callback)
    local steamid = ply:SteamID64()
    local json = util.TableToJSON(data)
    
    cLib.MYSQL.f.Query(MyAddon.DB,
        "UPDATE myaddon_players SET data = ? WHERE steamid = ?",
        {json, steamid},
        function()
            callback(true)
        end,
        function(err)
            cLib.Debug.Error("Failed to save player:", err)
            callback(false)
        end
    )
end

function MyAddon.CreatePlayer(ply, callback)
    local steamid = ply:SteamID64()
    
    cLib.MYSQL.f.Query(MyAddon.DB,
        "INSERT INTO myaddon_players (steamid, data) VALUES (?, ?)",
        {steamid, "{}"},
        function()
            callback()
        end
    )
end