Last active
July 28, 2019 03:05
-
-
Save MalkContent/9895d615f0765255d2a4ad99a5a3fb21 to your computer and use it in GitHub Desktop.
OpenComputers program to keep track of ImmersiveEngineering Mineral Deposits
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
commands:
requires lua 5.3 cpu
has autocomplete now :)
now supports t3 screens
now has touchscreen navigation (move buttons and click-on-destination)