· 9 years ago · Dec 18, 2016, 07:20 AM
1-- Written by Team Ulysses, http://ulyssesmod.net/
2-- Modified by ACProdigy for MySQL operation
3-- Modified by MRDRMUFN for gm_mysqloo support
4-- Modified by TweaK for more reliable operation
5-- Modified by xbeastguyx for uploading current data to MySQL and changing data storage method.
6
7if not SERVER then return end
8
9module( "Utime", package.seeall )
10
11require( "mysqloo" )
12
13----- Config -----
14
15local LockPassword = "asdasdasdasd" -- During the upload process of data, it should not be tampered with. This clears the server and locks it up with this password, preventing data changes during upload.
16local ShowMaintenance = true -- Place [MAINTENANCE] tag in front of your server name? Suggested to show players what you're doing.
17
18local RefreshTime = 67 -- Amount of time between each query to the database.
19
20----- Database connection details -----
21
22local DATABASE_HOST = ""
23local DATABASE_USERNAME = ""
24local DATABASE_PASSWORD = ""
25local DATABASE_PORT = 3306
26local DATABASE_NAME = ""
27
28--=== DO NOT EDIT BELOW THIS POINT ===--
29
30local utime_welcome = CreateConVar( "utime_welcome", "1", FCVAR_ARCHIVE )
31local queue = {}
32
33local function CMP( text ) -- Console Message Positive
34 MsgC( Color( 255, 255, 255 ), "[", Color( 255, 50, 50 ), "UTime-MySQL", Color( 255, 255, 255 ), "]", Color( 50, 255, 50 ), " " .. text .. "\n" )
35end
36
37local function CMN( text ) -- Console Message Negative
38 MsgC( Color( 255, 255, 255 ), "[", Color( 50, 255, 50 ), "UTime-MySQL", Color( 255, 255, 255 ), "]", Color( 255, 0, 0 ), " " .. text .. "\n" )
39end
40
41local db = mysqloo.connect( DATABASE_HOST, DATABASE_USERNAME, DATABASE_PASSWORD, DATABASE_NAME, DATABASE_PORT )
42
43local function query( str, callback )
44 local q = db:query( str )
45
46 function q:onSuccess( data )
47 callback( data )
48 end
49
50 function q:onError( err )
51 if db:status() == mysqloo.DATABASE_NOT_CONNECTED then
52 table.insert( queue, { str, callback } )
53 db:connect()
54 return end
55
56 CMN( "Failed to connect to the database!" )
57 CMN( "The error returned was: " .. err )
58 end
59
60 q:start()
61end
62
63function db:onConnected()
64 CMP( "Sucessfully connected to database!" )
65
66 for k, v in pairs( queue ) do
67 query( v[ 1 ], v[ 2 ] )
68 end
69
70 queue = {}
71end
72
73function db:onConnectionFailed( err )
74 CMN( "Failed to connect to the database!" )
75 CMN( "The error returned was: " .. err )
76end
77
78db:connect()
79
80-- Check that the table exists, create it if not
81table.insert( queue, { "SHOW TABLES LIKE 'utime'", function( data )
82 if table.Count( data ) < 1 then -- the table doesn't exist
83 query( "CREATE TABLE utime (id INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, player INTEGER UNSIGNED NOT NULL, totaltime INTEGER UNSIGNED NOT NULL, lastvisit INTEGER UNSIGNED NOT NULL, PRIMARY KEY (id))", function( data )
84 CMP( "Sucessfully created table!" )
85 end )
86 end
87end } )
88
89function PlayerJoined( ply )
90 local uid = ply:UniqueID()
91
92 query( "SELECT totaltime, lastvisit FROM utime WHERE player = " .. uid, function( data )
93 local time = 0
94
95 if table.Count( data ) > 0 then -- player exists
96 row = data[ 1 ]
97 if utime_welcome:GetBool() then
98 ULib.tsay( ply, "С возвращением! Ð’ поÑледний раз вы играли здеÑÑŒ " .. os.date( "%a, %b %d, %Y", row.lastvisit ) )
99 end
100
101 -- update lastvisit time
102 query( "UPDATE utime SET lastvisit = " .. os.time() .. " WHERE player = " .. uid, function() end )
103
104 time = row.totaltime
105 else -- player does not exist
106 if utime_welcome:GetBool() then
107 ULib.tsay( ply, "Добро пожаловать на наш Ñервер " .. ply:Nick() .. "!" )
108 end
109
110 -- create the player
111 query( "INSERT into utime ( player, totaltime, lastvisit ) VALUES ( " ..
112 uid .. ", 0, " .. os.time() .. " )",
113 function() print( "[UTime] Successfully created new player " .. ply:Nick() .. "." ) end )
114 end
115
116 ply:SetUTime( time )
117 ply:SetUTimeStart( CurTime() )
118 ply.UTimeLoaded = true
119 end )
120end
121hook.Add( "PlayerInitialSpawn", "UTimeInitialSpawn", PlayerJoined )
122
123function UpdatePlayer( ply )
124 query( "UPDATE utime SET totaltime = " .. math.floor( ply:GetUTimeTotalTime() ) .. " WHERE player = " .. ply:UniqueID() .. ";", function() end )
125end
126hook.Add( "PlayerDisconnected", "UTimeDisconnect", UpdatePlayer )
127
128function UpdateAll()
129 for _, ply in pairs( player.GetAll() ) do
130 if IsValid( ply ) and ply:IsConnected() and ply.UTimeLoaded then
131 UpdatePlayer( ply )
132 end
133 end
134end
135timer.Create( "UTimeTimer", RefreshTime, 0, UpdateAll )
136
137concommand.Add( "uploadutime", function( ply )
138 if !file.Exists( "utime_mysql.txt", "DATA" ) then
139 file.Write( "utime_mysql.txt", "" )
140
141 for k, v in pairs( player.GetAll() ) do
142 v:Kick( "SERVER MAINTENANCE, DO NOT JOIN!" )
143 end
144
145 RunConsoleCommand( "sv_password", LockPassword )
146
147 if ShowMaintenance then
148 RunConsoleCommand( "hostname", "[MAINTENANCE] " .. GetHostName() )
149 end
150
151 CMP( "UPLOADING DATA TO MYSQL, LAG MAY OCCUR!" )
152
153 if IsValid( ply ) then return end
154 local row = sql.QueryValue( "SELECT MAX ( rowid ) FROM utime;" )
155 local players = {}
156 for i = 1, tonumber( row ) do
157 local player = sql.QueryValue( "SELECT player FROM utime WHERE rowid = " .. i .. ";" )
158 local totaltime = sql.QueryValue( "SELECT totaltime FROM utime WHERE rowid = " .. i .. ";" )
159 local lastvisit = sql.QueryValue( "SELECT lastvisit FROM utime WHERE rowid = " .. i .. ";" )
160 players[i] = { player, totaltime, lastvisit }
161 end
162 for k, v in pairs( players ) do
163 local query = db:query( "INSERT into utime ( `player`, `totaltime`, `lastvisit` ) VALUES( " .. tonumber( v[1] ) .. ", " .. tonumber( v[2] ) .. ", " .. tonumber( v[3] ) .. " );" )
164 query:start()
165 end
166 CMP( "Data sucessfully uploaded!\nServer should restart in 10 seconds! If it does not, restart it manually!" )
167 timer.Simple( 10, function()
168 RunConsoleCommand( "_restart" )
169 end )
170 else
171 CMN( "You have run this process previously, doing so again will overwrite all previous data. To continue with the process, please type 'utime_continue' and rerun this command." )
172 end
173end )
174
175concommand.Add( "utime_continue", function( ply )
176 if IsValid( ply ) then return end
177 if file.Exists( "utime_mysql.txt", "DATA" ) then
178 file.Delete( "utime_mysql.txt" )
179 CMP( "Sucessfully deleted the file. Please rerun the 'uploadutime' command!" )
180 else
181 CMN( "You have not run the uploadutime command yet!" )
182 end
183end )
184
185concommand.Add( "utime_cleardb", function( ply )
186 if IsValid( ply ) then return end
187 local query = db:query( "TRUNCATE TABLE utime" )
188 query:start()
189 CMP( "Sucessfully cleared the table!" )
190end )