We did not build ULX around the idea that the data directory would be shared, sorry. While it's possible to support such a thing, you're the first person we've heard of who has it setup that way.
Mine is setup that way too Meg.
It's nice for a system where you want to save player data for a gamemode or point system to the sv.db or flatfiles and share them on all servers you are running. Not so nice for the source files such as bans.
If you're interested.. here is my script for user authentication and bans... If you don't know basic lua or how to set up the MySQLOO module, then don't even bother with this.. but here it is...
require("mysqloo")
G4PSQL = {}
local DATABASE_HOST = "127.0.0.1"
local DATABASE_PORT = 3306
local DATABASE_NAME = "g4padmin"
local DATABASE_USERNAME = "root"
local DATABASE_PASSWORD = ""
local DATABSE_TABLE = "userauth"
function G4PSQL_Init()
G4PSQL_ConnectToDatabase()
timer.Simple(60, G4PSQL_Init )
end
hook.Add( "Initialize", "G4PSQL_Init", G4PSQL_Init )
function G4PSQL_Format( str )
if not str then return "NULL" end
return string.format( "%q", str )
end
function Escape( str )
if not G4PSQL.db then
Msg( "Not connected to DB.\n" )
return
end
if not str then return end
local esc = G4PSQL.db:escape( str )
if not esc then
return nil
end
return esc
end
function G4PSQL_ConnectToDatabase()
G4PSQL.db = mysqloo.connect( "127.0.0.1", "root", "", "g4padmin", 3306 )
G4PSQL.db:connect()
end
function G4PSQL_PlayerAuthDB( ply )
if G4PSQL.db:status() == 0 then
local sid = ply:SteamID()
print("Checking for: " .. Escape( sid ) )
local q1 = G4PSQL.db:query("SELECT * FROM " ..DATABSE_TABLE.. " WHERE steamid = "..G4PSQL_Format( Escape( sid ) ).."")
function q1:onSuccess( data )
if data[1] then
--PrintTable(data)
ply.steamid = data[1]["steamid"]
ply.name = data[1]["pname"]
ply.group = data[1]["pgroup"]
ply.banned = data[1]["banned"]
ply.lastplayed = data[1]["lastplayed"]
--ServerLog("/////PLAYER DATA FOUND/////" .. "\n")
--ServerLog("Name: " .. ply.name .. "\n")
--ServerLog("SteamID: " .. ply.steamid .. "\n")
--ServerLog("Group: " .. ply.group .. "\n")
--ServerLog("Last Played: " .. ply.lastplayed .. "\n")
--ServerLog("Banned?: " .. ply.banned .. "\n")
--ServerLog("///////////////////////////" .. "\n")
if ply.name != ply:Nick() then
--ServerLog( "Updating name for player: " ..ply:Nick() .. "\n" )
local q2 = G4PSQL.db:query("UPDATE " ..DATABSE_TABLE.. " SET pname="..G4PSQL_Format( Escape( ply:Nick() ) ) .. " WHERE steamid=" ..G4PSQL_Format( Escape( sid ) ) )
function q2:onSuccess( data2 )
--ServerLog( "Name updated sucessfully!\n" )
end
function q2:onError( Q, E )
ServerLog( "ERROR!!! " .. Q .. "\n" )
ServerLog( "ERROR!!! " .. E .. "\n" )
end
q2:start()
end
--ServerLog( "AUTHING PLAYER: " ..ply:Nick().. " in group (" ..ply.group..")." .. "\n" )
ULib.ucl.addUser( ply:SteamID(), _, _, ply.group )
SGS_SetUpTeams(ply)
local q4 = G4PSQL.db:query("UPDATE " ..DATABSE_TABLE.. " SET lastplayed="..G4PSQL_Format( Escape( tostring(os.date("%y/%m/%d")) ) ) .. " WHERE steamid=" ..G4PSQL_Format( Escape( sid ) ) )
function q4:onSuccess( data4 )
--ServerLog( "User Data (lastplayed) updated sucessfully!\n" )
end
function q4:onError( Q, E )
ServerLog( "ERROR!!! " .. Q .. "\n" )
ServerLog( "ERROR!!! " .. E .. "\n" )
end
q4:start()
if string.upper(ply.banned) == "TRUE" then
ULib.kick( ply, "CUSTOM BAN MESSAGE PLEASE EDIT THIS" )
end
ULib.tsay(ply, "Welcome back " ..ply:Nick().. ", you have been authenticated as: " ..ply.group..".", true)
else
--print("No Entry Found")
--ServerLog("No Results Found ... Creating Entry\n")
local q3 = G4PSQL.db:query( "INSERT INTO " ..DATABSE_TABLE.. " ( steamid, pname, pgroup, lastplayed, banned ) VALUES( " ..G4PSQL_Format( Escape( sid ) ) .. ", " ..G4PSQL_Format( Escape( ply:Nick() ) ) .. ", " ..G4PSQL_Format( Escape( "user" ) ) .. ", " ..G4PSQL_Format( Escape( tostring(os.date("%y/%m/%d")) ) ) .. ", " ..G4PSQL_Format( Escape( "FALSE" ) ).. " )" )
function q3:onSuccess( data3 )
--ServerLog( "Entry added sucessfully!\n" )
end
function q3:onError( Q, E )
ServerLog( "ERROR!!! " .. Q .. "\n" )
ServerLog( "ERROR!!! " .. E .. "\n" )
end
q3:start()
end
end
q1:start()
else
G4PSQL_RetryAuth( ply )
return
end
end
hook.Add( "PlayerAuthed", "G4PSQL_PlayerAuthDB", G4PSQL_PlayerAuthDB )
function G4PSQL_RetryAuth( ply )
if not ply.retries then ply.retries = 3 end
if ply.retries > 0 then
ply.retries = ply.retries - 1
--ServerLog("DATABASE NOT CONNECTED - RETRYING (" .. tostring(ply.retries) .. " retries left)" .. "\n")
G4PSQL_ConnectToDatabase()
timer.Simple(2, function() G4PSQL_PlayerAuthDB( ply ) end)
else
ServerLog( "FALLBACK AUTHENTICATION... DATABASE CAN NOT BE CONNECTED TO\n" )
--ServerLog( "AUTHING PLAYER: " ..ply:Nick().. " in group (user)." .. "\n" )
ULib.ucl.addUser( ply:SteamID(), _, _, "user" )
SGS_SetUpTeams(ply)
end
end
function G4PSQL_ChangeGroup( ply, cmd, args )
local sid = args[1]
local group = tostring(string.lower(args[2]))
if !IsValid( ply ) or ply:IsUserGroup("superadmin") then
if #args != 2 then
Msg("Not enough arguements!\n")
return
end
if (string.sub(sid, 1, 5) == "STEAM") then
sid = sid
qtype = 1
else
if IsValid(ULib.getUser(sid)) then
sid = ULib.getUser(sid)
qtype = 2
if not sid then
Msg( "USER NOT FOUND!\n" )
return
end
else
Msg( "USER NOT FOUND!\n" )
return
end
end
local gcheck = false
for k, v in pairs(ULib.ucl.groups) do
if group == k then
Msg("Checking " ..group.. " against " .. k .. "\n")
gcheck = true
break
end
end
if gcheck == false then
Msg("Group Doesn't Exist!!\n")
return
end
if G4PSQL.db:status() == 0 then
if qtype == 1 then
local q1 = G4PSQL.db:query("SELECT * FROM " ..DATABSE_TABLE.. " WHERE steamid = "..G4PSQL_Format( Escape( sid ) ).."")
function q1:onSuccess( data )
if data[1] then
Msg( "Updating group for steamID: (" ..sid .. ")\n" )
local q2 = G4PSQL.db:query("UPDATE " ..DATABSE_TABLE.. " SET pgroup="..G4PSQL_Format( Escape( group ) ) .. " WHERE steamid=" ..G4PSQL_Format( Escape( sid ) ) )
function q2:onSuccess( data2 )
Msg( "Player (" .. sid .. ") Group Changed!\n" )
end
function q2:onError( Q, E )
ServerLog( "ERROR!!! " .. Q .. "\n" )
ServerLog( "ERROR!!! " .. E .. "\n" )
end
q2:start()
else
Msg("No Entry Found")
Msg("No Results Found ... Creating Entry\n")
local q3 = G4PSQL.db:query( "INSERT INTO " ..DATABSE_TABLE.. " ( steamid, pname, pgroup, lastplayed, banned ) VALUES( " ..G4PSQL_Format( Escape( sid ) ) .. ", " ..G4PSQL_Format( Escape( "ADMIN ENTERED" ) ) .. ", " .. G4PSQL_Format( Escape( group ) ) .. ", " ..G4PSQL_Format( Escape( tostring("NEVER") ) ) .. ", " ..G4PSQL_Format( Escape( "FALSE" ) ).. " )" )
function q3:onSuccess( data3 )
Msg( "Entry added sucessfully!\n" )
end
function q3:onError( Q, E )
ServerLog( "ERROR!!! " .. Q .. "\n" )
ServerLog( "ERROR!!! " .. E .. "\n" )
end
q3:start()
end
end
q1:start()
else
local q1 = G4PSQL.db:query("SELECT * FROM " ..DATABSE_TABLE.. " WHERE steamid = "..G4PSQL_Format( Escape( sid:SteamID() ) ).."")
function q1:onSuccess( data )
if data[1] then
Msg( "Updating group for player: " ..sid:Nick() .. "\n" )
local q2 = G4PSQL.db:query("UPDATE " ..DATABSE_TABLE.. " SET pgroup="..G4PSQL_Format( Escape( group ) ) .. " WHERE steamid=" ..G4PSQL_Format( Escape( sid:SteamID() ) ) )
function q2:onSuccess( data2 )
Msg( "Player Group Changed!\n" )
ULib.ucl.addUser( sid:SteamID(), _, _, group )
SGS_SetUpTeams(sid)
end
function q2:onError( Q, E )
ServerLog( "ERROR!!! " .. Q .. "\n" )
ServerLog( "ERROR!!! " .. E .. "\n" )
end
q2:start()
else
Msg("No Entry Found")
Msg("No Results Found ... Creating Entry\n")
local q3 = G4PSQL.db:query( "INSERT INTO " ..DATABSE_TABLE.. " ( steamid, pname, pgroup, lastplayed, banned ) VALUES( " ..G4PSQL_Format( Escape( sid:SteamID() ) ) .. ", " ..G4PSQL_Format( Escape( "ADMIN ENTERED" ) ) .. ", " .. G4PSQL_Format( Escape( group ) ) .. ", " ..G4PSQL_Format( Escape( tostring("NEVER") ) ) .. ", " ..G4PSQL_Format( Escape( "FALSE" ) ).. " )" )
function q3:onSuccess( data3 )
Msg( "Entry added sucessfully!\n" )
end
function q3:onError( Q, E )
ServerLog( "ERROR!!! " .. Q .. "\n" )
ServerLog( "ERROR!!! " .. E .. "\n" )
end
q3:start()
end
end
q1:start()
end
else
Msg( "DATABASE NOT CONNECTED PLEASE TRY AGAIN!\n" )
G4PSQL_ConnectToDatabase()
end
else
Msg( "This command is reserved for administrators only!\n" )
end
end
concommand.Add( "g4p_setgroup", G4PSQL_ChangeGroup)
function G4PSQL_Ban( ply, cmd, args )
local sid = args[1]
local badmin = "NONE"
local baid = "NONE"
if !IsValid( ply ) or ply:IsAdmin() then
if IsValid(ply) then
badmin = ply:Nick()
bacolor = team.GetColor(ply:Team())
baid = ply:SteamID()
else
badmin = "(Console)"
bacolor = Color(80,80,80,255)
baid = "(Console)"
end
if #args != 1 then
Msg("Not enough arguements!")
return
end
if (string.sub(sid, 1, 5) == "STEAM") then
sid = sid
qtype = 1
else
if IsValid(ULib.getUser(sid)) then
sid = ULib.getUser(sid)
qtype = 2
if not sid then
Msg( "USER NOT FOUND!\n" )
return
end
else
Msg( "USER NOT FOUND!\n" )
return
end
end
if G4PSQL.db:status() == 0 then
if qtype == 2 then
local q1 = G4PSQL.db:query("SELECT * FROM " ..DATABSE_TABLE.. " WHERE steamid = "..G4PSQL_Format( Escape( sid:SteamID() ) ).."")
function q1:onSuccess( data )
if data[1] then
Msg( "Banning player: " ..sid:Nick() .. "\n" )
local q2 = G4PSQL.db:query("UPDATE " ..DATABSE_TABLE.. " SET banned=" .. G4PSQL_Format( Escape( "TRUE" ) ) .. ", badmin=" .. G4PSQL_Format( Escape( baid ) ) .. " WHERE steamid=" ..G4PSQL_Format( Escape( sid:SteamID() ) ) )
function q2:onSuccess( data2 )
Msg( "Player Banned!\n" )
ULib.tsayColor(_, 1, Color(0,0,0,255), "(", Color(255,0,0,255), sid:Nick(), Color(0,0,0,255), ") ", Color(255,255,255,255), "was globally banned by ", bacolor, badmin, Color(255,255,255,255), ".")
ULib.kick( sid, "BANNED! Visit our website at www.g4p.org to dispute this ban." )
end
function q2:onError( Q, E )
ServerLog( "ERROR!!! " .. Q .. "\n" )
ServerLog( "ERROR!!! " .. E .. "\n" )
end
q2:start()
else
Msg("No Entry Found")
Msg("No Results Found ... Creating Entry\n")
local q3 = G4PSQL.db:query( "INSERT INTO " ..DATABSE_TABLE.. " ( steamid, pname, pgroup, lastplayed, banned, badmin ) VALUES( " ..G4PSQL_Format( Escape( sid:SteamID() ) ) .. ", " ..G4PSQL_Format( Escape( "ADMIN ENTERED" ) ) .. ", " .. G4PSQL_Format( Escape( "user" ) ) .. ", " ..G4PSQL_Format( Escape( tostring("NEVER") ) ) .. ", " ..G4PSQL_Format( Escape( "TRUE" ) ).. ", " ..G4PSQL_Format( Escape( "NONE" ) ).. " )" )
function q3:onSuccess( data3 )
Msg( "Player Banned!\n" )
ULib.tsayColor(_, 1, Color(0,0,0,255), "(", Color(255,0,0,255), sid:Nick(), Color(0,0,0,255), ") ", Color(255,255,255,255), "was globally banned by ", bacolor, badmin, Color(255,255,255,255), ".")
ULib.kick( sid:SteamID(), "BANNED! Visit our website at www.g4p.org to dispute this ban." )
end
function q3:onError( Q, E )
ServerLog( "ERROR!!! " .. Q .. "\n" )
ServerLog( "ERROR!!! " .. E .. "\n" )
end
q3:start()
end
end
q1:start()
else
local q1 = G4PSQL.db:query("SELECT * FROM " ..DATABSE_TABLE.. " WHERE steamid = "..G4PSQL_Format( Escape( sid ) ).."")
function q1:onSuccess( data )
if data[1] then
Msg( "Banning SteamID: " ..sid .. "\n" )
local q2 = G4PSQL.db:query("UPDATE " ..DATABSE_TABLE.. " SET banned=" .. G4PSQL_Format( Escape( "TRUE" ) ) .. ", badmin=" .. G4PSQL_Format( Escape( baid ) ) .. " WHERE steamid=" ..G4PSQL_Format( Escape( sid ) ) )
function q2:onSuccess( data2 )
Msg( "SteamID (" .. sid .. ") Banned!\n" )
ULib.tsayColor(_, 1, Color(0,0,0,255), "(", Color(255,0,0,255), sid, Color(0,0,0,255), ") ", Color(255,255,255,255), "was globally banned by ", bacolor, badmin, Color(255,255,255,255), ".")
end
function q2:onError( Q, E )
ServerLog( "ERROR!!! " .. Q .. "\n" )
ServerLog( "ERROR!!! " .. E .. "\n" )
end
q2:start()
else
Msg("No Entry Found")
Msg("No Results Found ... Creating Entry\n")
local q3 = G4PSQL.db:query( "INSERT INTO " ..DATABSE_TABLE.. " ( steamid, pname, pgroup, lastplayed, banned, badmin ) VALUES( " ..G4PSQL_Format( Escape( sid ) ) .. ", " ..G4PSQL_Format( Escape( "ADMIN ENTERED" ) ) .. ", " .. G4PSQL_Format( Escape( "user" ) ) .. ", " ..G4PSQL_Format( Escape( tostring("NEVER") ) ) .. ", " ..G4PSQL_Format( Escape( "TRUE" ) ).. ", " ..G4PSQL_Format( Escape( "NONE" ) ).. " )" )
function q3:onSuccess( data3 )
Msg( "SteamID (" .. sid .. ") Banned!\n" )
ULib.tsayColor(_, 1, Color(0,0,0,255), "(", Color(255,0,0,255), sid, Color(0,0,0,255), ") ", Color(255,255,255,255), "was globally banned by ", bacolor, badmin, Color(255,255,255,255), ".")
end
function q3:onError( Q, E )
ServerLog( "ERROR!!! " .. Q .. "\n" )
ServerLog( "ERROR!!! " .. E .. "\n" )
end
q3:start()
end
end
q1:start()
end
else
Msg( "DATABASE NOT CONNECTED PLEASE TRY AGAIN!\n" )
G4PSQL_ConnectToDatabase()
end
else
Msg( "This command is reserved for administrators only!\n" )
end
end
concommand.Add( "g4p_ban", G4PSQL_Ban)
function G4PSQL_UnBan( ply, cmd, args )
local sid = args[1]
banmin = "NONE"
bacolor = Color(255,255,255,255)
if !IsValid( ply ) or ply:IsAdmin() then
if IsValid(ply) then
badmin = ply:Nick()
bacolor = team.GetColor(ply:Team())
else
badmin = "(Console)"
bacolor = Color(80,80,80,255)
end
if #args != 1 then
Msg("Not enough arguements!")
end
if G4PSQL.db:status() == 0 then
local q1 = G4PSQL.db:query("SELECT * FROM " ..DATABSE_TABLE.. " WHERE steamid = "..G4PSQL_Format( Escape( sid ) ).."")
function q1:onSuccess( data )
if data[1] then
if data[1]["banned"] == "TRUE" then
Msg( "UnBanning SteamID: (" ..sid .. ")\n" )
local q2 = G4PSQL.db:query("UPDATE " ..DATABSE_TABLE.. " SET banned="..G4PSQL_Format( Escape( "FALSE" ) ) .. " WHERE steamid=" ..G4PSQL_Format( Escape( sid ) ) )
function q2:onSuccess( data2 )
ULib.tsayColor(_, 1, Color(0,0,0,255), "(", Color(255,0,0,255), sid, Color(0,0,0,255), ") ", Color(255,255,255,255), "was unbanned by ", bacolor, badmin, Color(255,255,255,255), ".")
Msg( "SteamID (" .. sid .. ") Unbanned!\n" )
end
function q2:onError( Q, E )
ServerLog( "ERROR!!! " .. Q .. "\n" )
ServerLog( "ERROR!!! " .. E .. "\n" )
end
q2:start()
else
Msg("Player Found... but player isn't currently banned...\n")
end
else
Msg("No Entry Found")
Msg("Couldn't find SteamID: " .. sid .."\n")
end
end
q1:start()
else
Msg( "DATABASE NOT CONNECTED PLEASE TRY AGAIN!\n" )
G4PSQL_ConnectToDatabase()
end
else
Msg( "This command is reserved for administrators only!\n" )
end
end
concommand.Add( "g4p_unban", G4PSQL_UnBan)
The commands.. and you can change them in the lua are:
g4p_setgroup <player> <group>
It checks to make sure the group exists before trying to add them. You can also give it a SteamID for the playername if the player isn't connected to the server. Currenty restricted to superadmins only. you can edit this in the code.
g4p_ban <player>
You can give this a SteamID or a partial player name if the player is connected. Restricted to admins and above.
g4p_unban <steamID>
Checks to make sure the steamID is valid and actually listed as a ban. Restricted to admins and above.
Edit your table name and database info at the top of the file.
You will need the following columns in your database table.
steamid -Players SteamID
pname -Players Name (Will be updated every time the player joins if it's different)
pgroup -Players authentication group
lastplayed -The last time the player connected to the server
banned -Is the player banned?
badmin -The SteamID of the admin who banned the player.
Notes: This is not necessarily a ULib/ULX addon so it needs to be in your garrysmod/lua/autorun/server folder (if this doesn't exist, create it).
It overrides the ULib authentication.. so you will HAVE to use this for authentication as well as bans. It works fine though.
Note: All the commands work from the dedicated console as well. The ban and unban will only echo in game. The setgroup will only echo in the dedicated console if run from there. This isn't an error.. I just didn't much care to make it super fancy.. it gets me by for what I need.
There are a lot of commented out debug code. Some of it is useful if you want to uncomment it.