enet_client.nim 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. import enet, strutils,
  2. sfml, sfml_colors, sg_gui, input_helpers,
  3. math_helpers, sg_packets, estreams, tables,
  4. json, sg_assets, client_helpers
  5. if enetInit() != 0:
  6. quit "Could not initialize ENet"
  7. type
  8. TClientSettings = object
  9. resolution*: TVideoMode
  10. offlineFile: string
  11. dirserver: tuple[host: string, port: int16]
  12. website*: string
  13. var
  14. clientSettings: TClientSettings
  15. event: enet.TEvent
  16. bConnected = false
  17. runServer = true
  18. gui = newGuiContainer()
  19. zonelist = newGuiContainer()
  20. kc = newKeyClient(setActive = true)
  21. clock = newClock()
  22. chatBox: PMessageArea
  23. chatInput: PTextEntry
  24. loginBtn, playBtn: PButton
  25. fpsText = newText("", guiFont, 18)
  26. connectionButtons: seq[PButton]
  27. connectButton: PButton
  28. u_alias, u_passwd: PTextEntry
  29. dirServer: PServer
  30. zone: PServer
  31. showZoneList = false
  32. myCreds = newScLogin(0, "", "") ##my session token
  33. proc handleChat(server: PServer; buf: PBuffer) =
  34. let msg = readScChat(buf)
  35. chatBox.add msg
  36. proc handlePlayerLogin(server: PServer; buf: PBuffer) =
  37. let login = readScLogin(buf)
  38. myCreds = login
  39. echo("I am ", $myCreds)
  40. kc.registerHandler MouseLeft, down, proc() =
  41. gui.click(input_helpers.getMousePos())
  42. block:
  43. var pos = vec2f(15, 550)
  44. chatBox = gui.newMessageArea(pos)
  45. pos.y += 20
  46. chatInput = gui.newTextEntry("...", pos, proc() =
  47. sendPubChat dirServer, chatInput.getText()
  48. chatInput.clearText())
  49. gui.setActive(chatInput)
  50. proc dispMessage(args: varargs[string, `$`]) =
  51. var s = ""
  52. for it in items(args):
  53. s.add it
  54. chatbox.add(s)
  55. proc dispMessage(text: string) {.inline.} =
  56. chatbox.add(text)
  57. proc dispError(text: string) {.inline.} =
  58. chatBox.add(newScChat(kind = CError, text = text))
  59. proc updateButtons() =
  60. let conn = dirServer.connected
  61. for b in connectionButtons: setEnabled(b, conn)
  62. if conn:
  63. connectButton.setString "Disconnect"
  64. else:
  65. connectButton.setString "Connect"
  66. proc poll(serv: PServer; timeout: cuint = 30) =
  67. if serv.isNil or serv.host.isNil: return
  68. if serv.connected:
  69. while serv.host.hostService(event, timeout) > 0:
  70. case event.kind
  71. of EvtReceive:
  72. var buf = newBuffer(event.packet)
  73. serv.handlePackets(buf)
  74. event.packet.destroy()
  75. of EvtDisconnect:
  76. dispMessage "Disconnected"
  77. serv.connected = false
  78. event.peer.data = nil
  79. updateButtons()
  80. of EvtNone: discard
  81. else:
  82. echo repr(event)
  83. else:
  84. if serv.host.hostService(event, timeout) > 0 and event.kind == EvtConnect:
  85. dispMessage "Connected"
  86. serv.connected = true
  87. if serv.peer != event.peer:
  88. serv.peer = event.peer
  89. event.peer.data = serv
  90. updateButtons()
  91. proc tryLogin*(b: PButton) =
  92. var login = newCsLogin(
  93. alias = u_alias.getText(),
  94. passwd = u_passwd.getText())
  95. dirServer.send HLogin, login
  96. proc tryTransition*(b: PButton) =
  97. discard
  98. #zone.writePkt HZoneJoinReq, myCreds
  99. proc tryConnect*(b: PButton) =
  100. if not dirServer.connected:
  101. var error: string
  102. if not dirServer.connect(
  103. clientSettings.dirServer.host,
  104. clientSettings.dirServer.port,
  105. error):
  106. dispError(error)
  107. else:
  108. dirServer.peer.disconnect(1)
  109. proc playOffline*(b: PButton) =
  110. var errors: seq[string] = @[]
  111. if loadSettingsFromFile(clientSettings.offlineFile, errors):
  112. transition()
  113. else:
  114. dispMessage "Errors reading the file (", clientSettings.offlineFile, "):"
  115. for e in errors: dispError(e)
  116. proc getClientSettings*(): TClientSettings =
  117. result = clientSettings
  118. proc lobbyInit*() =
  119. var s = json.parseFile("./client_settings.json")
  120. clientSettings.offlineFile = "data/"
  121. clientSettings.offlineFile.add s["default-file"].str
  122. let dirserv = s["directory-server"]
  123. clientSettings.dirserver.host = dirserv["host"].str
  124. clientSettings.dirserver.port = dirserv["port"].num.int16
  125. clientSettings.resolution.width = s["resolution"][0].num.cint
  126. clientSettings.resolution.height= s["resolution"][1].num.cint
  127. clientSettings.resolution.bitsPerPixel = s["resolution"][2].num.cint
  128. clientSettings.website = s["website"].str
  129. zonelist.setPosition(vec2f(200.0, 100.0))
  130. connectionButtons = @[]
  131. var pos = vec2f(10, 10)
  132. u_alias = gui.newTextEntry(
  133. if s.hasKey("alias"): s["alias"].str else: "alias",
  134. pos)
  135. pos.y += 20
  136. u_passwd = gui.newTextEntry("buzz", pos)
  137. pos.y += 20
  138. connectionButtons.add(gui.newButton(
  139. text = "Login",
  140. position = pos,
  141. onClick = tryLogin,
  142. startEnabled = false))
  143. pos.y += 20
  144. fpsText.setPosition pos
  145. pos.y += 20
  146. connectButton = gui.newButton(
  147. text = "Connect",
  148. position = pos,
  149. onClick = tryConnect)
  150. pos.y += 20
  151. gui.newButton("Test Files", position = pos, onClick = proc(b: PButton) =
  152. var req = newCsZoneJoinReq(myCreds)
  153. dirServer.send HZoneJoinReq, req)
  154. pos.y += 20
  155. connectionButtons.add(gui.newButton(
  156. text = "Test Chat",
  157. position = pos,
  158. onClick = (proc(b: PButton) =
  159. var pkt = newCsChat(text = "ohai")
  160. dirServer.send HChat, pkt),
  161. startEnabled = false))
  162. pos.y += 20
  163. downloadProgress.setPosition(pos)
  164. downloadProgress.bg.setFillColor(color(34, 139, 34))
  165. downloadProgress.bg.setSize(vec2f(0, 0))
  166. gui.add(downloadProgress)
  167. playBtn = gui.newButton(
  168. text = "Play",
  169. position = vec2f(680.0, 8.0),
  170. onClick = tryTransition,
  171. startEnabled = false)
  172. gui.newButton(
  173. text = "Play Offline",
  174. position = vec2f(680.0, 28.0),
  175. onClick = playOffline)
  176. discard """gui.newButton(text = "Scrollback + 1", position = vec2f(185, 10), onClick = proc(b: PButton) =
  177. messageArea.scrollBack += 1
  178. update(messageArea))
  179. gui.newButton(text = "Scrollback - 1", position = vec2f(185+160, 10), onClick = proc(b: PButton) =
  180. messageArea.scrollBack -= 1
  181. update(messageArea))
  182. gui.newButton(text = "Flood msg area", position = vec2f(185, 30), onClick = proc(b: PButton) =
  183. for i in 0..< 30:
  184. dispMessage($i))"""
  185. dirServer = newServer()
  186. dirServer.addHandler HChat, handleChat
  187. dirServer.addHandler HLogin, handlePlayerLogin
  188. dirServer.addHandler HFileTransfer, client_helpers.handleFilePartRecv
  189. dirServer.addHandler HChallengeResult, client_helpers.handleFileChallengeResult
  190. dirServer.addHandler HFileChallenge, client_helpers.handleFileChallenge
  191. proc lobbyReady*() =
  192. kc.setActive()
  193. gui.setActive(u_alias)
  194. var i = 0
  195. proc lobbyUpdate*(dt: float) =
  196. dirServer.poll()
  197. #let res = disp.poll()
  198. gui.update(dt)
  199. i = (i + 1) mod 60
  200. if i == 0:
  201. fpsText.setString("FPS: " & ff(1.0/dt))
  202. proc lobbyDraw*(window: PRenderWindow) =
  203. window.clear(Black)
  204. window.draw chatBox
  205. window.draw gui
  206. window.draw fpsText
  207. if showZonelist: window.draw zonelist
  208. window.display()