MinePossu

sms

May 6th, 2017
227
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.61 KB | None | 0 0
  1. h = fs.open("/void/nick", "r")
  2. text = h.readAll()
  3. h.close()
  4.  
  5. username = text
  6. local function printUsage()
  7. print( "Usages:" )
  8. print( "chat host <hostname>" )
  9. print( "chat join <hostname> <nickname>" )
  10. end
  11.  
  12. local sOpenedModem = nil
  13. local function openModem()
  14. for n,sModem in ipairs( peripheral.getNames() ) do
  15. if peripheral.getType( sModem ) == "modem" then
  16. if not rednet.isOpen( sModem ) then
  17. rednet.open( sModem )
  18. sOpenedModem = sModem
  19. end
  20. return true
  21. end
  22. end
  23. print( "No modems found." )
  24. return false
  25. end
  26.  
  27. local function closeModem()
  28. if sOpenedModem ~= nil then
  29. rednet.close( sOpenedModem )
  30. sOpenedModem = nil
  31. end
  32. end
  33.  
  34. -- Colours
  35. local highlightColour, textColour
  36. if term.isColour() then
  37. textColour = colours.white
  38. highlightColour = colours.yellow
  39. else
  40. textColour = colours.white
  41. highlightColour = colours.white
  42. end
  43.  
  44. local sCommand = "join"
  45. if sCommand == "host" then
  46. -- "chat host"
  47. -- Get hostname
  48. local sHostname = tArgs[2]
  49. if sHostname == nil then
  50. printUsage()
  51. return
  52. end
  53.  
  54. -- Host server
  55. if not openModem() then
  56. return
  57. end
  58. rednet.host( "chat", sHostname )
  59. print( "0 users connected." )
  60.  
  61. local tUsers = {}
  62. local nUsers = 0
  63. function send( sText, nUserID )
  64. if nUserID then
  65. local tUser = tUsers[ nUserID ]
  66. if tUser then
  67. rednet.send( tUser.nID, {
  68. sType = "text",
  69. nUserID = nUserID,
  70. sText = sText,
  71. }, "chat" )
  72. end
  73. else
  74. for nUserID, tUser in pairs( tUsers ) do
  75. rednet.send( tUser.nID, {
  76. sType = "text",
  77. nUserID = nUserID,
  78. sText = sText,
  79. }, "chat" )
  80. end
  81. end
  82. end
  83.  
  84. -- Setup ping pong
  85. local tPingPongTimer = {}
  86. function ping( nUserID )
  87. local tUser = tUsers[ nUserID ]
  88. rednet.send( tUser.nID, {
  89. sType = "ping to client",
  90. nUserID = nUserID,
  91. }, "chat" )
  92.  
  93. local timer = os.startTimer( 15 )
  94. tUser.bPingPonged = false
  95. tPingPongTimer[ timer ] = nUserID
  96. end
  97.  
  98. function printUsers()
  99. local x,y = term.getCursorPos()
  100. term.setCursorPos( 1, y - 1 )
  101. term.clearLine()
  102. if nUsers == 1 then
  103. print( nUsers .. " user connected." )
  104. else
  105. print( nUsers .. " users connected." )
  106. end
  107. end
  108.  
  109. -- Handle messages
  110. local ok, error = pcall( function()
  111. parallel.waitForAny( function()
  112. while true do
  113. local sEvent, timer = os.pullEvent( "timer" )
  114. local nUserID = tPingPongTimer[ timer ]
  115. if nUserID and tUsers[ nUserID ] then
  116. local tUser = tUsers[ nUserID ]
  117. if tUser then
  118. if not tUser.bPingPonged then
  119. send( "* "..tUser.sUsername.." has timed out" )
  120. tUsers[ nUserID ] = nil
  121. nUsers = nUsers - 1
  122. printUsers()
  123. else
  124. ping( nUserID )
  125. end
  126. end
  127. end
  128. end
  129. end,
  130. function()
  131. while true do
  132. local tCommands
  133. tCommands = {
  134. ["me"] = function( tUser, sContent )
  135. if string.len(sContent) > 0 then
  136. send( "* "..tUser.sUsername.." "..sContent )
  137. else
  138. send( "* Usage: /me [words]", tUser.nUserID )
  139. end
  140. end,
  141. ["nick"] = function( tUser, sContent )
  142. if string.len(sContent) > 0 then
  143. local sOldName = tUser.sUsername
  144. tUser.sUsername = sContent
  145. send( "* "..sOldName.." is now known as "..tUser.sUsername )
  146. else
  147. send( "* Usage: /nick [nickname]", tUser.nUserID )
  148. end
  149. end,
  150. ["users"] = function( tUser, sContent )
  151. send( "* Connected Users:", tUser.nUserID )
  152. local sUsers = "*"
  153. for nUserID, tUser in pairs( tUsers ) do
  154. sUsers = sUsers .. " " .. tUser.sUsername
  155. end
  156. send( sUsers, tUser.nUserID )
  157. end,
  158. ["help"] = function( tUser, sContent )
  159. send( "* Available commands:", tUser.nUserID )
  160. local sCommands = "*"
  161. for sCommand, fnCommand in pairs( tCommands ) do
  162. sCommands = sCommands .. " /" .. sCommand
  163. end
  164. send( sCommands.." /logout", tUser.nUserID )
  165. end,
  166. }
  167.  
  168. local nSenderID, tMessage = rednet.receive( "chat" )
  169. if type( tMessage ) == "table" then
  170. if tMessage.sType == "login" then
  171. -- Login from new client
  172. local nUserID = tMessage.nUserID
  173. local sUsername = tMessage.sUsername
  174. if nUserID and sUsername then
  175. tUsers[ nUserID ] = {
  176. nID = nSenderID,
  177. nUserID = nUserID,
  178. sUsername = sUsername,
  179. }
  180. nUsers = nUsers + 1
  181. printUsers()
  182. send( "* "..sUsername.." has joined the chat" )
  183. ping( nUserID )
  184. end
  185.  
  186. else
  187. -- Something else from existing client
  188. local nUserID = tMessage.nUserID
  189. local tUser = tUsers[ nUserID ]
  190. if tUser and tUser.nID == nSenderID then
  191. if tMessage.sType == "logout" then
  192. send( "* "..tUser.sUsername.." has left the chat" )
  193. tUsers[ nUserID ] = nil
  194. nUsers = nUsers - 1
  195. printUsers()
  196.  
  197. elseif tMessage.sType == "chat" then
  198. local sMessage = tMessage.sText
  199. if sMessage then
  200. local sCommand = string.match( sMessage, "^/([a-z]+)" )
  201. if sCommand then
  202. local fnCommand = tCommands[ sCommand ]
  203. if fnCommand then
  204. local sContent = string.sub( sMessage, string.len(sCommand)+3 )
  205. fnCommand( tUser, sContent )
  206. else
  207. send( "* Unrecognised command: /"..sCommand, tUser.nUserID )
  208. end
  209. else
  210. send( "<"..tUser.sUsername.."> "..tMessage.sText )
  211. end
  212. end
  213.  
  214. elseif tMessage.sType == "ping to server" then
  215. rednet.send( tUser.nID, {
  216. sType = "pong to client",
  217. nUserID = nUserID,
  218. }, "chat" )
  219.  
  220. elseif tMessage.sType == "pong to server" then
  221. tUser.bPingPonged = true
  222.  
  223. end
  224. end
  225. end
  226. end
  227. end
  228. end )
  229. end )
  230. if not ok then
  231. printError( error )
  232. end
  233.  
  234. -- Unhost server
  235. for nUserID, tUser in pairs( tUsers ) do
  236. rednet.send( tUser.nID, {
  237. sType = "kick",
  238. nUserID = nUserID,
  239. }, "chat" )
  240. end
  241. rednet.unhost( "chat" )
  242. closeModem()
  243.  
  244. elseif sCommand == "join" then
  245. -- "chat join"
  246. -- Get hostname and username
  247. local sHostname = "chat"
  248. local sUsername = username
  249. if sHostname == nil or sUsername == nil then
  250. printUsage()
  251. return
  252. end
  253.  
  254. -- Connect
  255. if not openModem() then
  256. return
  257. end
  258. write( "Looking up " .. sHostname .. "... " )
  259. local nHostID = rednet.lookup( "chat", sHostname )
  260. if nHostID == nil then
  261. print( "Failed." )
  262. return
  263. else
  264. print( "Success." )
  265. end
  266.  
  267. -- Login
  268. local nUserID = math.random( 1, 2147483647 )
  269. rednet.send( nHostID, {
  270. sType = "login",
  271. nUserID = nUserID,
  272. sUsername = sUsername,
  273. }, "chat" )
  274.  
  275. -- Setup ping pong
  276. local bPingPonged = true
  277. local pingPongTimer = os.startTimer( 0 )
  278.  
  279. function ping()
  280. rednet.send( nHostID, {
  281. sType = "ping to server",
  282. nUserID = nUserID,
  283. }, "chat" )
  284. bPingPonged = false
  285. pingPongTimer = os.startTimer( 15 )
  286. end
  287.  
  288. -- Handle messages
  289. local w,h = term.getSize()
  290. local parentTerm = term.current()
  291. local titleWindow = window.create( parentTerm, 1, 1, w, 1, true )
  292. local historyWindow = window.create( parentTerm, 1, 2, w, h-2, true )
  293. local promptWindow = window.create( parentTerm, 1, h, w, 1, true )
  294. historyWindow.setCursorPos( 1, h-2 )
  295.  
  296. term.clear()
  297. term.setTextColour( textColour )
  298. term.redirect( promptWindow )
  299. promptWindow.restoreCursor()
  300.  
  301. function drawTitle()
  302. local x,y = titleWindow.getCursorPos()
  303. local w,h = titleWindow.getSize()
  304. local sTitle = sUsername.." on "..sHostname
  305. titleWindow.setTextColour( highlightColour )
  306. titleWindow.setCursorPos( math.floor( w/2 - string.len(sTitle)/2 ), 1 )
  307. titleWindow.clearLine()
  308. titleWindow.write( sTitle )
  309. promptWindow.restoreCursor()
  310. end
  311.  
  312. function printMessage( sMessage )
  313. term.redirect( historyWindow )
  314. print()
  315. if string.match( sMessage, "^\*" ) then
  316. -- Information
  317. term.setTextColour( highlightColour )
  318. write( sMessage )
  319. term.setTextColour( textColour )
  320. else
  321. -- Chat
  322. local sUsernameBit = string.match( sMessage, "^\<[^\>]*\>" )
  323. if sUsernameBit then
  324. term.setTextColour( highlightColour )
  325. write( sUsernameBit )
  326. term.setTextColour( textColour )
  327. write( string.sub( sMessage, string.len( sUsernameBit ) + 1 ) )
  328. else
  329. write( sMessage )
  330. end
  331. end
  332. term.redirect( promptWindow )
  333. promptWindow.restoreCursor()
  334. end
  335.  
  336. drawTitle()
  337.  
  338. local ok, error = pcall( function()
  339. parallel.waitForAny( function()
  340. while true do
  341. local sEvent, timer = os.pullEvent()
  342. if sEvent == "timer" then
  343. if timer == pingPongTimer then
  344. if not bPingPonged then
  345. printMessage( "Server timeout." )
  346. return
  347. else
  348. ping()
  349. end
  350. end
  351.  
  352. elseif sEvent == "term_resize" then
  353. local w,h = parentTerm.getSize()
  354. titleWindow.reposition( 1, 1, w, 1 )
  355. historyWindow.reposition( 1, 2, w, h-2 )
  356. promptWindow.reposition( 1, h, w, 1 )
  357.  
  358. end
  359. end
  360. end,
  361. function()
  362. while true do
  363. local nSenderID, tMessage = rednet.receive( "chat" )
  364. if nSenderID == nHostID and type( tMessage ) == "table" and tMessage.nUserID == nUserID then
  365. if tMessage.sType == "text" then
  366. local sText = tMessage.sText
  367. if sText then
  368. printMessage( sText )
  369. end
  370.  
  371. elseif tMessage.sType == "ping to client" then
  372. rednet.send( nSenderID, {
  373. sType = "pong to server",
  374. nUserID = nUserID,
  375. }, "chat" )
  376.  
  377. elseif tMessage.sType == "pong to client" then
  378. bPingPonged = true
  379.  
  380. elseif tMessage.sType == "kick" then
  381. return
  382.  
  383. end
  384. end
  385. end
  386. end,
  387. function()
  388. local tSendHistory = {}
  389. while true do
  390. promptWindow.setCursorPos( 1,1 )
  391. promptWindow.clearLine()
  392. promptWindow.setTextColor( highlightColour )
  393. promptWindow.write( ": ")
  394. promptWindow.setTextColor( textColour )
  395.  
  396. local sChat = read( nil, tSendHistory )
  397. if string.match( sChat, "^/logout" ) then
  398. break
  399. else
  400. rednet.send( nHostID, {
  401. sType = "chat",
  402. nUserID = nUserID,
  403. sText = sChat,
  404. }, "chat" )
  405. table.insert( tSendHistory, sChat )
  406. end
  407. end
  408. end )
  409. end )
  410.  
  411. -- Close the windows
  412. term.redirect( parentTerm )
  413.  
  414. -- Print error notice
  415. local w,h = term.getSize()
  416. term.setCursorPos( 1, h )
  417. term.clearLine()
  418. term.setCursorBlink( false )
  419. if not ok then
  420. printError( error )
  421. end
  422.  
  423. -- Logout
  424. rednet.send( nHostID, {
  425. sType = "logout",
  426. nUserID = nUserID,
  427. }, "chat" )
  428. closeModem()
  429.  
  430. -- Print disconnection notice
  431. print( "Disconnected." )
  432.  
  433. else
  434. -- "chat somethingelse"
  435. printUsage()
  436.  
  437. end
Advertisement
Add Comment
Please, Sign In to add comment