Omnimaga

General Discussion => Gaming Discussion => Technology and Development => Minecraft Discussion => Topic started by: Keoni29 on January 01, 2013, 02:06:18 pm

Title: Lua minecraft IRC server. (computercraft mod)
Post by: Keoni29 on January 01, 2013, 02:06:18 pm
Tekkit the famous modpack for minecraft contains a mod called computercraft. It allows you to place little computers running lua code in your minecraft world. You can even connect them to the Rednet. Rednet is an API which allows computers to communicate using a wireless modem. The first thing which came to my mind was: IRC.

I am learning lua and I don't really have an idea how exactely IRC should work on the server side. Does the server just pass trough any incoming messages?

This is what I've got so far:
(http://www.omnimaga.org/index.php?action=dlattach;topic=15463.0;attach=14421;image)
Title: Re: Lua minecraft IRC server. (computercraft mod)
Post by: TIfanx1999 on January 01, 2013, 02:50:02 pm
Sounds like a pretty cool idea. :) Could you do simple 2 player games like Pong, Tron, or perhaps even Tetris? That would be pretty neat too.
Title: Re: Lua minecraft IRC server. (computercraft mod)
Post by: Keoni29 on January 01, 2013, 03:10:46 pm
Yes that's possible and really simple too since it has setCursorPos(x, y) for text based gfx and the rednet api is easy to work with.
Title: Re: Lua minecraft IRC server. (computercraft mod)
Post by: cooliojazz on January 01, 2013, 05:52:24 pm
Are you actually trying to make it implement real IRC protocol? Have you read through an IRC RFC eg. http://tools.ietf.org/html/rfc2812 ?
Title: Re: Lua minecraft IRC server. (computercraft mod)
Post by: Keoni29 on January 02, 2013, 04:34:21 am
Hmm perhaps it's easier to implement a chat with channels, nicknames and some commands rather than true irc. It's a pain to use the text editor in computercraft, so I don't want to have to write a lot of code.

Edit:
We got a working chat program. Both client and server.
Implemented commands so far:
/help
/join
/me
/msg
/nick

To do: some optimization and removing some glitches. (and of course more commands)
Title: Re: Lua minecraft IRC server. (computercraft mod)
Post by: Keoni29 on January 02, 2013, 03:43:51 pm
More commands implemented:
/quit
/who -- lists the online users
yet to implement /who #channel
Title: Re: Lua minecraft IRC server. (computercraft mod)
Post by: Keoni29 on January 12, 2013, 06:55:10 am
My epic new server building!
Title: Re: Lua minecraft IRC server. (computercraft mod)
Post by: TIfanx1999 on January 12, 2013, 08:18:12 am
Pretty cool stuff! ^^
Title: Re: Lua minecraft IRC server. (computercraft mod)
Post by: Keoni29 on January 12, 2013, 01:36:06 pm
The two lights that make up the cursor actually blink :)
Title: Re: Lua minecraft IRC server. (computercraft mod)
Post by: Keoni29 on January 25, 2013, 02:24:25 am
Is there a way to export these lua programs to a text file (and load them from a text file)?
Title: Re: Lua minecraft IRC server. (computercraft mod)
Post by: cooliojazz on January 25, 2013, 11:22:20 am
look under %appdata%/.minecraft/saves/*WORLD*/computer/*COMP #*/ all the files on the computer are stored there
Title: Re: Lua minecraft IRC server. (computercraft mod)
Post by: Keoni29 on January 25, 2013, 11:29:52 am
Wow thanks. This is gonna make life so much easier :P
Title: Re: Lua minecraft IRC server. (computercraft mod)
Post by: Keoni29 on March 29, 2013, 05:31:02 am
Here is the sourcecode for those who are interested:
IRCserver
Code: [Select]
SERVER = os.getComputerID()
nick = {}
channel = {}
--initialize names 1 to 128
for i=1,128 do
  nick[i]="&new"
  channel[i]="&new"
end
nick[SERVER] = "SERVER"
channel[SERVER] =  "VIP LOUNGE"

function getUserId(str)
  for i=1,128 do
    if nick[i] == str then
      return i
    end
  end
  return nil
end

function listUsers(id)
  p(id,"@ircOnline Users:")
  for i=1,128 do
    if nick[i]~="&new" and i~=SERVER then
      p(id,"@irc -".. nick[i] .. " " .. channel[i])
    end
  end
end

function compare(str)
  return string.find(message, str)
end

function newline()
  mon.scroll(1)
  mon.setCursorPos(1,20)
end

function post(str)
  newline()
  mon.write("<IRC>".. channel[senderId])
  mon.setCursorPos(16,20)
  mon.write(str)
  chan = channel[senderId]
  for i=1,128 do
    if channel[i] == chan then
      rednet.send(i,"@irc" .. str)
    end
  end
end

function addTime()
  return "[" .. textutils.formatTime(os.time(),true) .. "]"
end

function postPrivate(receiver,str)
  if getUserId(receiver) then
    rednet.send(getUserId(receiver), "@irc".. addTime() .."<msg from ".. nick[senderId].. ">" .. str)
    newline()
    mon.write(addTime() .. "(msg " .. nick[senderId] .. " > " .. receiver .. ")" .. str)
  else
    rednet.send(senderId,"@ircUser " .. receiver .. " does not exist")    
  end  
end

function p(i,str)
  rednet.send(i,str)
end

function sendHelp(i)
  p(i,"@irc--commands:------------")
  p(i,"@irc  /join channel -- joins the channel. example: /join #minecraft")
  p(i,"@irc  message       -- sends plain text to the channel you're on")
  p(i,"@irc  /nick name    -- changes your nickname. limited to 16 characters.")
--p(i,"@irc  /msg receiver message  -- sends a private message to 'receiver'")
  p(i,"@irc  /quit message -- quits IRC with a message")
end



rednet.open("left")
mon = peripheral.wrap("top")
mon.clear()
newline()
mon.write("IRC server software Alpha 1.0")
newline()
mon.write("Booting up server!")
rednet.announce()
repeat
  senderId, message, distance = rednet.receive(1)
  if senderId and string.len(message)>1 then
  if nick[senderId]~="&new" or compare("/nick ")==1 then
    if compare("/")==1 then
      if compare("/join ")==1 and string.len(message)<=23 and string.len(message)>=1 and compare(" #")==6 then
        channel[senderId]=string.sub(message, 7)
        post(addTime() .. "*" .. nick[senderId] .. " has joined " .. channel[senderId])
      elseif compare("/me ")==1 then
        post(addTime() .. "*" .. nick[senderId] .. " " .. string.sub(message, 5) .. "*")
      elseif compare("/nick ")==1 then
        local oldnick= nick[senderId]
        if string.sub(message,7,23)~="&new" then
          nick[senderId] = string.sub(message, 7, 23)
          if nick~=oldnick and oldnick~="&new" then
            post(addTime() .. oldnick .. " changed his nickname to " .. nick[senderId])
          end
        end
      elseif compare("/help")==1 then
        sendHelp(senderId)
        newline()
        mon.write(addTime() .. nick[senderId] .. " requested help.")
      elseif compare("/msg ")==1 then
        msgStart = string.find(string.sub(message,6)," ")
        if msgStart>1 then
          postPrivate(string.sub(message,6,msgStart-1),string.sub(message,msgStart))
        end
      elseif compare("/quit ")==1 or compare("/quit") then
        if nick[senderId]~="&new" then
          post(addTime() .. "*".. nick[senderId] .. " has quit IRC (" .. string.sub(message,7) .. ")")
          nick[senderId]="&new"
        end
      elseif compare("/who")==1 then
        listUsers(userId)
      end
    else
      post(addTime().. "<" .. nick[senderId] .. "> " .. message)
    end
  else
    p(senderId,"@ircYou are not connected to IRC! type /join #irc")
  end
  end
until redstone.getInput("front")
rednet.close("left")
term.clear()
term.setCursorPos(1,1)
term.write("Closed Server!")
newline()
mon.write(addTime() .. "Closed Server!")
term.setCursorPos(1,2)

IRCclient
Note: Change SERVER = 29 to the ID of the server computer.
Code: [Select]
SERVER = 29
breakfree = false

function newline()
  term.scroll(1)
  term.setCursorPos(1,12)
end

function put(str)
  newline()
  term.write(str)
end

rednet.open("left")
rednet.announce()
function enterNick()
  term.clear()
  term.setCursorPos(1,1)
  print("Enter nickname:")
  username = read()
  if string.len(username) and string.len(username)<=16 then
    rednet.send(SERVER,"/nick " .. username)
    rednet.send(SERVER,"/join #IRC")
    return 0
  else
    return enterNick()
  end
end

enterNick()
function1 = function()
  while true do
    local senderId, message, distance = rednet.receive(1)
    if senderId and string.find(message,"@irc")==1 then
      local x,y = term.getCursorPos()
      put(string.sub(message,5))
      term.setCursorPos(x,y)
    end
    if redstone.getInput("front") then
      breakfree = true
      return
    end
  end
end

function2 = function()
  term.setCursorPos(1,14)
  local message = read()
  if string.find(message,"/quit")==1 then
    breakfree=true
  end
  rednet.send(SERVER,message)
  term.setCursorPos(1,14)
  term.write("                                                  ")
end

while not breakfree do
  parallel.waitForAny(function1,function2)
end
rednet.send(SERVER, "/quit Client")
rednet.close("left")

I typed and debugged all of this using the ingame editor. It really sucks there are no linenumbers.

Edit: There is just one glitch: You can join with a name that is taken, so for instance when Keoni29 is on the IRC another guy can impersonate me by joining with the same nickname. It's probably quite easy to fix, but I leave that to someone else. I have had enough of the tekkit lua programming.