DaGamer12345

Test

Jul 18th, 2013
132
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 11.22 KB | None | 0 0
  1. --[[
  2. Code derived from:
  3. talk - a simple chat program by GopherAtl, 2013
  4. "do whatever you want with this program/code, just
  5. give me credit for the original code."
  6. --]]
  7.  
  8. local width,height=term.getSize()
  9.  
  10. local function debug(...)
  11.   term.redirect(term.native)
  12.   print(...)
  13.   os.pullEvent("char")
  14.   term.restore()
  15. end
  16.  
  17. local function printUsage()
  18.   print([[Usage:
  19.  <nick> [channel]
  20.  <nick> is the name you want to use in chat
  21.  [channel] is an optional name of the chat channel to chat on
  22. ]])
  23.   error()
  24. end
  25.  
  26. local tArgs={...}
  27. if #tArgs<1 or #tArgs>2 then
  28.   printUsage()
  29. end
  30.  
  31. --look for a modem
  32. local modem
  33.  
  34. do
  35.   local modemSides={}
  36.   for _,v in pairs(rs.getSides()) do
  37.     if peripheral.getType(v)=="modem" then
  38.       modemSides[#modemSides+1]=v
  39.     end
  40.   end
  41.  
  42.   if #modemSides==0 then
  43.     print("A modem is required for chat!")
  44.     return
  45.   end
  46.   if #modemSides>1 then
  47.     term.scroll(#modemSides+3)
  48.     local selected=1
  49.    
  50.     local function printMenu()
  51.       term.clear()
  52.       term.setCursorPos(1,1)
  53.       print("+---------------------------+")
  54.       print("I Multiple modems detected! I")
  55.       print("+---------------------------+")
  56.       for i=1,#modemSides do
  57.         if selected==i then
  58.           term.setTextColor(colors.black)
  59.           term.setBackgroundColor(colors.white)
  60.         end
  61.         print(i..": "..modemSides[i].." - "..(peripheral.call(modemSides[i],"isWireless") and "wireless" or "wired"))
  62.         if selected==i then
  63.           term.setTextColor(colors.white)
  64.           term.setBackgroundColor(colors.black)
  65.         end
  66.       end
  67.     end
  68.      
  69.     print("Select a modem to use:")
  70.     printMenu()
  71.     if term.isColor() then
  72.       write("Use arrows and enter, press # to select, or click with mouse to select")
  73.     else
  74.       write("Use arrows and enter or press # to select")
  75.     end
  76.     while true do
  77.       local e={os.pullEvent()}
  78.       if e[1]=="key" then
  79.         local key=e[2]
  80.         if key==keys.up then
  81.           selected=selected==1 and #modemSides or selected-1
  82.           printMenu()
  83.         elseif key==keys.down then
  84.           selected=(selected%#modemSides)+1
  85.           printMenu()
  86.         elseif key==keys.enter then
  87.           break
  88.         end
  89.       elseif e[1]=="char" then
  90.         local char=e[2]
  91.         local num=tonumber(char)
  92.         if num and num>0 and num<=#modemSides then
  93.           selected=num
  94.           break
  95.         end
  96.       end
  97.     end
  98.    
  99.     term.scroll(2)
  100.     modem=peripheral.wrap(modemSides[selected])    
  101.   else
  102.     modem=peripheral.wrap(modemSides[1])
  103.   end
  104. end
  105.  
  106.          
  107. local function parseNick(str)
  108.   local nick=str:match("%s*([%w_]+)%s*")
  109.   return nick and nick:sub(1,12) or nil
  110. end
  111.  
  112. local nick=parseNick(tArgs[1])
  113. if nick==nil then
  114.   print("Invalid nick! Must be alphanumeric and must be no more than 12 characters long.")
  115.   return
  116. end
  117.  
  118. local users={
  119.   [nick]=true
  120. }
  121.  
  122. local channel, frequency="chat",1337
  123.  
  124. local function parseChannel(str)
  125.   local chan,freq=str:match("%s*(%w+):(%d+)%s*")
  126.   if not chan then
  127.     freq=frequency
  128.     chan=str:match("(%w+)"):lower():sub(1,16)
  129.     if not chan then
  130.       chan=channel
  131.     end
  132.   else
  133.     chan=chan:lower():sub(1,16)
  134.     freq=tonumber(freq)%65536
  135.   end
  136.   return chan,freq
  137. end
  138.  
  139.  
  140. if tArgs[2] then
  141.   channel,frequency=parseChannel(tArgs[2])
  142. end
  143.  
  144. modem.open(frequency)
  145.  
  146. local inputCurPos={1,2}
  147. local inputTextColor=colors.white
  148. local inputBGColor=colors.black
  149. local inputCursorBlink=false
  150. local inputBuffer=(""):rep(width)
  151.  
  152. local statusLine
  153.  
  154. local function rebuildStatus()
  155.   statusLine=" CCLChat                   channel: "..channel..":"..frequency
  156.   statusLine=statusLine..(" "):rep(width-#statusLine)
  157.   term.native.setCursorPos(1,height-1)
  158.   term.native.setTextColor(colors.black)
  159.   term.native.setBackgroundColor(colors.white)
  160.   term.native.write(statusLine)
  161.   term.native.setTextColor(colors.white)
  162.   term.native.setBackgroundColor(colors.black)  
  163. end
  164.  
  165. local function redrawInput()
  166.   term.redirect(term.native)
  167.   term.setCursorPos(1,height-1)
  168.   term.setTextColor(colors.black)
  169.   term.setBackgroundColor(colors.white)
  170.   term.write(statusLine)
  171.   term.setCursorPos(1,height)
  172.   term.setBackgroundColor(colors.black)
  173.   term.setTextColor(colors.white)
  174.   term.write(inputBuffer)
  175.   term.setCursorPos(unpack(inputCurPos))
  176.   term.restore()
  177. end
  178.  
  179.  
  180. --input+status redirect
  181. local inputRedirect = {
  182.   getSize=function() return width,2 end,
  183.   setCursorPos=function(x,y) inputCurPos={x,y} term.native.setCursorPos(x,height) end,
  184.   getCursorPos=function() return unpack(inputCurPos) end,
  185.   setTextColor=function(color) inputTextColor=color term.native.setTextColor(color) end,
  186.   setTextColour=function(color) inputTextColor=color term.native.setTextColor(color) end,
  187.   setBackgroundColor=function(color) inputBGColor=color term.native.setBackgroundColor(color) end,
  188.   setBackgroundColour=function(color) inputBGColor=color term.native.setBackgroundColor(color) end,
  189.   setCursorBlink=function(state) inputCursorBlink=state term.native.setCursorBlink(state) end,
  190.   isColor=function() return term.native.isColor() end,
  191.   isColour=function() return term.native.isColour() end,
  192.   scroll=function() term.clearLine() end,
  193.   write=function(val)
  194.       inputBuffer=inputBuffer:sub(1,inputCurPos[1]-1)..val..inputBuffer:sub(inputCurPos[1]+#val)
  195.       inputCurPos[1]=inputCurPos[1]+#val
  196.       term.native.write(val)
  197.     end,
  198.   clear=function()
  199.       inputBuffer=(""):rep(width)
  200.     end,
  201.   clearLine=function()
  202.       inputBuffer=(""):rep(width)
  203.     end,
  204. }
  205.  
  206.  
  207. local isNewLogLine=true
  208. --main log redirect
  209. local logRedirect = {
  210.   getSize=function() return width,height-1 end,
  211.   setCursorBlink=function() end,
  212.   scroll=function(amt)      
  213.       term.native.scroll(amt)      
  214.       isNewLogLine=true
  215.     end,
  216.   write=function(text)
  217.       if isNewLogLine then
  218.         term.native.clearLine()
  219.         isNewLogLine=false
  220.       end      
  221.       term.native.write(text)
  222.     end,
  223. }
  224.  
  225. for k,v in pairs(term.native) do
  226.   if logRedirect[k]==nil then
  227.     logRedirect[k]=v
  228.   end
  229. end
  230.  
  231.  
  232. local function printLine(line)
  233.   local x,y=term.getCursorPos()
  234.   term.redirect(logRedirect)
  235.   term.setCursorPos(1,height-1)
  236.   print(line)
  237.   term.restore()
  238.   redrawInput()
  239.   term.setCursorPos(x,y)
  240.   --queue a dummy event to trigger coRead update?
  241.   --os.queueEvent("key")  
  242. end
  243.  
  244. local function printHelp()
  245.   printLine([[CCChat v1.0
  246. commands:
  247.   /quit [msg] - Exits chat with optional message
  248.   /join <name> - Leaves the current chat channel
  249.                 and joins <name>. <name> can end
  250.                 with :<freq> to change both,
  251.                 ex: /join foo:1338
  252.   /freq <freq> - switches chat frequencies
  253.   /help - displays this help
  254.   /nick <nick> - changes your nick to <nick>
  255.   /users - lists users in channel
  256.   /me - 3rd person thingy (ex: /me ate a pie would send * <nick> ate a pie)
  257.  
  258.   NOTE: Anything typed without a / will be said in the
  259.   channel and heard by all in range on the same
  260.   channel and frequency.]])
  261.  
  262. end
  263.  
  264.  
  265. local function sendMsg(msg)
  266.   local out="CHAT "..channel.." "..nick.." "..msg
  267.   modem.transmit(frequency,frequency,out)
  268. end
  269.  
  270. local function showUsers()
  271.   local first=true
  272.   local str="** Users in channel "..channel..":"
  273.   for k,v in pairs(users) do
  274.     if first then
  275.       first=false
  276.     else
  277.       str=str..","
  278.     end
  279.     str=str.." "..k
  280.   end
  281.   printLine(str)
  282. end
  283.  
  284. local autoUsersTimer
  285.  
  286. local function coRead()
  287.   history={}
  288.   while true do
  289.     term.setCursorPos(1,height)
  290.     local input=read(nil,history)
  291.     history[#history+1]=input
  292.     if #history==256 then
  293.       table.remove(history,1)
  294.     end
  295.    
  296.     if input:sub(1,1)=="/" then
  297.       local cmd,args=input:match("/(%S+) ?(.*)")
  298.       if cmd=="quit" then
  299.         printLine("Exiting chat")
  300.         sendMsg("quit "..args:match("^%s*(.*)%s*$"))
  301.         return
  302.       elseif cmd=="me" then
  303.         printLine("* "..nick.." "..args)
  304.         sendMsg("me "..args)
  305.       elseif cmd=="join" then
  306.         local chan,freq=parseChannel(args)
  307.         if chan then
  308.           if chan==channel then
  309.             printLine("** You are already in that channel!")
  310.           elseif args~="" then
  311.             printLine("** switching to channel "..chan..(freq==frequency and "" or (":"..freq)))
  312.             sendMsg("quit leftChannel")
  313.             channel=chan
  314.             if frequency~=freq then
  315.               modem.open(freq)
  316.               modem.close(frequency)
  317.               frequency=freq
  318.             end
  319.             sendMsg("join")
  320.             rebuildStatus()
  321.             users={[nick]=true}
  322.             autoUsersTimer=os.startTimer(.25)
  323.           else
  324.             printLine("** invalid channel!")
  325.           end
  326.         else
  327.           printLine("** invalid syntax")
  328.         end
  329.       elseif cmd=="freq" then
  330.         args=tonumber(args)
  331.         if args==nil then
  332.           printLine("** frequency must be a number.")
  333.         elseif frequency~=args then
  334.           printLine("** switching to frequency "..args)
  335.           sendMsg("quit leftChannel")
  336.           modem.open(args)
  337.           modem.close(frequency)
  338.           frequency=args
  339.           sendMsg("join")
  340.           rebuildStatus()
  341.           users={[nick]=true}
  342.           autoUsersTimer=os.startTimer(.25)
  343.         end
  344.       elseif cmd=="help" then
  345.         printHelp()
  346.       elseif cmd=="nick" then
  347.         local newNick=parseNick(args)
  348.         if newNick then          
  349.           printLine("** nick changed to "..newNick)
  350.           sendMsg("nick "..nick.." "..newNick)
  351.           nick=newNick
  352.         end
  353.       elseif cmd=="users" then
  354.         showUsers()
  355.       else
  356.         printLine("** Unknown command")
  357.       end
  358.     else
  359.       printLine("<"..nick.."> "..input)
  360.       sendMsg("say "..input)
  361.     end
  362.   end
  363. end
  364.  
  365.  
  366. local function coMain()
  367.   while true do  
  368.     e={os.pullEvent()}
  369.     if e[1]=="modem_message" then
  370.       local msgChannel, msgNick, msgCmd, msgArgs=e[5]:match("CHAT (%S+) (%S+) (%S+) ?(.*)")
  371.       if msgChannel==channel then
  372.         --it's a chat message on the right channel
  373.         if msgCmd=="say" then
  374.           printLine("<"..msgNick.."> "..msgArgs)
  375.         elseif msgCmd=="me" then
  376.           printLine("* "..msgNick.." "..msgArgs)
  377.         elseif msgCmd=="join" then
  378.           printLine("** "..msgNick.." has joined the chat")
  379.           sendMsg("ident")
  380.         elseif msgCmd=="ident" then
  381.           users[msgNick]=true
  382.         elseif msgCmd=="quit" then
  383.           printLine("** "..msgNick.." has left the channel ("..(msgArgs=="" and "quit" or msgArgs)..")")          
  384.         elseif msgCmd=="nick" then
  385.           local old, new=msgArgs:match("(%S+) (%S+)")
  386.           users[old]=nil
  387.           users[new]=true
  388.           printLine("** "..old.." now known as "..new)          
  389.         end
  390.       end
  391.     elseif e[1]=="timer" and e[2]==autoUsersTimer then
  392.       showUsers()      
  393.     end    
  394.   end
  395. end
  396.  
  397. sendMsg("join")
  398.  
  399. autoUsersTimer=os.startTimer(.25)
  400.  
  401. term.clear()
  402. rebuildStatus()
  403.  
  404. term.redirect(inputRedirect)
  405. printLine([[CCLChat Chat Client
  406. Type /help for a list of commands
  407. Type /quit to quit
  408. Just type to talk.]])
  409.  
  410. parallel.waitForAny(coRead,coMain)
  411.  
  412. modem.close(frequency)
  413.  
  414. term.restore()
  415. term.scroll(1)
  416. print("\nGoodbye!\n")
  417. term.clear()
Advertisement
Add Comment
Please, Sign In to add comment