vision/src/client/ui/browser.lua

246 lines
6.7 KiB
Lua

local lg = assert( love.graphics )
local scene = assert( require 'client.scene' )
local textInput = assert( require 'client.ui.textinput' )
local button = assert( require 'client.ui.button' )
local packet = assert( require 'shared.packet' )
local menu = assert( require 'client.ui.menu' )
local strings = assert( require 'client.strings' )
local fonts = assert( require 'client.ui.fonts' )
local metaserver = assert ( require 'client.udp' )
local utf8 = assert( require 'utf8' )
local browser = { latest = 0, }
local test = assert( require 'client.test.browser' )
local font = fonts.font
local cw = fonts.font:getWidth( "w" )
local function joinServerCallback( button )
if button.ip and button.port then
return browser.joinIP( button.ip, button.port )
end
end
local function tryAdd( text, d, x )
local s = packet.getString( d )
return pcall( text.add, text, s, x ) or text:add( strings.utf8_error, x )
end
local function serverInfoToText( server )
local cw = fonts.font:getWidth( "w" )
local text = lg.newText( fonts.font )
tryAdd( text, server.svname, 0 )
tryAdd( text, server.map, cw * 16 )
text:add( tostring( server.ip ), cw * 32 )
text:add( server.port, cw * ( 32 + 12 ) )
text:add( server.players, cw * ( 32 + 12 + 6 ) )
text:add( server.capacity, cw * ( 32 + 12 + 9 ) )
return text
end
local serverList = menu.new{
name = "serverList",
buttons = {},
fg = lg.newMesh{
{ 0.5, 0, 0.5, 0, 0, 0, 0, 0 },
{ 1, 0, 1, 0, 1, 1, 1, 0.5 },
{ 1, 1, 1, 1, 1, 1, 1, 0.5 },
{ 0.5, 1, 0.5, 1, 0, 0, 0, 0 },
},
bg = lg.newMesh{
{ 0, 0, 0, 0, 0.4, 0.05, 0.0, 0.9 },
{ 1, 0, 1, 0, 0.8, 0.3, 0.1, 0.8 },
{ 1, 1, 1, 1, 0.7, 0.4, 0.1, 0.8 },
{ 0, 1, 0, 1, 0.4, 0.05, 0.05, 0.9 },
},
font = fonts.font,
subScene = true }
serverList.selected = false
serverList.x = 25
serverList.y = 0
serverList.h = 36
serverList.ips = {}
local serverButtons = serverList.buttons
local color = { 1, 0.6, 0.6, 0.1 }
local ti = textInput.new{
width = lg.getWidth(),
length = 20,
x = cw,
y = 35,
h = 55,
str = strings.ip_button,
font = fonts.midFont,
}
function ti:callback() return self:enterText( browser.joinIPString ) end
local headerButtons = {
button{
callback = function() return serverList.requestServers() end,
text = lg.newText( fonts.midFont, strings.refresh_button ) ,
color = color,
x = cw * 32,
y = 75,
w = 1400,
h = 36
},
button{
callback = function() return scene.mainmenu() end,
text = lg.newText( fonts.midFont, strings.mainmenu_button ) ,
color = color,
x = cw,
y = 75,
w = 1400,
},
ti,
button{ x = cw * 53, color = color, y = 135, text = lg.newText( font, strings.svinfo_capacity ) },
button{ x = cw * 50, color = color, y = 135, text = lg.newText( font, strings.svinfo_players ) },
button{ x = cw * 44, color = color, y = 135, text = lg.newText( font, strings.svinfo_port ) },
button{ x = cw * 32, color = color, y = 135, text = lg.newText( font, strings.svinfo_ip ) },
button{ x = cw * 16, color = color, y = 135, text = lg.newText( font, strings.svinfo_map ) },
button{ x = cw , color = color, y = 135, text = lg.newText( font, strings.svinfo_name ) },
}
for j, headerButton in ipairs( headerButtons ) do
serverButtons[j] = headerButton
end
function serverList.requestServers()
return metaserver.requestServerList()
end
function serverList.clear( )
for i = #headerButtons + 1, #serverButtons do serverButtons[i] = nil end
for ip in pairs( serverList.ips ) do serverList.ips[ip] = nil end
end
function serverList.add( serverInfo )
local y = 27 * ( #serverButtons - #headerButtons ) + 180
local ip = tostring( serverInfo.ip )
serverButtons[ #serverButtons + 1] = button{
space = 0,
x = cw,
w = lg.getWidth(),
y = y,
h = 24,
color = { 0.3 + 0.1 * (#serverButtons % 2), 0.3 + 0.1 * (#serverButtons % 2), 0.8, 0.3 },
callback = joinServerCallback,
serverInfo = serverInfo,
ip = ip,
port = serverInfo.port,
text = serverInfoToText( serverInfo ),
active = ( y < lg.getHeight() )}
serverList.ips[ ip ] = true
return serverList:paint()
end
local metaServerHandlers = setmetatable(
{
default = function() end,
heartbeat = serverList.clear,
serverInfo = serverList.add,
},
{__index = function( t ) return t.default end })
function serverList.scroll( up )
local minY = 170
local maxY = lg.getHeight() + 40
if #serverButtons > #headerButtons then
if up and serverButtons[ #headerButtons + 1 ].y > minY then return end
if ( not up ) and serverButtons[ #serverButtons ].y < maxY then return end
up = ( 27 / 3 ) * ( up and 1 or -1 )
for i = #headerButtons + 1, #serverButtons do
local sb = serverButtons[i]
sb.y = sb.y + up
sb.active = ( sb.y > minY ) and ( sb.y < maxY )
end
end
return serverList:paint()
end
browser.selected = false
function browser.draw()
lg.setColor( 1, 1, 1, 1 )
serverList.draw()
end
function browser.update( dt )
local p = metaserver.receiveMeta()
if not p then return end
print( "Receiving server list:", p )
local msgs, types = packet.deserialise( p )
for i = 1, #msgs do metaServerHandlers[types[i]]( msgs[i] ) end
end
function browser.onLoad( )
serverList:onLoad()
lg.setColor( 1, 1, 1, 1 )
end
function browser.mousemoved( x, y, dx, dy, istouch )
return serverList.mousemoved( x, y, dx, dy, istouch )
end
function browser.wheelmoved( x, y )
if y == 0 then return end
return serverList.scroll( ( y > 0 ) )
end
function browser.resize( x, y )
serverList.resize( x, y )
for i, button in ipairs( serverButtons ) do
button.w = x
end
return serverList:paint()
end
function browser.mousepressed(x, y, button, istouch, pressed)
return serverList.mousepressed( x, y, button, istouch, pressed )
end
function browser.joinIPString( s )
--Parse IP address and port from string. If it's valid, join the server.
print( "browser: entered IP and port", s )
if not s then return end
ti:clear()
local ip, port = s:match '(%d+%.%d+%.%d+%.%d+)', s:match ':(%d+)'
print( "browser:", "ip:", ip, port )
if ip and port then return browser.joinIP( ip, port ) end
end
function browser.joinIP( ip, port )
print( "Joining server:", ip, port )
return scene.loadScene( scene.connecting, { ip = ip, port = port } )
end
function browser.keypressed( key, code, isRepeat )
local y = serverList.getSelectedButton()
if code == "escape" then return scene.mainmenu() end
if y and code == "down" and y.y > lg.getHeight() - 100 then
for i = 1, 3 do serverList.scroll( false ) end
end
if y and code == "up" and y.y > 180 and y.y < 250 then
for i = 1, 3 do serverList.scroll( true ) end
end
return serverList.keypressed( key, code, isRepeat )
end
scene.browser = browser
return browser