Showing posts with label Computercraft. Show all posts
Showing posts with label Computercraft. Show all posts

RedNetChat v6 - A ComputerCraft chat program

-- [ --------------------------------------------------------------------- ] --
-- [ RedNetChat - A public chat program for ComputerCraft                  ] --
-- [ Created by gpgautier (ign gpgauier), 2012                             ] --
-- [ Licence: Creative Commons Attribution-ShareAlike 3.0 Unported License ] --
-- [ ComputerCraft version: 1.3 and up                                     ] --
-- [ Posted to:                                                            ] --
-- [ GitHub: https://github.com/gpgautier/RedNetChat                       ] --
-- [ Pastebin: http://pastebin.com/JDU4wJxX                                ] --
-- [ --------------------------------------------------------------------- ] --

local VERSION = "0.6"
local MODEM = nil
local NICKNAME = nil
local ACTIVE = false
local BUFFER = {}
local POINTER = 0
local ONLINE = {}
local ISONLINE = false
local ID = os.computerID()
local LAST_MSG_TARGET = nil
local CHANNEL = 1
local SCROLL_POINTER = POINTER
local WIDTH, HEIGHT = term.getSize()
local LINES = HEIGHT - 6
local START_LINE = 5
local OPERATOR = "RNC"

-- [ --------------------------------------------------------------------- ] --

-- Split a string
function split(str, pat)
    local t = {}  -- NOTE: use {n = 0} in Lua-5.0
    if str ~= nil then
       local fpat = "(.-)" .. pat
       local last_end = 1
       local s, e, cap = str:find(fpat, 1)
       while s do
          if s ~= 1 or cap ~= "" then
            table.insert(t,cap)
          end
          last_end = e+1
          s, e, cap = str:find(fpat, last_end)
       end
       if last_end <= #str then
          cap = str:sub(last_end)
          table.insert(t, cap)
       end
    else
        print("##ERROR failed to split ["..str.."] by:"..pat)
    end
    return t
end

-- Log a message to file
function log(message)
  local file = io.open("rednetchat.log", "a")
  file:write("\n" .. message)
  file:close()
end

-- Application entry
function main()
  term.clear()
  term.setCursorPos(1, 1)

  if not setPeripherals() then
    print("[FATAL ERROR] Not able to setup peripherals.")
    return false
  end
 
  welcome()
end

-- Set the attached peripherals. Opens rednet modem and warps monitor
function setPeripherals()
  local i, side

  for i, side in pairs(rs.getSides()) do
    if peripheral.isPresent(side) then
      if peripheral.getType(side) == "modem" then
        MODEM = side
        if not rednet.isOpen(side) then
          rednet.open(MODEM)
        end
      end
    end
  end
 
  -- Exit with a fatal error when modem not found
  if MODEM == nil then
    print("[FATAL ERROR] No modem was detected. Plase attach a modem on any side.")
    return false
  end

  return true
end

-- Start the welcome screen
function welcome()
  local x, y

  term.clear()
  writeHeader()

  print("")
  print("")
  print("Enter a nickname and press [enter].")
  print("")
  term.write("Nickname: ")
 
  x, y = term.getCursorPos()

  while NICKNAME == nil or NICKNAME == "" do
    term.setCursorPos(x, y)
    NICKNAME = read()
    execute("/online")
    appendBuffer("[" .. OPERATOR .. "]: Type /help for a list of commands")
  end
 
  start()
end

-- Writes the screen header
function writeHeader()
  local col

  term.setCursorPos(1, 1)
  term.write("RedNet Chat " .. VERSION .. "")
  term.setCursorPos(1, 2)

  for col = 1, WIDTH do
    term.write("-")
  end
end

-- Writes the list of online users
function writeOnlineList()
  local i, v, count, x, y, col

  count = 0

  x, y = term.getCursorPos()
 
  term.setCursorPos(1, HEIGHT - 1)

  for col = 1, WIDTH do
    term.write("-")
  end
 
  term.setCursorPos(1, HEIGHT)
  term.clearLine()
  term.write("Online: ")

  for i, v in pairs(ONLINE) do
    if count == 0 then
      term.write(i)
    else
      term.write(", " .. i)
    end

    count = count + 1
  end

  if count == 0 then
    term.write("Nobody online in channel " .. CHANNEL)
  end

  term.setCursorPos(x, y)
end

-- Start the chat
function start()
  term.clear()
  writeHeader()
  writeOnlineList()

  ACTIVE = true

  showBuffer()
 
  parallel.waitForAll(input, watchEvents)
end

-- Stop the application
function stop()
  ACTIVE = false
end

-- Reset the application
function reset()
  execute("/offline")

  if rednet.isOpen(MODEM) then
    rednet.close(MODEM)
  end

  sleep(1.5)
  os.reboot()
end

-- Watch all input to provide possible shortcuts (for example usernames)
function watchEvents()
  local type, param, param2, param3, i, v
 
  while ACTIVE do
    type, param, param2, param3 = os.pullEvent()

    if type == "key" then
      if param == 200 then -- up
        scroll(-1)
      elseif param == 208 then -- down
        scroll(1)
      elseif param == 201 then -- pageup
        scroll(-12)
      elseif param == 209 then -- pagedown
        scroll(12)
      --else
      --  appendBuffer(tostring(param))
      end
    elseif type == "mouse_scroll" then
      if param == -1 then
        scroll(-1)
      else
        scroll(1)
      end
    elseif type == "rednet_message" then
      receive(param2)
    end
  end
end

-- Scroll through the chat
function scroll(amount)
  SCROLL_POINTER = SCROLL_POINTER + amount
  showBuffer()
end

-- Handle input from the prompt
function input()
  local message, col

  term.setCursorPos(1, 4)
 
  for col = 1, WIDTH do
    term.write("-")
  end

  while ACTIVE do
    term.setCursorPos(1, 3)
    term.clearLine()
    term.write("[" .. CHANNEL .. "] > ")

    message = read()

    if message ~= nil and message ~= "" then
      execute(message, "local")
    end
  end
end

-- Send a message
function send(message, target)
  local request, serialized, x, encrypted

  request = {protocol = "rnc", nickname = NICKNAME, sender = ID, target = target, channel = CHANNEL, message = message}
  serialized = textutils.serialize(request)

  encrypted = ""
  for x = 1, #serialized do
    encrypted = encrypted .. string.char(serialized:byte(x) + 1)
  end

  if request.target ~= nil then    
    rednet.send(request.target, encrypted)
  else
    rednet.broadcast(encrypted)
  end
end

-- Recieve a message
function receive(message)
  local request, decrypted, x

  if message ~= nil and message ~= "" then

    decrypted = ""
    for x = 1, #message do
      decrypted = decrypted .. string.char(message:byte(x) - 1)
    end

    request = textutils.unserialize(decrypted)

    if request.protocol == "rnc" and request.channel == CHANNEL then
      if request.nickname ~= nil and request.nickname ~= "" then
        execute(request, "remote")
      end
    end
  end
end

-- Execute a command or add a chat message
function execute(message, source)
  local command, splitCommand, nickname, id, body, onlineUser
 
  if message.nickname ~= nil then
    executeRemote(message)
    return
  end

  if message:sub(0, 1) == "/" then
      command = message:sub(2)

      if command == "quit"
          or command == "reset"
          or command == "restart"
          or command == "reboot"
          or command == "stop"
        then
          appendBuffer("[" .. OPERATOR .. "]: Stopping application")
          reset()
      elseif command == "online" then
        if not ISONLINE then
          send("/online")
          putOnline()
          appendBuffer("[" .. OPERATOR .. "]: You are now online")
          ISONLINE = true
        else
          appendBuffer("[" .. OPERATOR .. "]: You are already online")
        end
      elseif command == "offline" then
        if ISONLINE then
          send("/offline")
          takeOffline()
          appendBuffer("[" .. OPERATOR .. "]: You are now offline")
          ISONLINE = false
        else
          appendBuffer("[" .. OPERATOR .. "]: You are already offline")
        end
      elseif command:sub(0, 5) == "nick " then
        takeOffline()
        NICKNAME = command:sub(6)
        putOnline()
        appendBuffer("[" .. OPERATOR .. "]: Your nickname has been changed")
      elseif command:sub(0, 5) == "slap " then
        appendBuffer(command:sub(6) .. " was slapped by " .. NICKNAME)
      elseif command:sub(0, 4) == "msg " then
        splitCommand = split(command:sub(5), "%s")

        onlineUser = false

        for nickname, id in pairs(ONLINE) do
          if nickname == splitCommand[1] then
            body = command:sub(5 + splitCommand[1]:len() + 1)
            send(body, id)
            appendBuffer(NICKNAME .. " > " .. nickname .. ": " .. body)
            onlineUser = true
            LAST_MSG_TARGET = nickname
          end
        end

        if not onlineUser then
            appendBuffer("[" .. OPERATOR .. "]: User " .. splitCommand[1] .. " is not online")
        end
      elseif command:sub(0, 2) == "r " then
        if LAST_MSG_TARGET ~= nil then
          execute("/msg " .. LAST_MSG_TARGET .. " " .. command:sub(3), "local")
        else
          appendBuffer("[" .. OPERATOR .. "]: No valid user for message")
        end
      elseif command:sub(0, 5) == "join " then
        if CHANNEL ~= tonumber(command:sub(6)) then
          execute("/offline")
          CHANNEL = tonumber(command:sub(6))
          execute("/online")
          appendBuffer("[" .. OPERATOR .. "]: Joined channel " .. CHANNEL)
        else
          appendBuffer("[" .. OPERATOR .. "]: Already in channel " .. CHANNEL)
        end
      elseif command == "help" then
        appendBuffer("[" .. OPERATOR .. "] Commands:")
        appendBuffer("/quit : Exit the chat")
        appendBuffer("/msg <nickname> <message> : Send a private message")
        appendBuffer("/r <message> : Reply to a private message")
        appendBuffer("/join <channel> : Switch channel")
      else
        appendBuffer("[" .. OPERATOR .. "]: Unknown command")
      end
     
      return
  end

  appendBuffer(NICKNAME .. ": " .. message)
  send(message)
end

--
function putOnline(nickname, id)
  if nickname == nil or id == nil then
    nickname = NICKNAME
    id = ID
  end

  ONLINE[nickname] = id

  writeOnlineList()
end

--
function takeOffline(nickname, id)
  if nickname == nil or id == nil then
    nickname = NICKNAME
    id = ID
  end

  ONLINE[nickname] = nil

  writeOnlineList()
end

--
function executeRemote(request)
  local command

  if request.message:sub(0, 1) == "/" then
    command = request.message:sub(2)

    if command == "online" then
      putOnline(request.nickname, request.sender)
      appendBuffer("[" .. OPERATOR .. "]: " .. request.nickname .. " is now online")
      send("/metoo")
    elseif command == "offline" then
      takeOffline(request.nickname, request.sender)
      appendBuffer("[" .. OPERATOR .. "]: " .. request.nickname .. " is now offline")
    elseif command == "metoo" then
      putOnline(request.nickname, request.sender)
    end
    return
  end

  if request.target ~= nil then
    appendBuffer(request.nickname .. " > " .. NICKNAME .. ": " .. request.message)
    LAST_MSG_TARGET = request.nickname
  else
    appendBuffer(request.nickname .. ": " .. request.message)
  end
end

--
function appendBuffer(message)
  local length

  length = message:len()

  if length > WIDTH then
    table.insert(BUFFER, message:sub(1, WIDTH))
    POINTER = POINTER + 1
    appendBuffer(message:sub(WIDTH + 1))
  else
    table.insert(BUFFER, message)
    POINTER = POINTER + 1
  end

  SCROLL_POINTER = POINTER

  showBuffer()
end

--
function showBuffer()
  local i, line, bufferPointer, x, y, pointer

  pointer = SCROLL_POINTER
 
  if pointer == 0 then
    return
  elseif SCROLL_POINTER > POINTER then
    SCROLL_POINTER = POINTER
    pointer = POINTER
  elseif POINTER < LINES + 1 then
    SCROLL_POINTER = POINTER
    pointer = POINTER
  elseif POINTER > LINES and SCROLL_POINTER < LINES then
    SCROLL_POINTER = LINES
    pointer = SCROLL_POINTER
  end

  x, y = term.getCursorPos()
 
  line = START_LINE

  bufferPointer = -(LINES - 1 - pointer)
 
  for i = bufferPointer, bufferPointer + (LINES - 1) do
    term.setCursorPos(1, line)
    term.clearLine()
   
    if BUFFER[i] ~= nil then
      term.write(tostring(BUFFER[i]))
    end
   
    line = line + 1
  end

  term.setCursorPos(x, y)
end

-- Fire up the application
main()

Computercraft mining turtle script with variable maxfuel

--Script by victorqyu aka. sol
--11/8/13
--For Computercraft for Minecraft
--For mining turtle.
--Requires pre-fueling. (The more the better but 64 coal is adequate)
--
--running arguments are x,y,z where;
--x = Number of cycles to move forward. (A cycle consists of 3 blocks on the axis of facing where the turtle occupies the central block) eg 10 cycles = 30 blocks
--y = the number of lines to mine to the left of the turtle.
--z = Max depth to dig down
--n = maxFuel value - Value over which coal and other fuels will not be consumed prior to dumping inventory.
--Enderchest to store items in must be placed in the turtle's last inventory slot
--

local tArgs = { ... }
if #tArgs ~= 4 then --If number of args does not equal this, print useage scirpt
print( "Usage: mineAll <# cycles forward> <# lines to the left> <Depth to dig> <Max fuel buffer(7000 recomended)>" )
return --Ends the program
end

-- VAR DEC's
local fwdCycleTarget = tonumber(tArgs[1]) --retrieve blocks to dig forward of turtle
local lftCycleTarget = tonumber(tArgs[2]) --retrieve blocks to dig left of turtle
local digDepth = tonumber(tArgs[3]) --retrieve depth to dig down
local maxFuel = tonumber(tArgs[4]) --Retrieve fuel buffer
local enoughFuel = false
local keepDigging = true
local oddRowNum = false
local miningComplete = false
local yCurPos = 0
local fwdCycleCurrent = 0
local lftCyclePos = 0
-- VAR DEC's

function checkFuel() --wait for turtle to have enough fuel to complete a cycle.
print("Checking fuel level...")
enoughFuel = false
while enoughFuel == false do
if turtle.getFuelLevel() > (7+digDepth*2) then
enoughFuel = true
else
print("Inadequate fuel to cycle")
print("Please place a fuel source in me.")
sleep(5)
shell.run("refuel all")
end
end
end

function dumpInvToChest() --place all items in inv into enderchest (retrieved from inv slot 16)
print("Clearing inventory...")
turtle.dig()
if turtle.getFuelLevel() < maxFuel then
shell.run("refuel all")
end
turtle.select(16)
turtle.place()
sleep(1)
for i = 1,15 do
turtle.select(i)
turtle.drop()
end
turtle.select(16)
turtle.dig()
end

function digCycle() --Dig one cycle & move into pos for next & dump inv to enderchest
print("Begining dig cycle...")
keepDigging = true
yCurPos = digDepth
--Diging part of cycle
while keepDigging == true do
turtle.digDown()
turtle.dig()
if turtle.down() == false then
turtle.dig()
keepDigging = false
end
if keepDigging == true then
yCurPos = yCurPos-1 --If turtle moved down, lower the Y height var by 1
end
if yCurPos == 0 then
keepDigging = false
end
end
--Return part of cycle
turtle.dig()
turtle.turnLeft()
turtle.turnLeft()
while yCurPos < digDepth do
turtle.dig()
turtle.digUp()
turtle.up()
yCurPos = yCurPos+1
end
--call the dump to enderchest func. to clear inv.
turtle.turnLeft()
turtle.turnLeft()
dumpInvToChest()
end

function movePos() --Move into the next position
print("Moving position...")
if fwdCycleCurrent+1 < fwdCycleTarget then --move up if we haven't met cycle count
turtle.dig()
turtle.forward()
turtle.dig()
turtle.forward()
turtle.dig()
turtle.forward()
fwdCycleCurrent=fwdCycleCurrent+1
elseif lftCyclePos+1 < lftCycleTarget and oddRowNum == false then --Get into pos for return line
turtle.dig()
turtle.forward()
turtle.turnLeft()
turtle.dig()
turtle.forward()
turtle.turnLeft()
turtle.dig()
turtle.forward()
lftCyclePos = lftCyclePos+1
fwdCycleCurrent = 0
oddRowNum = true
elseif lftCyclePos+1 < lftCycleTarget and oddRowNum == true then --this part is for the return line
turtle.dig()
turtle.forward()
turtle.turnRight()
turtle.dig()
turtle.forward()
turtle.turnRight()
turtle.dig()
turtle.forward()
lftCyclePos = lftCyclePos+1
fwdCycleCurrent = 0
oddRowNum = false
else
miningComplete = true
print("Mining Complete.")
end
end

shell.run("refuel all") --Initial Fuel up

while miningComplete == false do
checkFuel()
digCycle()
movePos()
end

Computercraft Solar Turtle Auto Mining Script

--Script by victorqyu aka. sol
--7/8/13
--For Computercraft for Minecraft
--For solar mining turtle.

--running arguments are x,y,z where;
--x = Number of cycles to move forward. (A cycle consists of 3 blocks on the axis of facing where the turtle occupies the central block) eg 10 cycles = 30 blocks
--y = the number of lines to mine to the left of the turtle.
--z = The starting height of the turtle (Used to calculate the fuel cost per cycle)
--
--Enderchest to store items in must be placed in the turtle's last inventory slot
--


local tArgs = { ... }
if #tArgs ~= 3 then --If number of args does not equal this, print useage scirpt
print( "Usage: mineAll <# cycles forwrd)> <# lines to the left> <fuel buffer(depth)>" )
return --Ends the program
end

-- VAR DEC's
local fwdCycleTarget = tonumber(tArgs[1]) --retrieve blocks to dig forward of turtle
local lftCycleTarget = tonumber(tArgs[2]) --retrieve blocks to dig left of turtle
local fuelBuffer = tonumber(tArgs[3]) --retrieve starting height.
local enoughFuel = false
local keepDigging = true
local oddRowNum = false
local miningComplete = false
local yCurPos = 0
local fwdCycleCurrent = 0
local lftCyclePos = 0
-- VAR DEC's

function waitForFuel() --wait for turtle to have enough fuel to complete a cycle.
print("Checking fuel level...")
enoughFuel = false
while enoughFuel == false do
if turtle.getFuelLevel() > (fuelBuffer*2) then
enoughFuel = true
else
print("Waiting for fuel...")
print("Fuel level is: "..turtle.getFuelLevel())
sleep(5)
end
end
end

function dumpInvToChest() --place all items in inv into enderchest (retrieved from inv slot 16)
print("Clearning inventory...")
turtle.dig()
turtle.select(16)
turtle.place()
sleep(1)
for i = 1,15 do
turtle.select(i)
turtle.drop()
end
turtle.select(16)
turtle.dig()
end

function digCycle() --Dig one cycle & move into pos for next & dump inv to enderchest
print("Begining dig cycle...")
keepDigging = true
yCurPos = 1000 --Arbitrary value so we dont deal with negatives
--Diging part of cycle
while keepDigging == true do
turtle.digDown()
turtle.dig()
if turtle.down() == false then
keepDigging = false
end
if keepDigging == true then
yCurPos = yCurPos-1 --If turtle moved down, lower the Y height var by 1
end
end
--Return part of cycle
turtle.turnLeft()
turtle.turnLeft()
while yCurPos < 1000 do
turtle.dig()
turtle.digUp()
turtle.up()
yCurPos = yCurPos+1
end
--call the dump to enderchest func. to clear inv.
turtle.turnLeft()
turtle.turnLeft()
dumpInvToChest()
end

function movePos() --Move into the next position
print("Moving position...")
if fwdCycleCurrent+1 < fwdCycleTarget then --move up if we haven't met cycle count
turtle.forward()
turtle.forward()
turtle.forward()
fwdCycleCurrent=fwdCycleCurrent+1
elseif lftCyclePos+1 < lftCycleTarget and oddRowNum == false then --Get into pos for return line
turtle.forward()
turtle.turnLeft()
turtle.forward()
turtle.turnLeft()
turtle.forward()
lftCyclePos = lftCyclePos+1
fwdCycleCurrent = 0
oddRowNum = true
elseif lftCyclePos+1 < lftCycleTarget and oddRowNum == true then --this part is for the return line
turtle.forward()
turtle.turnRight()
turtle.forward()
turtle.turnRight()
turtle.forward()
lftCyclePos = lftCyclePos+1
fwdCycleCurrent = 0
oddRowNum = false
else
miningComplete = true
print("Mining Complete.")
end
end

shell.run("refuel all")

while miningComplete == false do
waitForFuel()
digCycle()
movePos()
end

Computercraft Chat to Speech script

Little script to pull server chat messages and speak them using misc.preipherals speaker and chatbox
Chatbox on left, Speaker on right

--TODO: Compile a table of all networked speakers to cycle through to allow sound reproduction over a larger area
--TODO: Signed server chat to command execution

local chatMsg = ""
local chatBox = peripheral.wrap("left")
local speaker = peripheral.wrap("right")

function getChat()
eventTyp, chatPlr, chatMsg = os.pullEvent("chat")
end

function sayChat()
speaker.speak(chatMsg,0)
end

--Main loop
while true do
getChat()
sayChat()
end