Skip to content

Instantly share code, notes, and snippets.

@MalkContent
Last active July 28, 2019 03:05
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save MalkContent/9895d615f0765255d2a4ad99a5a3fb21 to your computer and use it in GitHub Desktop.
OpenComputers program to keep track of ImmersiveEngineering Mineral Deposits
local term = require("term")
local gpu = term.gpu()
local seri = require("serialization")
local event = require("event")
local prefixes = {"get", "set", "near", "quit", "save", "load"}
local p_get = "^get%s+(-?%d+)%s+(-?%d+)$"
local p_near = "^near%s+(-?%d+)%s+(-?%d+)(.*)$"
local p_set = "^set%s+(-?%d+)%s+(-?%d+)%s+(.*)$"
local p_quit = "^quit$"
local p_save = "^save$"
local p_load = "^load$"
local savName = "veins.sav"
local nearRange = 32
local rectw = 13
local recth = 9
local xspacing = 4
local yspacing = 2
local xmoffset = 3
local ymoffset = 3
local drawnav = true
local buttons = {}
local timerId
local currentX, currentZ
local markX, markZ = math.huge, math.huge
local veinMap = {}
local veinNames = {"Bauxite", "Coal", "Copper", "Galena", "Gold", "Iron", "Lapis", "Lead", "Magnetite", "Nickel", "Platinum", "Pyrite", "Quarzite", "Silver", "Uranium"}
veinNames[0] = "No Mineral"
veinNames[-1] = "Unscanned"
veinNames[-2] = "scanned Area"
local vc = {[0] = 0xffffff, 0xffcc33, 0xcc66cc, 0x6699ff, 0xffff33, 0x33cc33, 0xff6699, 0x333333, 0xcccccc, 0x336699, 0x9933cc, 0x333399, 0x663300, 0x336600, 0xff3333, 0x000000}
local veinColors = {2, 12, 1, 3, 4, 8, 11, 3, 1, 13, 10, 14, 0, 3, 5}
veinColors[0] = 7
veinColors[-1] = 7
veinColors[-2] = 0
local function quitHint(line, index)
if index > 1 then
return {}
else
return {"Y", "n"}
end
end
local function comHint(line, index)
if line == "" then
return prefixes
end
local hints = {}
local mchstr = {string.match(line, "^%a+$")}
local carstr
if mchstr[1] then
carstr = string.lower(mchstr[1])
for i = 1, #prefixes do
if carstr == string.sub(prefixes[i], 1, index - 1) then
table.insert(hints, prefixes[i])
end
end
return hints
end
local mchstr = {string.match(line, "^((%a+)%s+-?%d+%s+-?%d+%s+)(%a*)$")}
if mchstr[2] == "set" or mchstr[2] == "near" then
local carstr = mchstr[3] and string.lower(mchstr[3]) or ""
local offset = index - string.len(mchstr[1]) - 1
for i = -1, #veinNames do
if carstr == string.lower(string.sub(veinNames[i], 1, offset)) then
table.insert(hints, mchstr[1] .. veinNames[i])
end
end
end
return hints
end
local histopts = {nowrap=true}
local function getStdIn(quitting)
return string.lower(string.match(term.read(quitting and {nowrap=true} or histopts, nil, quitting and quitHint or comHint), "^(.*)\n$"))
end
local function omSet(x, z, oreId)
if veinMap[x] == nil and oreId >= 0 then
veinMap[x] = {}
end
if veinMap[x] ~= nil then
if oreId >= 0 then
veinMap[x][z] = oreId
else
veinMap[x][z] = nil
if next(veinMap) == nil then
veinMap[x] = nil
end
end
end
end
local function omGet(x, z)
local veinType = -1
if veinMap[x] ~= nil and veinMap[x][z] ~= nil then
veinType = veinMap[x][z]
end
return veinType
end
local function writeOre(veinIndx)
local cvein = veinColors[veinIndx]
if cvein then
gpu.setForeground(vc[cvein])
end
cvein = veinNames[veinIndx]
term.write(cvein and cvein or veinIndx)
gpu.setForeground(vc[0])
end
local function squareChToBlk(x1, z1, x2, z2)
if x2 == nil then
x2 = x1
z2 = z1
else
if x1 > x2 then
x1, x2 = x2, x1
end
if z1 > z2 then
z1, z2 = z2, z1
end
end
return {16*x1, 16*z1, 15+16*x2, 15+16*z2}
end
local function printMainInfo(stay)
if not currentX or not currentZ then
return
end
local borders = squareChToBlk(currentX, currentZ)
local bx, by
if not stay then
bx, by = term.getCursor()
end
term.setCursor(1, 3)
term.clearLine()
term.write(borders[1] .. ", " .. borders[2] .. " to " .. borders[3] .. ", " .. borders[4] .. ": ") writeOre(omGet(currentX, currentZ))
if not stay then
term.setCursor(bx, by)
end
end
local function drawVeinInfo()
if not currentX or not currentZ then
return
end
local sqshx = 1 + rectw//2
local sqshz = 1 + recth//2
if drawnav then
gpu.setBackground(vc[14])
local btn
local cx
local cy
for i = 1, 4 do
if i <= 2 then
if i == 1 then
btn = " "
cx = xmoffset + sqshx*xspacing - 3
cy = ymoffset + 1
else
cy = ymoffset + recth*yspacing + 1
end
else
if i == 3 then
btn = " "
cy = ymoffset + sqshz*yspacing
cx = xmoffset - 1
else
cx = xmoffset + rectw*xspacing
end
end
term.setCursor(cx, cy)
term.write(btn)
buttons[i] = {cx, cy}
end
gpu.setBackground(vc[9])
cx = (sqshx - 1)*xspacing + xmoffset
cz = (sqshz - 1)*yspacing + ymoffset
for i = 1, 3 do
term.setCursor(cx, cz + i)
if i == 2 then
term.write(" ")
local bx, by = term.getCursor()
term.setCursor(bx + 1, by)
term.write(" ")
else
term.write(" ")
end
end
gpu.setBackground(vc[15])
drawnav = false
end
local bgcolored = false
local x, z = currentX - sqshx, currentZ - sqshz
local cmx, cmz = markX - currentX + sqshx, markZ - currentZ + sqshz
local vein
for cz = 1, recth do
for cx = 1, rectw do
if cx == sqshx and cz == sqshz then
bgcolored = true
gpu.setBackground(vc[9])
elseif cx == cmx and cz == cmz then
bgcolored = true
gpu.setBackground(vc[6])
end
term.setCursor(cx*xspacing - 2 + xmoffset, cz*yspacing + ymoffset)
veinIndex = omGet(x + cx, z + cz)
local cId = veinColors[veinIndex]
if cId then
gpu.setForeground(vc[cId])
else
gpu.setForeground(vc[0])
end
term.write((veinIndex >= 0 and veinIndex or "?"))
if bgcolored and (cx ~= sqshx or cz ~= sqshz) then
gpu.setBackground(vc[15])
bgcolored = false
end
term.write(" ")
if bgcolored then
gpu.setBackground(vc[15])
bgcolored = false
end
end
end
term.setCursor(1, 3 + ymoffset + 2 * recth)
local borders = squareChToBlk(x+1, z+1, x+rectw, z+recth)
gpu.setForeground(vc[0])
print("Area drawn: " .. borders[1] .. ", " .. borders[2] .. " to " .. borders[3] .. ", " .. borders[4])
end
local function searchNear(x, z, oreId)
local sx, sz
local dir, i
local ore
local nx, nz = nil, nil
local nore
local ndist = math.huge
ore = omGet(x, z)
if ore == oreId or (oreId == -2 and ore >= 0) then
return x, z, ore, 0
end
for curR = 1, nearRange do
sx = -curR
sz = -curR
for edge = 0, 3 do
i = ((edge % 2 == 0) and sx or sz)
dir = ((edge // 2 < 1) and 1 or -1)
while i*dir < curR do
if sx >= ndist or sz >= ndist then
return nx*16, nz*16, nore, math.floor(ndist * 1600)/100
end
ore = omGet(x+sx, z+sz)
if ore == oreId or (oreId == -2 and ore >= 0) then
local pyt = math.sqrt(math.pow (sx, 2) + math.pow (sz, 2))
if pyt < ndist then
ndist = pyt
nx, nz = x+sx, z+sz
nore = ore
end
end
i = i + dir
if(edge % 2 == 0) then
sx = i
else
sz = i
end
end
end
end
if nx then
return nx*16, nz*16, nore, math.floor(ndist * 1600)/100
end
end
local function getOreId(instr)
local ore = string.match(instr, "^[%a%s]+$")
if ore then
ore = string.lower(ore)
local nomatch = true
for i = -1, #veinNames do
if ore == string.lower(veinNames[i]) then
ore = i
nomatch = false
break
end
end
if nomatch then return nil end
else
ore = string.match(instr, "^-?%d+$")
if ore then
ore = tonumber(ore)
end
end
return ore
end
local function dinfo()
timerId = event.timer(2, printMainInfo)
end
local function loadFromFile()
local file = io.open(savName)
if file ~= nil then
local savVeins = file:read()
if savVeins ~= nil and savVeins ~= "" then
veinMap = seri.unserialize(savVeins)
local xz = veinMap.csav
if xz and not (currentX and currentZ) then
currentX = xz[1]
currentZ = xz[2]
veinMap.csav = nil
printMainInfo(true)
drawVeinInfo()
end
end
file:close()
end
end
local function saveToFile()
local pre = savName .. ".pre"
if currentX and currentZ then
veinMap.csav = {currentX, currentZ}
end
do
local file = io.open(pre, "w")
file:write(seri.serialize(veinMap))
file:close()
end
veinMap.csav = nil
local fsys = require("filesystem")
local path = fsys.path(require("process").info().path)
fsys.copy(path .. pre, path .. savName)
fsys.remove(path .. pre)
end
local run = true
local saved = true
local function parse(instr)
if timerId then
event.cancel(timerId)
end
if not instr or instr == "" then
printMainInfo(true)
return
end
local results = {string.match(instr, p_get)}
if results[1] == nil then
results = {string.match(instr, p_set)}
if results[1] then
local carstr = results[3]
local ore
if carstr and carstr ~= "" then
ore = getOreId(carstr)
end
if not ore then
return true
end
results[3] = ore
end
end
if results[1] == nil then
results = {string.match(instr, p_near)}
if results[1] then
local carstr = results[3]
local ore
if carstr and carstr ~= "" then
ore = getOreId(string.match(carstr, "^%s+(-?[%a%d]+)$"))
if not ore then
return true
end
else
ore = -2
end
local x, z = tonumber(results[1]), tonumber(results[2])
results = {searchNear(x//16, z//16, ore)}
if results[1] == nil then
term.write("No ") writeOre(ore) term.write(" found near " .. x .. ", " .. z)
return
end
markX, markZ = x//16, z//16
end
end
if results[1] ~= nil then
local x, z = tonumber(results[1])//16, tonumber(results[2])//16
if results[3] ~= nil and results[4] == nil then
omSet(x, z, tonumber(results[3]))
saved = false
end
currentX, currentZ = x, z
printMainInfo(true)
if results[4] then
term.write(", approx. " .. results[4] .. " blocks away")
else
markX, markZ = currentX, currentZ
end
drawVeinInfo()
return
end
results = {string.match(instr, p_quit)}
if results[1] ~= nil then
if saved == false then
term.write("Unsaved changes. Save before quitting (Y/n): ")
local c, r = term.getCursor()
local yn = getStdIn(true)
local width = gpu.getResolution() - c
while yn ~= "y" and yn ~= "n" do
gpu.fill(c, r, width, 1, " ")
term.setCursor(c, r)
yn = getStdIn(true)
end
if yn == "y" then
saveToFile()
end
end
run = false
return
end
results = {string.match(instr, p_save)}
if results[1] ~= nil then
saveToFile()
saved = true
print("Saved to File")
dinfo()
return
end
results = {string.match(instr, p_load)}
if results[1] ~= nil then
loadFromFile()
saved = true
print("Loaded from File")
dinfo()
drawVeinInfo()
return
end
return true
end
local function scroll(_, _, x, y, btn)
local mx1 = xmoffset - 2 + xspacing
local mx2 = mx1 + xspacing*rectw - 3
local my1 = ymoffset + yspacing
local my2 = my1 + yspacing*recth - 2
local cx, cy
local refresh = false
if x >= mx1 and x <= mx2 and y >= my1 and y <= my2 then
cx, cy = x - xmoffset + 2 - xspacing, y - ymoffset - yspacing
if cx % xspacing == 0 and cy % yspacing == 0 then
cx, cy = cx//xspacing - rectw//2, cy//yspacing - recth//2
if cx ~= 0 or cy ~= 0 then
currentX = currentX + cx
currentZ = currentZ + cy
refresh = true
end
end
else
local btnsize = 3
for i = 1, 4 do
if i == 2 then
btnsize = 2
end
local cbtn = buttons[i]
if y == cbtn[2] and x >= cbtn[1] and x < cbtn[1] + btnsize then
if i <= 2 then
currentZ = currentZ + (i == 2 and 1 or -1)
else
currentX = currentX + (i == 4 and 1 or -1)
end
refresh = true
end
end
end
if refresh then
cx, cy = term.getCursor()
printMainInfo(true)
drawVeinInfo()
term.setCursor(cx, cy)
end
end
local function getInput()
term.setCursor(1,2)
local ins = getStdIn()
term.setCursor(1,2)
term.clearLine()
term.setCursor(1,3)
term.clearLine()
return ins
end
term.clear()
print("Veintracker ™")
loadFromFile()
do
local tox = xmoffset + 2 + (rectw+1)*xspacing
local toy = 5
local numStr
for i = -1, #veinNames do
numStr = i .. (i<0 and "/?" or "")
term.setCursor(tox - string.len(numStr), toy + i)
term.write(numStr .. ": ")
gpu.setForeground(vc[veinColors[i]])
term.write(veinNames[i])
gpu.setForeground(vc[0])
end
end
event.listen("touch", scroll)
while run do
local ins = getInput()
if parse(ins) then
print("Invalid Input")
dinfo()
end
end
event.ignore("touch", scroll)
term.clear()
@MalkContent
Copy link
Author

MalkContent commented Sep 19, 2016

commands:

  • get x z
  • set x z oreid/orename
  • near x z (oreid/orename)
  • load
  • save
  • quit

requires lua 5.3 cpu
has autocomplete now :)
now supports t3 screens
now has touchscreen navigation (move buttons and click-on-destination)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment