Skip to content

Instantly share code, notes, and snippets.

@rejax
Created October 16, 2014 10:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rejax/07349fd16a3906a921fd to your computer and use it in GitHub Desktop.
Save rejax/07349fd16a3906a921fd to your computer and use it in GitHub Desktop.
20 minute server hopper
local config = {
retrieve_info = true, -- retrieve external info about the server(s)?
retrieve_rate_minutes = .05, -- set to 0 to get info when opening the menu
servers = {
{ name = "Default", ip = "localhost", port = 27015 },
},
bgcolor = Color( 70, 70, 70 ),
bgcolor_hover = Color( 90, 90, 90 ),
spacey = 5,
framew = 300,
frameh = 400,
}
local get = "http://uppercutservers.com/rejax/getserver.php?ip=%s&port=%s"
local external = { servers = {} }
local function RetrieveInfo( callback )
for k, server in next, config.servers do
http.Fetch( get:format( server.ip, server.port ), function( body )
local result = util.JSONToTable( body )
if not result or not result.status then return end
external.servers[server.ip] = {
name = result.info.HostName,
map = result.info.Map,
players = result.info.Players,
maxplayers = result.info.MaxPlayers,
port = server.port,
}
if callback then callback( server.ip, external.servers[server.ip] ) end
end )
end
end
if config.retrieve_info and config.retrieve_rate_minutes ~= 0 then
timer.Create( "serverhopper_retrieve", config.retrieve_rate_minutes * 60, 0, RetrieveInfo )
end
local function OpenMenu()
local frame = vgui.Create( "DFrame" )
frame:SetSize( config.framew, config.frameh )
frame:Center()
frame:SetTitle( "Servers - Click to Connect" )
frame:ShowCloseButton( false )
frame:MakePopup()
frame.Paint = function( s, w, h )
surface.SetDrawColor( 50, 50, 50 )
surface.DrawRect( 0, 0, w, h )
end
local cb = vgui.Create( "DButton", frame )
cb:SetPos( frame:GetWide() - 50, 0 )
cb:SetSize( 50, 20 )
cb:SetText( "" )
cb.DoClick = function() frame:Close() end
cb.Paint = function( s, w, h ) surface.SetDrawColor( 120, 60, 60 ) surface.DrawRect( 0, 0, w, h ) end
local scroll = vgui.Create( "DScrollPanel", frame )
scroll:SetPos( 2, 25 )
scroll:SetSize( config.framew, config.frameh - 25 )
scroll.PerformLayout = function( s )
DScrollPanel.PerformLayout( s )
local bar = s:GetVBar()
if not bar then return end
bar.Paint = function() end
local _w = 8
local function draw( _, w, h )
surface.SetDrawColor( 120, 120, 120, 230 )
surface.DrawRect( w-_w, 0, _w, h )
end
bar.btnUp.Paint = draw
bar.btnDown.Paint = draw
bar.btnGrip.Paint = draw
end
local servers = vgui.Create( "DIconLayout", scroll )
servers:SetSize( config.framew, scroll:GetTall() - 5 )
servers:SetSpaceX( frame:GetWide() )
servers:SetSpaceY( config.spacey )
servers.FixLayout = function( s )
for _, child in next, s:GetChildren() do
child:SetSize( s:GetWide() - 4, 80 )
end
end
local function AddServer( ip, port, name, players, maxplayers, map )
if not IsValid( servers ) then return end
local pnl = servers:Add( "serverhopper_entry" )
pnl:SetVar( "name", name )
pnl.internet = players ~= nil
pnl:SetVar( "players", players )
pnl:SetVar( "maxplayers", maxplayers )
pnl:SetVar( "map", map )
pnl.ip = ip .. ":" .. port
servers:FixLayout()
end
if config.retrieve_info then
if config.retrieve_rate_minutes == 0 then
RetrieveInfo( function( ip, server )
AddServer( ip, server.port, server.name, server.players, server.maxplayers, server.map )
end )
else
for ip, server in next, external.servers do
AddServer( ip, server.port, server.name, server.players, server.maxplayers, server.map:gsub( "%.bsp$", "" ) )
end
end
else
for _, server in next, config.servers do
AddServer( server.ip, server.port, server.name, 20, 24, "rp_downtown" )
end
end
end
concommand.Add( "servers", OpenMenu )
local function OnChat( ply, text )
if text:find( "[!/]server[s]?$" ) then
if ply == LocalPlayer() then OpenMenu() end
return true
end
end
hook.Add( "OnPlayerChat", "serverhopper_onchat", OnChat )
local PANEL = {}
local sml, lrg = 18, 22
for i = sml, lrg, lrg - sml do
surface.CreateFont( "serverhopper_" .. i, {
font = "Roboto",
size = i,
weight = 600
} )
end
function PANEL:Init()
self.vars = {}
self.vars.name = ""
self.vars.players = ""
self.vars.maxplayers = ""
self.vars.map = ""
self.ip = false
self:SetSize( config.framew - 5, 80 )
end
function PANEL:SetVar( name, val )
self.vars[name] = val
end
function PANEL:GetVarSize( name )
surface.SetFont( "serverhopper_" .. ( name == "name" and lrg or sml ) )
return surface.GetTextSize( self.vars[name] )
end
function PANEL:OnCursorEntered() self.In = true end
function PANEL:OnCursorExited() self.In = false end
function PANEL:OnMousePressed( m )
if self.ip and m == MOUSE_LEFT then LocalPlayer():ConCommand( "connect " .. self.ip ) end
end
local base = "http://image.www.gametracker.com/images/maps/160x120/garrysmod/%s.jpg"
function PANEL:GetMapURL() -- eh
return base:format( self.vars.map:gsub( "%.bsp$", "" ) )
end
local bg = config.bgcolor
local bg_hover = config.bgcolor_hover
function PANEL:Paint( _w, _h )
surface.SetDrawColor( self.In and bg_hover or bg )
surface.DrawRect( 0, 0, _w, _h )
surface.SetTextColor( color_white )
local w, h = self:GetVarSize( "name" )
surface.SetTextPos( 10, 5 )
surface.DrawText( self.vars.name )
if self.internet then
local w2, h2 = self:GetVarSize( "players" )
surface.SetTextPos( 10, h + 10 )
surface.DrawText( self.vars.players .. "/" .. self.vars.maxplayers )
self:GetVarSize( "map" )
surface.SetTextPos( 10, h + h2 + 12 )
surface.DrawText( self.vars.map )
end
end
vgui.Register( "serverhopper_entry", PANEL, "Panel" )
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment