123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268 |
- import
- sockets, streams, tables, times, math, strutils, json, os, md5,
- sfml, sfml_vector, sfml_colors,
- streams_enh, input_helpers, zlib_helpers, client_helpers, sg_packets, sg_assets, sg_gui
- type
- TClientSettings = object
- resolution*: TVideoMode
- offlineFile: string
- dirserver: tuple[host: string, port: TPort]
- website*: string
- var
- clientSettings: TClientSettings
- gui = newGuiContainer()
- zonelist = newGuiContainer()
- u_alias, u_passwd: PTextEntry
- activeInput = 0
- aliasText, passwdText: PText
- fpsTimer: PButton
- loginBtn: PButton
- playBtn: PButton
- keyClient = newKeyClient("lobby")
- showZonelist = false
- chatInput*: PTextEntry
- messageArea*: PMessageArea
- mySession*: ScLogin
- var
- dirServer: PServer
- zone*: PServer
- activeServer: PServer
- bConnected = false
- outgoing = newStringStream("")
- downloadProgress: PButton
- connectionButtons: seq[PButton] #buttons that depend on connection to function
- template dispmessage(m: expr): stmt =
- messageArea.add(m)
- proc connectZone(host: string; port: TPort)
- proc connectToDirserv()
- proc writePkt[T](pid: PacketID; p: var T) =
- if activeServer.isNil: return
- activeServer.writePkt pid, p
- proc setConnected(state: bool) =
- if state:
- bConnected = true
- for b in connectionButtons: enable(b)
- else:
- bConnected = false
- for b in connectionButtons: disable(b)
- proc setActiveZone(ind: int; zone: ScZoneRecord) =
- #highlight it or something
- dispmessage("Selected " & zone.name)
- connectZone(zone.ip, zone.port)
- playBtn.enable()
- proc handleChat(serv: PServer; s: PStream) =
- var msg = readScChat(s)
- messageArea.add(msg)
- proc connectToDirserv() =
- if dirServer.isNil:
- dirServer = newServerConnection(clientSettings.dirserver.host, clientSettings.dirserver.port)
- dirServer.handlers[HHello] = proc(serv: PServer; s: PStream) =
- let msg = readScHello(s)
- dispMessage(msg.resp)
- setConnected(true)
- dirServer.handlers[HLogin] = proc(serv: PServer; s: PStream) =
- mySession = readScLogin(s)
- ##do something here
- dirServer.handlers[HZonelist] = proc(serv: PServer; s: PStream) =
- var
- info = readScZonelist(s)
- zones = info.zones
- if zones.len > 0:
- zonelist.clearButtons()
- var pos = vec2f(0.0, 0.0)
- zonelist.newButton(
- text = "Zonelist - "& info.network,
- position = pos,
- onClick = proc(b: PButton) =
- dispmessage("Click on header"))
- pos.y += 20
- for i in 0..zones.len - 1:
- var z = zones[i]
- zonelist.newButton(
- text = z.name, position = pos,
- onClick = proc(b: PButton) =
- setActiveZone(i, z))
- pos.y += 20
- showZonelist = true
- dirServer.handlers[HPoing] = proc(serv: PServer; s: PStream) =
- var ping = readPoing(s)
- dispmessage("Ping: "& $ping.time)
- ping.time = epochTime().float32
- serv.writePkt HPoing, ping
- dirServer.handlers[HChat] = handleChat
- dirServer.handlers[HFileChallenge] = handleFileChallenge
- var hello = newCsHello()
- dirServer.writePkt HHello, hello
- activeServer = dirServer
- proc zoneListReq() =
- var pkt = newCsZonelist("sup")
- writePkt HZonelist, pkt
- ##key handlers
- keyClient.registerHandler(MouseMiddle, down, proc() =
- gui.setPosition(getMousePos()))
- keyClient.registerHandler(KeyO, down, proc() =
- if keyPressed(KeyRShift): echo(repr(outgoing)))
- keyClient.registerHandler(KeyTab, down, proc() =
- activeInput = (activeInput + 1) mod 2) #does this work?
- keyClient.registerHandler(MouseLeft, down, proc() =
- let p = getMousePos()
- gui.click(p)
- if showZonelist: zonelist.click(p))
- var mptext = newText("", guiFont, 16)
- keyClient.registerHandler(MouseRight, down, proc() =
- let p = getMousePos()
- mptext.setPosition(p)
- mptext.setString("($1,$2)"%[$p.x.int,$p.y.int]))
- proc connectZone(host: string, port: TPort) =
- echo "Connecting to zone at ", host, ':', port
- if zone.isNil:
- zone = newServerConnection(host, port)
- zone.handlers[HFileChallenge] = handleFileChallenge
- zone.handlers[HChallengeResult] = handleFileChallengeResult
- zone.handlers[HFileTransfer] = handleFileTransfer
- zone.handlers[HChat] = handleChat
- else:
- zone.sock.connect(host, port)
- var hello = newCsHello()
- zone.writePkt HHello, hello
- proc lobbyReady*() =
- keyClient.setActive()
- gui.setActive(u_alias)
- proc tryConnect*(b: PButton) =
- connectToDirserv()
- proc tryLogin*(b: PButton) =
- var login = newCsLogin(
- alias = u_alias.getText(),
- passwd = u_passwd.getText())
- writePkt HLogin, login
- proc tryTransition*(b: PButton) =
- ##check if we're logged in
- #<implementation censored by the church>
- #var joinReq = newCsJ
- zone.writePkt HZoneJoinReq, mySession
- #var errors: seq[string] = @[]
- #if loadSettings("", errors):
- # transition()
- #else:
- # for e in errors: dispmessage(e)
- proc playOffline*(b: PButton) =
- var errors: seq[string] = @[]
- if loadSettingsFromFile(clientSettings.offlineFile, errors):
- transition()
- else:
- dispmessage("Errors reading the file ("& clientSettings.offlineFile &"):")
- for e in errors: dispmessage(e)
- proc getClientSettings*(): TClientSettings =
- result = clientSettings
- proc lobbyInit*() =
- var s = json.parseFile("./client_settings.json")
- clientSettings.offlineFile = "data/"
- clientSettings.offlineFile.add s["default-file"].str
- let dirserv = s["directory-server"]
- clientSettings.dirserver.host = dirserv["host"].str
- clientSettings.dirserver.port = dirserv["port"].num.TPort
- clientSettings.resolution.width = s["resolution"][0].num.cint
- clientSettings.resolution.height= s["resolution"][1].num.cint
- clientSettings.resolution.bitsPerPixel = s["resolution"][2].num.cint
- clientSettings.website = s["website"].str
- zonelist.setPosition(vec2f(200.0, 100.0))
- connectionButtons = @[]
- downloadProgress = gui.newButton(
- text = "", position = vec2f(10, 130), onClick = nil)
- downloadProgress.bg.setFillColor(color(34, 139, 34))
- downloadProgress.bg.setSize(vec2f(0, 0))
- var pos = vec2f(10, 10)
- u_alias = gui.newTextEntry(
- if s.existsKey("alias"): s["alias"].str else: "alias",
- pos)
- pos.y += 20
- u_passwd = gui.newTextEntry("buzz", pos)
- pos.y += 20
- connectionButtons.add(gui.newButton(
- text = "Login",
- position = pos,
- onClick = tryLogin,
- startEnabled = false))
- pos.y += 20
- fpsText.setPosition(pos)
- playBtn = gui.newButton(
- text = "Play",
- position = vec2f(680.0, 8.0),
- onClick = tryTransition,
- startEnabled = false)
- gui.newButton(
- text = "Play Offline",
- position = vec2f(680.0, 28.0),
- onClick = playOffline)
- fpsTimer = gui.newButton(
- text = "FPS: ",
- position = vec2f(10.0, 70.0),
- onClick = proc(b: PButton) = nil)
- gui.newButton(
- text = "Connect",
- position = vec2f(10.0, 90.0),
- onClick = tryConnect)
- connectionButtons.add(gui.newButton(
- text = "Test Chat",
- position = vec2f(10.0, 110.0),
- onClick = (proc(b: PButton) =
- var pkt = newCsChat(text = "ohai")
- writePkt HChat, pkt),
- startEnabled = false))
- chatInput = gui.newTextEntry("...", vec2f(10.0, 575.0), proc() =
- sendChat dirServer, chatInput.getText()
- chatInput.clearText())
- messageArea = gui.newMessageArea(vec2f(10.0, 575.0 - 20.0))
- messageArea.sizeVisible = 25
- gui.newButton(text = "Scrollback + 1", position = vec2f(185, 10), onClick = proc(b: PButton) =
- messageArea.scrollBack += 1
- update(messageArea))
- gui.newButton(text = "Scrollback - 1", position = vec2f(185+160, 10), onClick = proc(b: PButton) =
- messageArea.scrollBack -= 1
- update(messageArea))
- gui.newButton(text = "Flood msg area", position = vec2f(185, 30), onClick = proc(b: PButton) =
- for i in 0..< 30:
- dispMessage($i))
- var i = 0
- proc lobbyUpdate*(dt: float) =
- #let res = disp.poll()
- gui.update(dt)
- i = (i + 1) mod 60
- if i == 0:
- fpsTimer.setString("FPS: "& $round(1.0/dt))
- if not pollServer(dirServer, 5) and bConnected:
- setConnected(false)
- echo("Lost connection")
- discard pollServer(zone, 5)
- proc lobbyDraw*(window: PRenderWindow) =
- window.clear(Black)
- window.draw messageArea
- window.draw mptext
- window.draw gui
- if showZonelist: window.draw zonelist
- window.display()
|