Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -------------------------
- -- Game Server Library --
- -------------------------
- require_once( "events" )
- require_once( "handles" )
- require_once( "concommand" )
- gameserver = {}
- local clientVersion = ""
- local PlayerList = {}
- local metaPly = {}
- metaPly.__index = metaPly
- local asciiMode = true
- function metaPly:New()
- self.Valid = true
- local Disconnect, Data
- function Disconnect( conn )
- if not self.Valid then return end
- local hdl = Handle( conn, "connection" )
- if not (hdl:GetID() == self._hdl:GetID()) then return end
- for id, ply in pairs( PlayerList ) do
- if (ply == self) then
- table.remove( PlayerList, id )
- break
- end
- end
- events.Unhook( "OnDisconnect", Disconnect )
- events.Unhook( "OnConnectionData", Data )
- events.Raise( "PlayerDisconnect", self )
- --print( "Player object deleted!" )
- self.Valid = false
- end
- function Data( conn, pckt )
- if not self.Valid then return print( "Received data for invalid player object" ) end
- local hdl = Handle( conn, "connection" )
- if not (hdl:GetID() == self._hdl:GetID()) then return print( "Handle mismatch" ) end
- --print( "Handling data..." )
- local data = Handle( pckt, "netpacket" )
- self:HandleData( data )
- end
- events.Hook( "OnDisconnect", Disconnect )
- events.Hook( "OnConnectionData", Data )
- print( "Player object created!" )
- self:SetAuthLevel( 0 )
- self:SetNick( "Unconnected" )
- self.lastactivity = CurTime()
- self.ping = 0
- self:Ping()
- end
- function metaPly:HandleData( pckt ) -- This handles CLIENT -> SERVER data
- self.lastactivity = CurTime()
- local id = pckt:ReadByte()
- if (asciiMode) then id = tonumber( string.char( id ) ) end
- if (id == 0) then -- Ping
- local pk = self:StartPacket()
- self:WriteByte( 1 ) -- Pong
- pk:WriteString( "PONG" )
- self:Send()
- end
- if (id == 1) then -- Pong
- if self.pingstart then
- self.ping = math.ceil( (CurTime()-self.pingstart)*1000 )
- self.pingstart = nil
- --print( "[" .. self:GetID() .. "] Ping: " .. self.ping )
- else
- self:Error( "PONG WITHOUT PING" )
- end
- end
- if (id == 2) then -- Version auth
- local str = pckt:ReadString()
- if (str == clientVersion) then
- local pk = self:StartPacket()
- self:WriteByte( 2 ) -- Version auth reply
- self:WriteByte( 1 ) -- Success
- pk:WriteString( clientVersion )
- self:Send()
- self:IncAuth( 1 )
- else
- self:Error( "BAD CLIENT VERSION (" .. str .. ")" )
- local pk = self:StartPacket()
- self:WriteByte( 2 ) -- Version auth reply
- self:WriteByte( 0 ) -- Failed
- pk:WriteString( clientVersion )
- self:Send()
- end
- end
- if (id == 3) then -- Disconnect
- self:Drop( "Disconnect by user." )
- return -- No leftover packet for you
- end
- if (id == 4) then -- User auth
- if (self:GetAuthLevel() == 1) then
- local user = pckt:ReadString()
- local pass = pckt:ReadString()
- -- TODO: Proper auth
- if (string.lower( user ) == "guest") and (pass == "guest") then
- self:IncAuth( 2 )
- self:SetNick( user )
- local pk = self:StartPacket()
- self:WriteByte( 4 ) -- User auth reply
- self:WriteByte( 1 ) -- Success
- self:Send()
- gameserver.BroadcastChat( 0, self:GetNick() .. " has connected!" )
- else
- local pk = self:StartPacket()
- self:WriteByte( 4 ) -- User auth reply
- self:WriteByte( 0 ) -- Failed
- self:Send()
- self.FailedUserAuth = (self.FailedUserAuth or 0) + 1
- if (self.FailedUserAuth == 3) then self:Drop( "Too many failed user auth attempts." ) end
- end
- else
- self:Error( "TRIED TO USER AUTH BEFORE VERSION AUTH" )
- end
- end
- if (id == 5) then -- Chat message
- if (self:IsAuthLevel( 2 )) then
- gameserver.BroadcastChat( 1, self:GetNick() .. ": " .. pckt:ReadString() )
- else
- self:Error( "TRIED TO CHAT BEFORE USER AUTH" )
- end
- end
- local leftover = pckt:GetSize() - pckt:GetCursorPos()
- if (leftover > 0) then
- self:HandleData( pckt )
- end
- end
- function metaPly:Error( msg )
- Msg( self:GetInfo() .. " --- " .. msg )
- end
- function metaPly:Drop( reason )
- local pk = self:StartPacket()
- self:WriteByte( 3 ) -- Dropped with reason
- pk:WriteString( reason )
- self:Send()
- self:Error( "Dropped ('" .. reason .. "')" )
- self._hdl:Close()
- self.Dropped = true
- end
- function metaPly:StartPacket()
- local raw = CreatePacket()
- local hdl = Handle( raw, "netpacket" )
- self._outgoing = hdl
- return hdl
- end
- function metaPly:Send( packet )
- if not self.Valid then return end
- if self.Dropped then return end
- if not packet then packet = self._outgoing end
- self._hdl:SendPacket( packet._o )
- end
- function metaPly:WriteByte( val )
- if (asciiMode) then
- self._outgoing:WriteByte( string.byte( tostring( val ) ) )
- else
- self._outgoing:WriteByte( val )
- end
- end
- function metaPly:SetNick( name )
- self.nick = name
- end
- function metaPly:GetNick()
- return self.nick
- end
- function metaPly:GetPing()
- return self.ping
- end
- function metaPly:GetIP()
- return self._hdl:GetRemoteIP()
- end
- function metaPly:GetID()
- return self._hdl:GetID()
- end
- function metaPly:Ping()
- if (self.pingstart) then return end
- self.pingstart = CurTime()
- local pk = self:StartPacket()
- self:WriteByte( 0 )
- pk:WriteString( "PING" )
- self:Send()
- end
- function metaPly:SetAuthLevel( lvl )
- self.authlvl = lvl
- end
- function metaPly:IncAuth( min )
- self.authlvl = ((self.authlvl < min) and min) or self.authlvl
- end
- function metaPly:IsAuthLevel( lvl )
- return self.authlvl >= lvl
- end
- function metaPly:GetAuthLevel()
- return self.authlvl
- end
- function metaPly:GetInfo()
- return self:GetID() .. ": IP=" .. self:GetIP() .. ", PING=" .. self:GetPing()
- end
- function metaPly:SendChat( channel, msg )
- local pk = self:StartPacket()
- self:WriteByte( 5 ) -- Chat message
- self:WriteByte( channel ) -- Channel ID
- pk:WriteString( msg )
- self:Send()
- end
- function gameserver.SetClientVersion( str )
- clientVersion = str
- end
- function gameserver.PrintInfo()
- for i=1, #PlayerList do
- local ply = PlayerList[i]
- print( tostring( ply ) )
- Msg( ply:GetInfo() )
- end
- end
- function gameserver.GetPlayers()
- return PlayerList
- end
- function gameserver.SendToAll( pckt )
- for i=1, #PlayerList do
- local ply = PlayerList[i]
- ply:Send( pckt )
- end
- end
- function gameserver.BroadcastChat( channel, msg )
- print( "[" .. channel .. "] " .. msg )
- for i=1, #PlayerList do
- local ply = PlayerList[i]
- ply:SendChat( channel, msg )
- end
- end
- local function cmdPrintInfo()
- gameserver.PrintInfo()
- end
- command.Register( "printinfo", cmdPrintInfo )
- local function evConnect( port, rawconn )
- local hdl = Handle( rawconn, "connection" )
- local o = {}
- setmetatable( o, metaPly )
- o._hdl = hdl
- o:New()
- table.insert( PlayerList, o )
- events.Raise( "PlayerConnect", o )
- end
- events.Hook( "OnConnection", evConnect )
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement