MaTaXeToS

ComputerCraft Chat

Jun 20th, 2013
57
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 10.71 KB | None | 0 0
  1. local width,height=term.getSize()
  2.  
  3. local function debug(...)
  4.   term.redirect(term.native)
  5.   print(...)
  6.   os.pullEvent("char")
  7.   term.restore()
  8. end
  9.  
  10. local function printUsage()
  11.   print([[Uso:
  12. chat <nick> [channel]
  13.  Nick es el nombre que quieres en el chat
  14.  Canal es opcional
  15. ]])
  16.   error()
  17. end
  18.  
  19. local tArgs={...}
  20. if #tArgs<1 or #tArgs>2 then
  21.   printUsage()
  22. end
  23.  
  24. --look for a modem
  25. local modem
  26.  
  27. do
  28.   local modemSides={}
  29.   for _,v in pairs(rs.getSides()) do
  30.     if peripheral.getType(v)=="modem" then
  31.       modemSides[#modemSides+1]=v
  32.     end
  33.   end
  34.  
  35.   if #modemSides==0 then
  36.     print("A modem required for chat!")
  37.     return
  38.   end
  39.   if #modemSides>1 then
  40.     term.scroll(#modemSides+3)
  41.     local selected=1
  42.    
  43.     local function printMenu()
  44.       term.setCursorPos(1,height-#modemSides-2)
  45.       for i=1,#modemSides do
  46.         if selected==i then
  47.           term.setTextColor(colors.black)
  48.           term.setBackgroundColor(colors.white)
  49.         end
  50.         print(i..": "..modemSides[i].." - "..(peripheral.call(modemSides[i],"isWireless") and "wireless" or "wired"))
  51.         if selected==i then
  52.           term.setTextColor(colors.white)
  53.           term.setBackgroundColor(colors.black)
  54.         end
  55.       end
  56.     end
  57.      
  58.     print("Selecciona un modem a usar:")
  59.     printMenu()
  60.     if term.isColor() then
  61.       write("Haz click con el raton para seleccionar")
  62.     else
  63.       write("use las flechas e Intro para seleccionar")
  64.     end
  65.     while true do
  66.       local e={os.pullEvent()}
  67.       if e[1]=="key" then
  68.         local key=e[2]
  69.         if key==keys.up then
  70.           selected=selected==1 and #modemSides or selected-1
  71.           printMenu()
  72.         elseif key==keys.down then
  73.           selected=(selected%#modemSides)+1
  74.           printMenu()
  75.         elseif key==keys.enter then
  76.           break
  77.         end
  78.       elseif e[1]=="char" then
  79.         local char=e[2]
  80.         local num=tonumber(char)
  81.         if num and num>0 and num<=#modemSides then
  82.           selected=num
  83.           break
  84.         end
  85.       end
  86.     end
  87.    
  88.     term.scroll(2)
  89.     modem=peripheral.wrap(modemSides[selected])    
  90.   else
  91.     modem=peripheral.wrap(modemSides[1])
  92.   end
  93. end
  94.  
  95.          
  96. local function parseNick(str)
  97.   local nick=str:match("%s*([%w_]+)%s*")
  98.   return nick and nick:sub(1,12) or nil
  99. end
  100.  
  101. local nick=parseNick(tArgs[1])
  102. if nick==nil then
  103.   print("Nick Invalido! Solo puede contener letras, numeros o _ | Longitud maxima: 12 caracteres.")
  104.   return
  105. end
  106.  
  107. local users={
  108.   [nick]=true
  109. }
  110.  
  111. local channel, frequency="ifds",1337
  112.  
  113. local function parseChannel(str)
  114.   local chan,freq=str:match("%s*(%w+):(%d+)%s*")
  115.   if not chan then
  116.     freq=frequency
  117.     chan=str:match("(%w+)"):lower():sub(1,16)
  118.     if not chan then
  119.       chan=channel
  120.     end
  121.   else
  122.     chan=chan:lower():sub(1,16)
  123.     freq=tonumber(freq)%65536
  124.   end
  125.   return chan,freq
  126. end
  127.  
  128.  
  129. if tArgs[2] then
  130.   channel,frequency=parseChannel(tArgs[2])
  131. end
  132.  
  133. modem.open(frequency)
  134.  
  135. local inputCurPos={1,2}
  136. local inputTextColor=colors.white
  137. local inputBGColor=colors.black
  138. local inputCursorBlink=false
  139. local inputBuffer=(""):rep(width)
  140.  
  141. local statusLine
  142.  
  143. local function rebuildStatus()
  144.   statusLine=" IFDS Chat v1.0     Canal: "..channel..":"..frequency
  145.   statusLine=statusLine..(" "):rep(width-#statusLine)
  146.   term.native.setCursorPos(1,height-1)
  147.   term.native.setTextColor(colors.black)
  148.   term.native.setBackgroundColor(colors.white)
  149.   term.native.write(statusLine)
  150.   term.native.setTextColor(colors.white)
  151.   term.native.setBackgroundColor(colors.black)  
  152. end
  153.  
  154. local function redrawInput()
  155.   term.redirect(term.native)
  156.   term.setCursorPos(1,height-1)
  157.   term.setTextColor(colors.black)
  158.   term.setBackgroundColor(colors.white)
  159.   term.write(statusLine)
  160.   term.setCursorPos(1,height)
  161.   term.setBackgroundColor(colors.black)
  162.   term.setTextColor(colors.white)
  163.   term.write(inputBuffer)
  164.   term.setCursorPos(unpack(inputCurPos))
  165.   term.restore()
  166. end
  167.  
  168.  
  169. --input+status redirect
  170. local inputRedirect = {
  171.   getSize=function() return width,2 end,
  172.   setCursorPos=function(x,y) inputCurPos={x,y} term.native.setCursorPos(x,height) end,
  173.   getCursorPos=function() return unpack(inputCurPos) end,
  174.   setTextColor=function(color) inputTextColor=color term.native.setTextColor(color) end,
  175.   setTextColour=function(color) inputTextColor=color term.native.setTextColor(color) end,
  176.   setBackgroundColor=function(color) inputBGColor=color term.native.setBackgroundColor(color) end,
  177.   setBackgroundColour=function(color) inputBGColor=color term.native.setBackgroundColor(color) end,
  178.   setCursorBlink=function(state) inputCursorBlink=state term.native.setCursorBlink(state) end,
  179.   isColor=function() return term.native.isColor() end,
  180.   isColour=function() return term.native.isColour() end,
  181.   scroll=function() term.clearLine() end,
  182.   write=function(val)
  183.       inputBuffer=inputBuffer:sub(1,inputCurPos[1]-1)..val..inputBuffer:sub(inputCurPos[1]+#val)
  184.       inputCurPos[1]=inputCurPos[1]+#val
  185.       term.native.write(val)
  186.     end,
  187.   clear=function()
  188.       inputBuffer=(""):rep(width)
  189.     end,
  190.   clearLine=function()
  191.       inputBuffer=(""):rep(width)
  192.     end,
  193. }
  194.  
  195.  
  196. local isNewLogLine=true
  197. --main log redirect
  198. local logRedirect = {
  199.   getSize=function() return width,height-1 end,
  200.   setCursorBlink=function() end,
  201.   scroll=function(amt)      
  202.       term.native.scroll(amt)      
  203.       isNewLogLine=true
  204.     end,
  205.   write=function(text)
  206.       if isNewLogLine then
  207.         term.native.clearLine()
  208.         isNewLogLine=false
  209.       end      
  210.       term.native.write(text)
  211.     end,
  212. }
  213.  
  214. for k,v in pairs(term.native) do
  215.   if logRedirect[k]==nil then
  216.     logRedirect[k]=v
  217.   end
  218. end
  219.  
  220.  
  221. local function printLine(line)
  222.   local x,y=term.getCursorPos()
  223.   term.redirect(logRedirect)
  224.   term.setCursorPos(1,height-1)
  225.   print(line)
  226.   term.restore()
  227.   redrawInput()
  228.   term.setCursorPos(x,y)
  229.   --queue a dummy event to trigger coRead update?
  230.   --os.queueEvent("key")  
  231. end
  232.  
  233. local function printHelp()
  234.   printLine([[IFDS v1.0
  235. commands:
  236.   /quit [msg]   sale del chat con mensaje opcional
  237.   /join <name>  Dejas el canal actual y te unes al nuevo canal
  238.                 <name> puede ser con frequancia para cambiar de señal
  239.                 ex: /join IFDS:1338
  240.   /freq <freq>  Cambiar de frecuencia
  241.   /help         muestra esta ayuda
  242.   /nick <nick>  cambiar el nick a <nick>
  243.   /users        Muestra los usuarios en el canal
  244.  
  245.   Todos los mensajes tienen que tener /
  246.   Sino el mensaje sera visualizado por todos los usuarios en el mismo canal y frecuencia.]])
  247.  
  248. end
  249.  
  250.  
  251. local function sendMsg(msg)
  252.   local out="CHAT "..channel.." "..nick.." "..msg
  253.   modem.transmit(frequency,frequency,out)
  254. end
  255.  
  256. local function showUsers()
  257.   local first=true
  258.   local str="** Usuarios en el canal "..channel..":"
  259.   for k,v in pairs(users) do
  260.     if first then
  261.       first=false
  262.     else
  263.       str=str..","
  264.     end
  265.     str=str.." "..k
  266.   end
  267.   printLine(str)
  268. end
  269.  
  270. local autoUsersTimer
  271.  
  272. local function coRead()
  273.   history={}
  274.   while true do
  275.     term.setCursorPos(1,height)
  276.     local input=read(nil,history)
  277.     history[#history+1]=input
  278.     if #history==256 then
  279.       table.remove(history,1)
  280.     end
  281.    
  282.     if input:sub(1,1)=="/" then
  283.       local cmd,args=input:match("/(%S+) ?(.*)")
  284.       if cmd=="quit" then
  285.         printLine("Exiting chat")
  286.         sendMsg("quit "..args:match("^%s*(.*)%s*$"))
  287.         return
  288.       elseif cmd=="me" then
  289.         printLine("* "..nick.." "..args)
  290.         sendMsg("me "..args)
  291.       elseif cmd=="join" then
  292.         local chan,freq=parseChannel(args)
  293.         if chan then
  294.           if chan==channel then
  295.             printLine("** Ya estas en este canal!")
  296.           elseif args~="" then
  297.             printLine("** cambiando de canal "..chan..(freq==frequency and "" or (":"..freq)))
  298.             sendMsg("quit leftChannel")
  299.             channel=chan
  300.             if frequency~=freq then
  301.               modem.open(freq)
  302.               modem.close(frequency)
  303.               frequency=freq
  304.             end
  305.             sendMsg("join")
  306.             rebuildStatus()
  307.             users={[nick]=true}
  308.             autoUsersTimer=os.startTimer(.25)
  309.           else
  310.             printLine("** canal invalido!")
  311.           end
  312.         else
  313.           printLine("** sintaxis invalida")
  314.         end
  315.       elseif cmd=="freq" then
  316.         args=tonumber(args)
  317.         if args==nil then
  318.           printLine("** la frequencia tiene que ser un numero.")
  319.         elseif frequency~=args then
  320.           printLine("** cambiando de frequencia "..args)
  321.           sendMsg("quit leftChannel")
  322.           modem.open(args)
  323.           modem.close(frequency)
  324.           frequency=args
  325.           sendMsg("join")
  326.           rebuildStatus()
  327.           users={[nick]=true}
  328.           autoUsersTimer=os.startTimer(.25)
  329.         end
  330.       elseif cmd=="help" then
  331.         printHelp()
  332.       elseif cmd=="nick" then
  333.         local newNick=parseNick(args)
  334.         if newNick then          
  335.           printLine("** nick cambiado a "..newNick)
  336.           sendMsg("nick "..nick.." "..newNick)
  337.           nick=newNick
  338.         end
  339.       elseif cmd=="users" then
  340.         showUsers()
  341.       else
  342.         printLine("** Comando desconocido")
  343.       end
  344.     else
  345.       printLine("<"..nick.."> "..input)
  346.       sendMsg("say "..input)
  347.     end
  348.   end
  349. end
  350.  
  351.  
  352. local function coMain()
  353.   while true do  
  354.     e={os.pullEvent()}
  355.     if e[1]=="modem_message" then
  356.       local msgChannel, msgNick, msgCmd, msgArgs=e[5]:match("CHAT (%S+) (%S+) (%S+) ?(.*)")
  357.       if msgChannel==channel then
  358.         --it's a chat message on the right channel
  359.         if msgCmd=="say" then
  360.           printLine("<"..msgNick.."> "..msgArgs)
  361.         elseif msgCmd=="me" then
  362.           printLine("* "..msgNick.." "..msgArgs)
  363.         elseif msgCmd=="join" then
  364.           printLine("** "..msgNick.." ha entrado en el canal")
  365.           sendMsg("ident")
  366.         elseif msgCmd=="ident" then
  367.           users[msgNick]=true
  368.         elseif msgCmd=="quit" then
  369.           printLine("** "..msgNick.." ha salido del canal ("..(msgArgs=="" and "quit" or msgArgs)..")")          
  370.         elseif msgCmd=="nick" then
  371.           local old, new=msgArgs:match("(%S+) (%S+)")
  372.           users[old]=nil
  373.           users[new]=true
  374.           printLine("** "..old.." ahora se llama "..new)          
  375.         end
  376.       end
  377.     elseif e[1]=="timer" and e[2]==autoUsersTimer then
  378.       showUsers()      
  379.     end    
  380.   end
  381. end
  382.  
  383. sendMsg("join")
  384.  
  385. autoUsersTimer=os.startTimer(.25)
  386.  
  387. term.clear()
  388. rebuildStatus()
  389.  
  390. term.redirect(inputRedirect)
  391. printLine([[IFDS v1.0
  392. /help para mostrar la ayuda
  393. /quit Para salir
  394. ]])
  395.  
  396. parallel.waitForAny(coRead,coMain)
  397.  
  398. modem.close(frequency)
  399.  
  400. term.restore()
  401. term.scroll(1)
  402. print("\nIFDS!\n")
Advertisement
Add Comment
Please, Sign In to add comment