Posted 18 May 2014 - 11:23 PM
I'm working on a system that provides centralized redstone door/wall/bridge/light control for a base or home. Every so often the server 'dies' with the error "vm error: java.langNullPointerException". Minecraft doesn't crash (so no crash log) and the Forge logs don't show anything except occasional world leaks (but no entries at the times this happens).
Does anyone have an idea if this is happening due to my program or is this beyond my control? If it's beyond my control is this a bug that should be brought to the bug thread?
Server
Client
Does anyone have an idea if this is happening due to my program or is this beyond my control? If it's beyond my control is this a bug that should be brought to the bug thread?
Server
Spoiler
Pastebin
--[[ WiRe Server ]]--
--[[ by Dog ]]--
--[[ aka HydrantHunter ]]--
--[[ Wi = Wireless ]]--
--[[ Re = Redstone ]]--
--[[ pastebin hqpRw4Jy ]]--
--[[ GPL v3 ]]--
local WiReSver = "1.0.00"
--[[
Tested with/requires:
- Mincraft 1.6.4
- ComputerCraft ver. 1.6+ for MC 1.6.4
- A Computer (standard or advanced) with a wireless modem and at least one (1) advanced monitor
]]--
local tArgs = { ... }
-- CONFIGURATION
-- Default Settings
local termX,termY = term.getSize()
local monX,monY
local me = os.getComputerID()
local config = "/data/WiReServerCfg"
local ccSettings = {
name = "WiReServer",
note = "short note",
color = "lgray",
}
local newCmdData = { }
local allClients = { }
local loc = { }
local pageNum, numPages = 1, 1
local quit = "NO"
local help = false
local ccSuccess = false
local kernelState = false
local mon, bio, wifiSide
local lockState = "Unlocked"
local client, thisCommand, pollTimer, sortDeviceList
-- Terminal Colors
local white = colors.white
local black = colors.black
local lgray = colors.lightGray
local gray = colors.gray
local brown = colors.brown
local yellow = colors.yellow
local orange = colors.orange
local red = colors.red
local magenta = colors.magenta
local purple = colors.purple
local blue = colors.blue
local lblue = colors.lightBlue
local cyan = colors.cyan
local lime = colors.lime
local green = colors.green
if not term.isColor() then
lgray = colors.white
gray = colors.black
brown = colors.white
yellow = colors.white
orange = colors.white
red = colors.white
magenta = colors.white
purple = colors.white
green = colors.white
blue = colors.black
lblue = colors.white
cyan = colors.white
lime = colors.white
green = colors.white
end
-- Monitor colors
local mwhite = colors.white
local mblack = colors.black
local mlgray = colors.lightGray
local mgray = colors.gray
local mbrown = colors.brown
local myellow = colors.yellow
local morange = colors.orange
local mred = colors.red
local mmagenta = colors.magenta
local mpurple = colors.purple
local mblue = colors.blue
local mlblue = colors.lightBlue
local mcyan = colors.cyan
local mlime = colors.lime
local mgreen = colors.green
-- END CONFIGURATION
local function saveData()
if not fs.exists("/data") then fs.makeDir("/data") end
local srvConfig = fs.open(config,"w") or error("saveData(): Cannot open " .. config .. " for writing", 2)
srvConfig.write(textutils.serialize(ccSettings))
srvConfig.close()
end
local function netSend(qry)
local tempSettings = { }
if qry then
tempSettings = { program = "WiRe", cc = me, color = ccSettings.color, cmd = "WiReQRY", }
else
tempSettings = { program = "WiRe", cc = me, color = ccSettings.color, cmd = thisCommand, }
end
if client then
if not rednet.isOpen(wifiSide) then
rednet.open(wifiSide)
end
rednet.send(client,tempSettings)
return true
end
return false
end
local function netReceive()
local netEvent = { rednet.receive() }
local sender = netEvent[1]
newCmdData = netEvent[2]
if type(newCmdData) == "table" then
if newCmdData.program == "WiRe" and newCmdData.cc == sender and newCmdData.color == ccSettings.color then
client = sender
sortDeviceList()
thisCommand = newCmdData.deviceState
ccSuccess = true
return
end
end
client = nil
thisCommand = "net noise"
ccSuccess = false
return
end
sortDeviceList = function()
for i = 1,#allClients,1 do
if client == allClients[i].cc then -- we're already on the list
allClients[i].name = newCmdData.name
allClients[i].deviceType = newCmdData.deviceType
allClients[i].deviceState = newCmdData.deviceState
allClients[i].quietCount = newCmdData.quietCount
allClients[i].loc.x = newCmdData.loc.x
allClients[i].loc.y = newCmdData.loc.y
allClients[i].loc.z = newCmdData.loc.z
return
end
end
-- Sort by name
if #allClients == 0 then -- the list is empty
table.insert(allClients,newCmdData) -- add it
numPages = math.ceil(#allClients/7)
if numPages < pageNum then pageNum = numPages end
else
for i = 1,#allClients,1 do
if newCmdData.name < allClients[i].name then -- alphabetize
table.insert(allClients,i,newCmdData) -- insert
numPages = math.ceil(#allClients/7)
if numPages < pageNum then pageNum = numPages end
break
end
if i >= #allClients then -- we've reached the end of the list
table.insert(allClients,newCmdData) -- tack it on
numPages = math.ceil(#allClients/7)
if numPages < pageNum then pageNum = numPages end
break
end
end
end
end
local function getColor(assignment)
local colorBurst = { Purple = purple, Blue = blue, ["Light Blue"] = lblue, Green = green, Red = red, Orange = orange, Brown = brown, ["Light Gray"] = lgray, }
for name,color in pairs(colorBurst) do
if assignment == tostring(name) then
return color
end
end
end
local function helpScreen()
local hText = "WiRe Server Help"
term.setBackgroundColor(black)
term.setTextColor(white)
term.clear()
term.setBackgroundColor(blue)
term.setCursorPos(1,1)
term.write(string.rep(" ",math.floor(termX/2)-(#hText/2)) .. hText .. string.rep(" ",math.ceil(termX/2)+(#hText/2)))
term.setBackgroundColor(black)
term.setCursorPos(termX/2-5,3)
term.write("Client list")
term.setCursorPos(termX/2-15,5)
term.write(", < [ { PGUP Go back one page")
term.setCursorPos(termX/2-15,7)
term.write(". > ] } PDDN Go forward one page")
end
local function termScreen()
local hText = "WiRe Server " .. WiReSver
term.setBackgroundColor(black)
term.setCursorPos(1,1)
term.setTextColor(white)
term.setBackgroundColor(blue)
term.write(string.rep(" ",math.floor(termX/2)-(#hText/2)) .. hText .. string.rep(" ",math.ceil(termX/2)+(#hText/2)))
term.setCursorPos(1,3)
term.setTextColor(lgray)
term.setBackgroundColor(black)
term.write("Name: ")
term.setTextColor(white)
term.write(ccSettings.name)
term.setCursorPos(1,4)
term.setTextColor(lgray)
term.write("Note: ")
term.setTextColor(white)
term.write(ccSettings.note)
term.setCursorPos(1,6)
term.setTextColor(lgray)
term.write("Group: ")
term.setTextColor(getColor(ccSettings.color))
term.write(ccSettings.color)
term.setCursorPos(1,8)
term.setTextColor(lgray)
term.write("cc# ")
term.setTextColor(white)
term.write(tostring(me))
term.setCursorPos(1,10)
term.setTextColor(lgray)
term.write("WiFi: ")
term.setTextColor(white)
term.write(wifiSide)
term.setCursorPos(1,12)
term.setTextColor(lgray)
term.write("Last Client: ")
term.setTextColor(white)
local lastClient = client or "System"
term.write(" ")
term.setCursorPos(14,12)
term.write(tostring(lastClient))
term.setCursorPos(1,13)
term.setTextColor(lgray)
term.write("Last State: ")
if thisCommand == "CLOSED" or thisCommand == "ON" then
term.setTextColor(green)
elseif thisCommand == "OPEN" or thisCommand == "OFF" then
term.setTextColor(orange)
elseif thisCommand == "LOCKED" then
term.setTextColor(red)
else
term.setTextColor(yellow)
end
term.write(" ")
term.setCursorPos(14,13)
term.write(thisCommand)
term.setCursorPos(1,14)
term.setTextColor(lgray)
term.write("Success: ")
if ccSuccess then
term.setTextColor(green)
else
term.setTextColor(red)
end
term.write(tostring(ccSuccess) .. " ")
term.setCursorPos(1,16)
term.setTextColor(lgray)
term.write("Location: ")
term.setTextColor(white)
term.write("x: " .. loc.x)
term.setCursorPos(11,17)
term.write("y: " .. loc.y)
term.setCursorPos(11,18)
term.write("z: " .. loc.z)
term.setCursorPos(26,3)
term.setTextColor(lgray)
term.write("Clients (page " .. tostring(pageNum) .. " of " .. tostring(numPages) .. ")")
local yPos = 0
for i = (pageNum * 7) - 6,#allClients,1 do
yPos = yPos + 1
term.setCursorPos(26,(yPos*2)+3)
term.setTextColor(white)
term.write(allClients[i].name .. " (" .. tostring(allClients[i].cc) .. ")" .. string.rep(" ",termX))
if allClients[i].deviceState == "CLOSED" or allClients[i].deviceState == "ON" then
term.setTextColor(green)
elseif allClients[i].deviceState == "OPEN" or allClients[i].deviceState == "OFF" then
term.setTextColor(orange)
elseif allClients[i].deviceState == "LOCKED" then
term.setTextColor(red)
end
term.setCursorPos(termX-6,(yPos*2)+3)
term.write(" ")
term.setCursorPos(termX-#allClients[i].deviceState,(yPos*2)+3)
term.write(allClients[i].deviceState)
term.setCursorPos(27,(yPos*2)+4)
term.setTextColor(lgray)
if allClients[i].loc.x == "No GPS Fix" then
term.write(allClients[i].loc.x)
else
term.write("x: " .. allClients[i].loc.x .. " y: " .. allClients[i].loc.y .. " z: " .. allClients[i].loc.z)
end
if i >= #allClients or i >= pageNum * 7 then break end
end
end
local function powerSwitch(x,y,state)
mon.setCursorPos(x,y)
if state == "OPEN" or state == "OFF" then
mon.setBackgroundColor(gray) --
mon.write(" ") --
mon.setCursorPos(x,y+1) -- Switch (ON/CLOSED)
mon.setBackgroundColor(orange) --
mon.write(" ") --
elseif state == "CLOSED" or state == "ON" then
mon.setBackgroundColor(green) --
mon.write(" ") --
mon.setCursorPos(x,y+1) -- Switch (OFF/OPEN)
mon.setBackgroundColor(gray) --
mon.write(" ") --
elseif state == "LOCKED" then
mon.setBackgroundColor(red) --
mon.write(" ") -- Switch (LOCKED)
mon.setCursorPos(x,y+1) --
mon.write(" ") --
end
end
local function monControls()
local labelText = ccSettings.name .. " (" .. ccSettings.color .. ")"
local monLabel = string.rep(" ",math.floor((monX/2)-(#labelText/2))) .. labelText .. string.rep(" ",math.ceil((monX/2)-(#labelText/2)))
mon.setBackgroundColor(gray)
mon.setTextColor(cyan)
mon.setCursorPos(1,1)
mon.write(monLabel)
mon.setCursorPos(1,monY)
mon.setBackgroundColor(mgray)
mon.write(string.rep(" ",monX))
mon.setTextColor(mred)
mon.setCursorPos((monX/4)-2,monY)
mon.write("Lock")
mon.setTextColor(mgreen)
mon.setCursorPos((monX-(monX/4))-3,monY)
mon.write("Unlock")
for i = 1,#allClients,1 do
mon.setCursorPos((i*8)-6,3)
mon.setBackgroundColor(mblack)
mon.setTextColor(mlblue)
mon.write(allClients[i].name:sub(1,6) .. string.rep(" ",6-#allClients[i].name:sub(1,6)))
mon.setCursorPos((i*8)-6,4)
mon.write(allClients[i].name:sub(7,12) .. string.rep(" ",6-#allClients[i].name:sub(7,12)))
powerSwitch((i*8)-6,5,allClients[i].deviceState)
mon.setCursorPos((i*8)-6,8)
mon.setBackgroundColor(mblack)
if allClients[i].deviceState == "CLOSED" or allClients[i].deviceState == "ON" then
mon.setTextColor(mgreen)
elseif allClients[i].deviceState == "OPEN" or allClients[i].deviceState == "OFF" then
mon.setTextColor(morange)
elseif allClients[i].deviceState == "LOCKED" then
mon.setTextColor(mred)
end
mon.write(" ")
mon.setCursorPos((i*8)-6,8)
mon.write(allClients[i].deviceState)
end
end
local function monTouch()
local touchEvent = { os.pullEvent("monitor_touch") }
local posX = touchEvent[3]
local posY = touchEvent[4]
if posY == monY then
if posX < monX/2 then
thisCommand = "LOCKED"
lockState = "Locked"
for i = 1,#allClients,1 do
client = allClients[i].cc
allClients[i].deviceState = thisCommand
ccSuccess = netSend()
end
return
elseif posX > monX/2 then
for i = 1,#allClients,1 do
if allClients[i].deviceType == "Door" then
allClients[i].deviceState = "CLOSED"
thisCommand = "CLOSED"
elseif allClients[i].deviceType == "Energy" then
allClients[i].deviceState = "ON"
thisCommand = "ON"
elseif allClients[i].deviceType == "Bridge" then
allClients[i].deviceState = "OFF"
thisCommand = "OFF"
end
client = allClients[i].cc
ccSuccess = netSend()
end
lockState = "Unlocked"
return
end
end
for i = 1,#allClients,1 do
if posX > (i*8)-8 and posX < (i*8) then
client = allClients[i].cc
if posY == 8 then
thisCommand = "LOCKED"
allClients[i].deviceState = thisCommand
ccSuccess = netSend()
return
elseif posY > 4 and posY < 7 then
if allClients[i].deviceState == "OPEN" or allClients[i].deviceState == "OFF" then
if allClients[i].deviceType == "Door" then
thisCommand = "CLOSED"
else
thisCommand = "ON"
end
allClients[i].deviceState = thisCommand
ccSuccess = netSend()
return
elseif allClients[i].deviceState == "CLOSED" or allClients[i].deviceState == "ON" then
if allClients[i].deviceType == "Door" then
thisCommand = "OPEN"
else
thisCommand = "OFF"
end
allClients[i].deviceState = thisCommand
ccSuccess = netSend()
return
elseif allClients[i].deviceState == "LOCKED" then
if allClients[i].deviceType == "Door" then
thisCommand = "CLOSED"
elseif allClients[i].deviceType == "Energy" then
thisCommand = "ON"
elseif allClients[i].deviceType == "Bridge" then
thisCommand = "OFF"
end
allClients[i].deviceState = thisCommand
ccSuccess = netSend()
return
end
end
end
end
client = nil
thisCommand = "touch"
ccSuccess = false
end
local function keyInput()
local keyEvent = { os.pullEvent("key") }
if keyEvent[2] == 201 then -- keys.pageUp
if pageNum > 1 then
pageNum = pageNum - 1
return
end
elseif keyEvent[2] == 209 then -- keys.pageDown
if pageNum < numPages then
for i = 5,termY,1 do
term.setCursorPos(26,i)
term.write(string.rep(" ",termX))
end
pageNum = pageNum + 1
return
end
elseif keyEvent[2] == 59 then -- keys.F1
help = not help
if help then
helpScreen()
else
term.clear()
return
end
end
return
end
local function charInput()
local charEvent = { os.pullEvent("char") }
if charEvent[2] == "," or charEvent[2] == "<" or charEvent[2] == "[" or charEvent[2] == "{" then
if pageNum > 1 then
pageNum = pageNum - 1
return
end
elseif charEvent[2] == "." or charEvent[2] == ">" or charEvent[2] == "]" or charEvent[2] == "}" then
if pageNum < numPages then
for i = 5,termY,1 do
term.setCursorPos(26,i)
term.write(string.rep(" ",termX))
end
pageNum = pageNum + 1
return
end
elseif charEvent[2] == "q" then
kernelState = false
rednet.close(wifiSide)
mon.setBackgroundColor(mblack)
mon.clear()
term.clear()
term.setCursorPos(1,1)
term.setTextColor(white)
term.write("WiRe Server is OFFLINE")
term.setCursorPos(1,3)
return
end
return
end
local function foregroundShell()
term.setBackgroundColor(black)
term.setTextColor(white)
term.clear()
term.setCursorPos(1,1)
if tArgs[1] then
if fs.exists(tArgs[1]) then
shell.run(tArgs[1])
end
end
mon.setBackgroundColor(mblack)
mon.clear()
term.setBackgroundColor(black)
term.clear()
term.setCursorPos(1,1)
shell.run("shell")
term.clear()
term.setCursorPos(1,1)
term.write("WiRe Server is OFFLINE")
term.setCursorPos(1,3)
end
local function dataPoller()
local timerEvent = { os.pullEvent("timer") }
if timerEvent[2] == pollTimer then
if kernelState then
local clCount = 0
for i = 1,#allClients,1 do
clCount = clCount + 1
if allClients[i].quietCount > 1 then
table.remove(allClients,i)
i = i - 1
if i == 0 then i = 1 end
if not help then
term.setBackgroundColor(black)
term.setCursorPos(26,4+clCount)
term.write(string.rep(" ",termX))
mon.setBackgroundColor(mblack)
mon.clear()
end
end
if clCount >= #allClients then break end
end
numPages = math.ceil(#allClients/7)
for i = 1,#allClients,1 do
client = allClients[i].cc
allClients[i].quietCount = allClients[i].quietCount + 1
ccSuccess = netSend("QRY")
end
client = nil
thisCommand = "WiReQRY"
pollTimer = os.startTimer(3)
return
end
end
end
local function ccKernel()
while kernelState do
if not tArgs[1] and not help then
termScreen()
end
monControls()
parallel.waitForAny(monTouch,keyInput,charInput,netReceive,dataPoller)
end
end
local function firstRun()
if not fs.exists("/data") then fs.makeDir("/data") end
-- Set server name
term.setCursorPos(2,2)
term.write("Please name this server")
while true do
term.setCursorPos(2,4)
local newName = tostring(read())
if newName ~= "" and newName ~= "nil" then
ccSettings.name = newName
break
end
end
-- Set server description
term.clear()
term.setCursorPos(2,2)
term.write("Please type in a short")
term.setCursorPos(2,3)
term.write("server description")
while true do
term.setCursorPos(2,5)
local newDesc = tostring(read())
if newDesc ~= "" and newDesc ~= "nil" then
ccSettings.note = newDesc
break
end
end
-- Set computer label
local ccLabel = os.getComputerLabel()
if ccLabel == nil or ccLabel == "" then
os.setComputerLabel(ccSettings.name)
end
-- Select color
local colorList = { P = "Purple", B = "Blue", L = "Light Blue", G = "Green", R = "Red", O = "Orange", N = "Brown", Y = "Light Gray", }
local colorPick = { P = purple, B = blue, L = lblue, G = green, R = red, O = orange, N = brown, Y = lgray, }
term.clear()
term.setCursorPos(2,2)
term.write("Select a group color")
local ttY = 4
for c,n in pairs(colorList) do
term.setCursorPos(2,ttY)
term.write(tostring(c) .. " = " .. n)
ttY = ttY + 1
end
term.setCursorPos(2,13)
while true do
local done = false
local newColor = string.upper(tostring(read()))
if newColor ~= "" and newColor ~= "nil" then
for k,v in pairs(colorList) do
if newColor == tostring(k) then
ccSettings.color = v
done = true
break
end
end
if done then break end
end
end
saveData()
end
local function initMe()
term.setBackgroundColor(black)
term.clear()
if not fs.exists(config) then firstRun() end
term.setCursorPos(2,2)
term.setTextColor(white)
term.write("Ingesting configuration data . . .")
local srvConfig = fs.open(config,"r") or error("41: Cannot open " .. config .. " for reading", 2)
local srvData = srvConfig.readAll()
ccSettings = textutils.unserialize(srvData)
srvConfig.close()
term.setCursorPos(2,4)
term.write("Configuring hardware . . .")
for _,side in ipairs(rs.getSides()) do
if peripheral.isPresent(side) then
if peripheral.getType(side) == "monitor" then
mon = peripheral.wrap(side)
elseif peripheral.getType(side) == "modem" then
if peripheral.call(side,"isWireless") then
wifiSide = side
if not rednet.isOpen(side) then
rednet.open(side)
end
else
for _,perp in ipairs(peripheral.call(side,"getNamesRemote")) do
if perp:sub(1,7) == "biolock" then
bio = perhiperal.wrap(perp)
elseif perp:sub(1,7) == "monitor" then
mon = peripheral.wrap(perp)
end
end
end
end
end
end
if not wifiSide then
term.clear()
term.setTextColor(red)
term.setCursorPos(1,2)
print("No modem detected!")
print("WiRe Server REQUIRES")
print("a wireless modem.")
term.setCursorPos(1,6)
quit = "YES"
return
end
if not mon then
term.clear()
term.setTextColor(red)
term.setCursorPos(1,2)
print("No monitor detected!")
print("WiRe Server REQUIRES")
print("an Advanced Monitor.")
term.setCursorPos(1,6)
quit = "YES"
return
end
if not mon.isColor() then
term.clear()
term.setTextColor(red)
term.setCursorPos(1,2)
print("Standard Monitor detected!")
print("WiRe Server REQUIRES an")
print("Advanced Monitor.")
term.setCursorPos(1,6)
quit = "YES"
return
end
mon.setTextScale(0.5)
monX,monY = mon.getSize()
mon.setBackgroundColor(mblack)
mon.clear()
term.setCursorPos(2,6)
term.write("Acquiring GPS fix . . .")
loc.x, loc.y, loc.z = gps.locate(2)
if not loc.x then
loc.x,loc.y,loc.z = "No GPS Fix","No GPS Fix","No GPS Fix"
end
local lookupName = "WiRe-" .. ccSettings.color
rednet.host(lookupName,ccSettings.name)
ccSuccess = true
thisCommand = "init"
kernelState = true
term.clear()
end
if os.clock() < 5 then sleep(math.random(0,1)) end
initMe()
pollTimer = os.startTimer(3)
if quit == "YES" then return end
if tArgs[1] then
parallel.waitForAny(ccKernel, foregroundShell)
else
ccKernel()
end
Client
Spoiler
Pastebin
--[[ WiRe Client ]]--
--[[ by Dog ]]--
--[[ aka HydrantHunter ]]--
--[[ Wi = Wireless ]]--
--[[ Re = Redstone ]]--
--[[ pastebin jtFa7V1n ]]--
--[[ GPL v3 ]]--
local WiReCver = "1.0.00"
--[[
Tested with/requires:
- Mincraft 1.6.4
- ComputerCraft ver. 1.6+ for MC 1.6.4
- A Computer (standard or advanced) with a wireless modem and an optional Advanced Monitor, or a Wireless Turtle (standard or advanced)
]]--
local tArgs = { ... }
-- CONFIGURATION
-- Default Settings
local mon = { }
--local bio = { }
local termX,termY = term.getSize()
local me = os.getComputerID()
local config = "/data/WiReClientCfg"
local ccSettings = {
name = "WiReClient",
note = "short note",
color = "lgray",
side = "top",
deviceType = "Door",
}
local loc = { }
local deviceState, deviceType = "QRY", "QRY"
local quit = "NO"
local ccSuccess = false
local kernelState = false
local server, wifiSide, thisCommand, pollTimer, GPS
-- Terminal Colors
local white = colors.white
local black = colors.black
local lgray = colors.lightGray
local gray = colors.gray
local brown = colors.brown
local yellow = colors.yellow
local orange = colors.orange
local red = colors.red
local magenta = colors.magenta
local purple = colors.purple
local blue = colors.blue
local lblue = colors.lightBlue
local cyan = colors.cyan
local lime = colors.lime
local green = colors.green
if not term.isColor() then
lgray = colors.white
gray = colors.black
brown = colors.white
yellow = colors.white
orange = colors.white
red = colors.white
magenta = colors.white
purple = colors.white
green = colors.white
blue = colors.black
lblue = colors.white
cyan = colors.white
lime = colors.white
green = colors.white
end
-- Monitor colors
local mwhite = colors.white
local mblack = colors.black
local mlgray = colors.lightGray
local mgray = colors.gray
local mbrown = colors.brown
local myellow = colors.yellow
local morange = colors.orange
local mred = colors.red
local mmagenta = colors.magenta
local mpurple = colors.purple
local mblue = colors.blue
local mlblue = colors.lightBlue
local mcyan = colors.cyan
local mlime = colors.lime
local mgreen = colors.green
-- END CONFIGURATION
local function saveData()
if not fs.exists("/data") then fs.makeDir("/data") end
local clientConfig = fs.open(config,"w") or error("saveData(): Cannot open " .. config .. " for writing", 2)
clientConfig.write(textutils.serialize(ccSettings))
clientConfig.close()
end
local function netSend()
local tempSettings = {
program = "WiRe",
cc = me,
name = ccSettings.name,
color = ccSettings.color,
deviceType = deviceType,
deviceState = deviceState,
quietCount = 0,
loc = loc
}
if not rednet.isOpen(wifiSide) then
rednet.open(wifiSide)
end
rednet.send(server,tempSettings)
return true
end
local function netReceive()
local netEvent = { rednet.receive() }
local sender = netEvent[1]
local newCmdData = netEvent[2]
if type(newCmdData) == "table" then
if newCmdData.program == "WiRe" and newCmdData.cc == sender and newCmdData.color == ccSettings.color then
server = sender
local validActions = { ON = true, OFF = true, OPEN = true, CLOSED = true, LOCKED = true, WiReQRY = true, }
if validActions[newCmdData.cmd] then
thisCommand = newCmdData.cmd
return true
else
return false
end
end
end
return false
end
local function getColor(assignment)
local colorBurst = { Purple = purple, Blue = blue, ["Light Blue"] = lblue, Green = green, Red = red, Orange = orange, Brown = brown, ["Light Gray"] = lgray, }
for name,color in pairs(colorBurst) do
if assignment == tostring(name) then
return color
end
end
end
local function termScreen()
local hText = "WiRe Client " .. WiReCver
term.setBackgroundColor(black)
term.setCursorPos(1,1)
term.setTextColor(white)
term.setBackgroundColor(blue)
term.write(string.rep(" ",math.floor(termX/2)-(#hText/2)) .. hText .. string.rep(" ",math.ceil(termX/2)+(#hText/2)))
term.setCursorPos(1,3)
term.setTextColor(lgray)
term.setBackgroundColor(black)
term.write("Name: ")
term.setTextColor(white)
term.write(ccSettings.name)
term.setCursorPos(1,4)
term.setTextColor(lgray)
term.write("Note: ")
term.setTextColor(white)
term.write(ccSettings.note)
term.setCursorPos(1,6)
term.setTextColor(lgray)
term.write("Group: ")
term.setTextColor(getColor(ccSettings.color))
term.write(ccSettings.color)
term.setCursorPos(1,8)
term.setTextColor(lgray)
term.write("cc# ")
term.setTextColor(white)
term.write(tostring(me))
term.setCursorPos(1,9)
term.setTextColor(lgray)
term.write("Server cc# ")
term.setTextColor(white)
term.write(tostring(server))
term.setCursorPos(1,11)
term.setTextColor(lgray)
term.write("WiFi: ")
term.setTextColor(white)
term.write(wifiSide)
term.setCursorPos(1,12)
term.setTextColor(lgray)
term.write("Redstone: ")
term.setTextColor(white)
term.write(ccSettings.side)
term.setCursorPos(1,14)
term.setTextColor(lgray)
term.write("Device Type: ")
term.setTextColor(white)
term.write(ccSettings.deviceType)
term.setCursorPos(1,15)
term.setTextColor(lgray)
term.write("Current State: ")
if deviceState == "LOCKED" then
term.setTextColor(red)
elseif deviceState == "OPEN" or deviceState == "OFF" then
term.setTextColor(orange)
elseif deviceState == "CLOSED" or deviceState == "ON" then
term.setTextColor(green)
end
term.write(deviceState .. " ")
term.setCursorPos(1,17)
term.setTextColor(lgray)
term.write("Last Command: ")
term.setTextColor(white)
term.write(thisCommand .. string.rep(" ",8))
term.setCursorPos(1,18)
term.setTextColor(lgray)
term.write("Success: ")
if ccSuccess then
term.setTextColor(green)
else
term.setTextColor(red)
end
term.write(tostring(ccSuccess) .. " ")
term.setCursorPos(30,3)
term.setTextColor(lgray)
term.write("Peripherals")
term.setCursorPos(30,5)
term.setTextColor(white)
if bio then term.write("Biolock") setCursorPos(30,7) end
if mon then term.write("Monitor") end
end
local function doAction() -- to switch to net activation, change 'deviceState =' to 'thisCommand =' ???
local actions = {
ON = function() rs.setOutput(ccSettings.side,true) deviceState = "ON" return true end, -- redstone - side + true/false
OFF = function() rs.setOutput(ccSettings.side,false) deviceState = "OFF" return true end, -- redstone - side + true/false
OPEN = function() rs.setOutput(ccSettings.side,false) deviceState = "OPEN" return true end, -- redstone - side + true/false
CLOSED = function() rs.setOutput(ccSettings.side,true) deviceState = "CLOSED" return true end, -- redstone - side + true/false
LOCKED = function() if deviceType == "Door" or deviceType == "Energy" then rs.setOutput(ccSettings.side,true) else rs.setOutput(ccSettings.side,false) end deviceState = "LOCKED" return true end, -- redstone - side + true/false
WiReQRY = function()
local rsState = rs.getOutput(ccSettings.side)
if rsState then
if deviceState ~= "LOCKED" then
if deviceType == "Door" then
deviceState = "CLOSED"
return true
elseif deviceType == "Energy" then
deviceState = "ON"
return true
elseif deviceType == "Bridge" then
deviceState = "ON"
return true
end
end
else
if deviceState ~= "LOCKED" then
if deviceType == "Door" then
deviceState = "OPEN"
return true
elseif deviceType == "Energy" then
deviceState = "OFF"
return true
elseif deviceType == "Bridge" then
deviceState = "OFF"
return true
end
end
end
end,
}
for cmd,func in pairs(actions) do
if tostring(cmd) == thisCommand then
return func()
end
end
return false
end
local function foregroundShell()
term.setBackgroundColor(black)
term.setTextColor(white)
term.clear()
term.setCursorPos(1,1)
if fs.exists(tArgs[1]) then
shell.run(tArgs[1])
end
term.setBackgroundColor(black)
term.clear()
term.setCursorPos(1,1)
shell.run("shell")
term.clear()
term.setCursorPos(1,1)
term.write("WiRe Client is OFFLINE")
term.setCursorPos(1,3)
end
local function dataPoller()
while true do
local timerEvent = { os.pullEvent("timer") }
if timerEvent[2] == pollTimer then
if kernelState then
thisCommand = "WiReQRY"
pollTimer = os.startTimer(10)
return
end
end
end
end
local function charInput()
local charEvent = { os.pullEvent("char") }
if charEvent[2] == "q" then
kernelState = false
rednet.close(wifiSide)
if mon[1] then
for i = 1,#mon,1 do
mon[i].setBackgroundColor(mblack)
mon[i].clear()
end
end
term.clear()
term.setCursorPos(1,1)
term.setTextColor(white)
term.write("WiRe Client is OFFLINE")
term.setCursorPos(1,3)
return
end
return
end
local function monTouch()
if not mon[1] then return end
for i = 1,#mon,1 do
if deviceState == "LOCKED" then
mon[i].setBackgroundColor(mred)
elseif deviceState == "OPEN" or deviceState == "OFF" then
mon[i].setBackgroundColor(morange)
elseif deviceState == "CLOSED" or deviceState == "ON" then
mon[i].setBackgroundColor(mgreen)
end
for j = 2,6,1 do
for k = 2,4,1 do
mon[i].setCursorPos(j,k)
mon[i].write(" ")
end
end
mon[i].setCursorPos(3,3)
mon[i].setTextColor(mwhite)
mon[i].write("<*>")
end
local touchEvent = { os.pullEvent("monitor_touch") }
if deviceState == "OPEN" or deviceState == "OFF" then
if deviceType == "Door" then
thisCommand = "CLOSED"
else
thisCommand = "ON"
end
return
elseif deviceState == "CLOSED" or deviceState == "ON" then
if deviceType == "Door" then
thisCommand = "OPEN"
else
thisCommand = "OFF"
end
return
end
end
local function bioTouch() --"biolock", userPrint, attachSide, learnedName, accessLevel
if not bio then return end
local touchEvent = { os.pullEvent("biolock") }
if deviceState == "OPEN" then
return "CLOSED",touchEvent[5]
else
return "OPEN",touchEvent[5]
end
end
local function ccKernel()
while kernelState do
if not tArgs[1] then
termScreen()
end
--local actionTrigger
if mon[1] then
parallel.waitForAny(netReceive,dataPoller,charInput,monTouch)
else
parallel.waitForAny(netReceive,dataPoller,charInput)
end
ccSuccess = doAction()
ccSuccess = netSend()
end
end
local function firstRun()
term.clear()
if not fs.exists("/data") then fs.makeDir("/data") end
-- Set computer name
term.setCursorPos(2,2)
term.write("Please name this device")
term.setCursorPos(3,3)
term.write("(12 characters or less)")
while true do
term.setCursorPos(2,4)
local newName = tostring(read())
if newName ~= "" and newName ~= "nil" then
if #newName > 12 then newName = newName:sub(1,12) end
ccSettings.name = newName
break
end
end
-- Set computer description
term.clear()
term.setCursorPos(2,2)
term.write("Please type in a short")
term.setCursorPos(2,3)
term.write("client description")
while true do
term.setCursorPos(2,5)
local newDesc = tostring(read())
if newDesc ~= "" and newDesc ~= "nil" then
ccSettings.note = newDesc
break
end
end
-- Set computer label
local ccLabel = os.getComputerLabel()
if ccLabel == nil or ccLabel == "" then
os.setComputerLabel(ccSettings.name)
end
term.clear()
term.setCursorPos(2,2)
term.write("Is this a door (d), an energy barrier (e),")
term.setCursorPos(2,3)
term.write("or a bridge (B)/>?")
while true do
term.setCursorPos(2,5)
local newType = tostring(read())
if string.lower(newType) == "d" or string.lower(newType) == "e" or string.lower(newType) == "b" then
if string.lower(newType) == "d" then
deviceType = "Door"
elseif string.lower(newType) == "e" then
deviceType = "Energy"
elseif string.lower(newType) == "b" then
deviceType = "Bridge"
end
ccSettings.deviceType = deviceType
break
end
end
-- Select color
local colorList = { P = "Purple", B = "Blue", L = "Light Blue", G = "Green", R = "Red", O = "Orange", N = "Brown", Y = "Light Gray", }
local colorPick = { P = purple, B = blue, L = lblue, G = green, R = red, O = orange, N = brown, Y = lgray, }
term.clear()
term.setCursorPos(2,2)
term.write("Select a group color")
local ttY = 4
for c,n in pairs(colorList) do
term.setCursorPos(2,ttY)
term.write(tostring(c) .. " = " .. n)
ttY = ttY + 1
end
term.setCursorPos(2,13)
while true do
local newColor = string.upper(tostring(read()))
if newColor ~= "" and newColor ~= "nil" then
for k,v in pairs(colorList) do
if newColor == tostring(k) then
ccSettings.color = v
break
end
end
break
end
end
-- Select redstone output side
term.clear()
term.setCursorPos(2,2)
term.write("Select a redstone output side")
local yPos = 3
for num,side in ipairs(rs.getSides()) do
yPos = yPos + 1
term.setCursorPos(2,yPos)
term.write(num .. ": " .. side)
end
repeat
local finished = false
term.setCursorPos(2,11)
local rsSide = read()
for num,side in ipairs(rs.getSides()) do
if rsSide == side or tonumber(rsSide) == num then
ccSettings.side = side
finished = true
break
end
end
until finished
saveData()
end
local function initMe()
term.setBackgroundColor(black)
if not fs.exists(config) then firstRun() end
term.clear()
term.setCursorPos(2,2)
term.setTextColor(white)
term.write("Ingesting configuration data . . .")
local clientConfig = fs.open(config,"r") or error("41: Cannot open " .. config .. " for reading", 2)
local clientData = clientConfig.readAll()
ccSettings = textutils.unserialize(clientData)
clientConfig.close()
term.setCursorPos(2,4)
term.write("Configuring hardware . . .")
for _,side in ipairs(rs.getSides()) do
if peripheral.isPresent(side) then
if peripheral.getType(side) == "biolock" then
bio = perhiperal.wrap(side)
elseif peripheral.getType(side) == "monitor" then
mon[#mon+1] = peripheral.wrap(side)
elseif peripheral.getType(side) == "modem" then
if peripheral.call(side,"isWireless") then
wifiSide = side
if not rednet.isOpen(side) then
rednet.open(side)
end
else -- need to figure out if rednet works over wired modems (to eliminate wireless if desired)
for _,perp in ipairs(peripheral.call(side,"getNamesRemote")) do
if perp:sub(1,7) == "biolock" then
bio = perhiperal.wrap(perp)
elseif perp:sub(1,7) == "monitor" then
mon[#mon+1] = peripheral.wrap(perp)
end
end
end
end
end
end
if not wifiSide then
term.clear()
term.setTextColor(red)
term.setCursorPos(1,2)
print("No modem detected!")
print("WiRe Client REQUIRES")
print("a wireless modem.")
term.setCursorPos(1,6)
quit = "YES"
return
end
if mon[1] then
for i = 1,#mon,1 do
mon[i].setTextScale(1)
mon[i].setBackgroundColor(mblack)
mon[i].clear()
if not mon[i].isColor() then
term.clear()
term.setTextColor(red)
term.setCursorPos(1,2)
print("Standard Monitor detected!")
print("WiRe Client REQUIRES an")
print("Advanced Monitor.")
term.setCursorPos(1,6)
quit = "YES"
return
end
end
end
term.setCursorPos(2,6)
term.write("Acquiring GPS fix . . .")
loc.x, loc.y, loc.z = gps.locate(2)
if not loc.x then
loc.x,loc.y,loc.z = "No GPS Fix","No GPS Fix","No GPS Fix"
end
term.setCursorPos(2,8)
term.write("Looking for WiRe Server . . .")
for i = 1,3,1 do
local lookupName = "WiRe-" .. ccSettings.color
local tmpServers = { rednet.lookup(lookupName) }
server = tmpServers[1] or nil
if not server then
sleep(2)
else
break
end
end
if not server then
term.clear()
term.setTextColor(red)
term.setCursorPos(1,2)
print("No server detected!")
print("WiRe Client REQUIRES")
print("a WiRe Server.")
term.setCursorPos(1,6)
quit = "YES"
return
end
deviceType = ccSettings.deviceType
if deviceType == "Door" then
rs.setOutput(ccSettings.side,true)
deviceState = "CLOSED"
elseif deviceType == "Energy" then
rs.setOutput(ccSettings.side,true)
deviceState = "ON"
elseif deviceType == "Bridge" then
rs.setOutput(ccSettings.side,false)
deviceState = "OFF"
end
ccSuccess = netSend()
thisCommand = "init"
kernelState = true
term.clear()
end
if os.clock() < 5 then sleep(math.random(1,2)) end
initMe()
pollTimer = os.startTimer(10)
if quit == "YES" then return end
if tArgs[1] then
parallel.waitForAny(foregroundShell, ccKernel)
else
ccKernel()
end