Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- files = {
- "Project/startup.lua",
- "Project/API/sha",
- "Project/game/game.lua",
- "Project/game/map",
- "Project/maps/editor.lua",
- "Project/maps/editorlayout.nfp",
- "Project/maps/np",
- "Project/maps/house1/data.lvl",
- "Project/maps/house1/data.lvlDat",
- "Project/maps/house1/editor",
- "Project/maps/house2/data.lvl",
- "Project/maps/house2/data.lvlDat",
- "Project/maps/house2/editor",
- }
- fileData = {
- "side = \"top\" -- PLEASE REPLACE WITH YOUR MODEM SIDE\
- \
- local function getRunningPath()\
- local runningProgram = shell.getRunningProgram()\
- local programName = fs.getName(runningProgram)\
- return runningProgram:sub( 1, #runningProgram - #programName )\
- end\
- root = \"/\"\
- root = \"/\"..getRunningPath()\
- \
- os.loadAPI(root..\"/API/sha\")\
- \
- --[[\
- Hello and thanks for trying my experimental game :)\
- My goal is to make a multiplayer RPG (which is really hard to make, to be honest)\
- \
- ]]\
- \
- --Variablen\
- \
- rednet.open(side)\
- _ver = 2.1\
- _verstr = \"2.1\"\
- running = true\
- oldTerm = term.native()\
- connected = false\
- tmppw = \"\"\
- tmppw2 = \"\"\
- servRunning = false\
- usrName = \"\"\
- servId = 0\
- numbrs = {\
- \009\"0\",\
- \009\"1\",\
- \009\"2\",\
- \009\"3\",\
- \009\"4\",\
- \009\"5\",\
- \009\"6\",\
- \009\"7\",\
- \009\"8\",\
- \009\"9\",\
- }\
- msgs = {\
- \009\"ping\",\
- \009\"true\",\
- \009\"username\",\
- \009\"exists\",\
- \009\"new\",\
- \009\"wrong pw\",\
- \009\"deleteacc\",\
- \009\"changepw\"\
- }\
- \
- --Funktionen\
- \
- \
- function clear(bg, txt)\
- \009term.setCursorPos(1,1)\
- \009term.setBackgroundColor(bg)\
- \009term.setTextColor(txt)\
- \009term.clear()\
- end\
- \
- function limitRead(nLimit, replaceChar)\
- term.setCursorBlink(true)\
- local cX, cY = term.getCursorPos()\
- local rString = \"\"\
- if replaceChar == \"\" then replaceChar = nil end\
- repeat\
- local event, p1 = os.pullEvent()\
- if event == \"char\" then\
- -- Character event\
- if #rString + 1 <= nLimit then\
- rString = rString .. p1\
- write(replaceChar or p1)\
- end\
- elseif event == \"key\" and p1 == keys.backspace and #rString >= 1 then\
- -- Backspace\
- rString = string.sub(rString, 1, #rString-1)\
- xPos, yPos = term.getCursorPos()\
- term.setCursorPos(xPos-1, yPos)\
- write(\" \")\
- term.setCursorPos(xPos-1, yPos)\
- end\
- until event == \"key\" and p1 == keys.enter\
- term.setCursorBlink(false)\
- --print() -- Skip to the next line after clicking enter.\
- return rString\
- end\
- \
- function limitReadNumber(nLimit, replaceChar)\
- term.setCursorBlink(true)\
- local cX, cY = term.getCursorPos()\
- local rString = \"\"\
- if replaceChar == \"\" then replaceChar = nil end\
- repeat\
- local event, p1 = os.pullEvent()\
- if event == \"char\" then\
- -- Character event only numbers\
- for _, numbr in ipairs(numbrs) do\
- \009if p1 == numbrs[_] then\
- \009\009 \009if #rString + 1 <= nLimit then\
- \009\009 rString = rString .. p1\
- \009 \009 write(replaceChar or p1)\
- \009\009 end\
- \009\009end\
- \009end\
- elseif event == \"key\" and p1 == keys.backspace and #rString >= 1 then\
- -- Backspace\
- rString = string.sub(rString, 1, #rString-1)\
- xPos, yPos = term.getCursorPos()\
- term.setCursorPos(xPos-1, yPos)\
- write(\" \")\
- term.setCursorPos(xPos-1, yPos)\
- end\
- until event == \"key\" and p1 == keys.enter\
- term.setCursorBlink(false)\
- --print() -- Skip to the next line after clicking enter.\
- return rString\
- end\
- \
- function drawLauncher()\
- \009running = true\
- \009clear(colors.gray, colors.white)\
- \009local _p1 = false\
- \009local _p2 = false\
- \009local _pLogin = false\
- \009local _pRegister = false\
- \009local function page1()\
- \009\009_p1 = true\
- \009\009_p2 = false\
- \009\009grayWindow = window.create(oldTerm, 10, 5, 25, 10)\
- \009\009grayWindow.setBackgroundColor(colors.lightGray)\
- \009\009grayWindow.setTextColor(colors.black)\
- \009\009grayWindow.clear()\
- \009\009term.redirect(grayWindow)\
- \009\009term.setCursorPos(2,2)\
- \009\009term.setTextColor(colors.lime)\
- \009\009term.write(\"Enter server ID & connect.\")\
- \009\009idTxtBx = window.create(term.current(), 2, 4, 23, 1)\
- \009\009idTxtBx.setBackgroundColor(colors.gray)\
- \009\009idTxtBx.setTextColor(colors.lime)\
- \009\009idTxtBx.clear()\
- \009\009idTxtBx.write(\"Enter server ID...\")\
- \009\009term.setCursorPos(2,6)\
- \009\009term.setBackgroundColor(colors.gray)\
- \009\009term.setTextColor(colors.white)\
- \009\009term.write(\"Ping\")\
- \009\009term.setBackgroundColor(colors.lime)\
- \009\009term.setCursorPos(2,8)\
- \009\009term.write(\"Next\")\
- \009end\
- \
- \009local function page2()\
- \009\009_p2 = true\
- \009\009_p1 = false\
- \009\009grayWindow.setBackgroundColor(colors.lightGray)\
- \009\009grayWindow.setTextColor(colors.white)\
- \009\009grayWindow.clear()\
- \009\009term.setCursorPos(2,2)\
- \009\009term.setTextColor(colors.lime)\
- \009\009term.setBackgroundColor(colors.lightGray)\
- \009\009term.write(\"Enter Username\")\
- \009\009usrTxtBx = window.create(term.current(), 2, 4, 23, 1)\
- \009\009usrTxtBx.setBackgroundColor(colors.gray)\
- \009\009usrTxtBx.setTextColor(colors.lime)\
- \009\009usrTxtBx.clear()\
- \009\009usrTxtBx.write(\"Username...\")\
- \009end\
- \
- \009local function pageRegister()\
- \009\009_p2 = false\
- \009\009_p1 = false\
- \009\009_pLogin = false\
- \009\009_pRegister = true\
- \
- \009\009grayWindow.setBackgroundColor(colors.lightGray)\
- \009\009grayWindow.setTextColor(colors.white)\
- \009\009grayWindow.clear()\
- \009\009term.setCursorPos(2,2)\
- \009\009term.setTextColor(colors.lime)\
- \009\009term.write(\"Register\")\
- \009\009pwTxtBx = window.create(term.current(), 2, 4, 23, 1)\
- \009\009pwTxtBx.setBackgroundColor(colors.gray)\
- \009\009pwTxtBx.setTextColor(colors.lime)\
- \009\009pwTxtBx.clear()\
- \009\009pwTxtBx.write(\"Password...\")\
- \009\009pwTxtBx2 = window.create(term.current(), 2, 6, 23, 1)\
- \009\009pwTxtBx2.setBackgroundColor(colors.gray)\
- \009\009pwTxtBx2.setTextColor(colors.lime)\
- \009\009pwTxtBx2.clear()\
- \009\009pwTxtBx2.write(\"Repeat password...\")\
- \009end\
- \
- \009local function pageLogin()\
- \009\009_p2 = false\
- \009\009_p1 = false\
- \009\009_pRegister = false\
- \009\009_pLogin = true\
- \009\009grayWindow.setBackgroundColor(colors.lightGray)\
- \009\009grayWindow.setTextColor(colors.white)\
- \009\009grayWindow.clear()\
- \009\009term.setCursorPos(2,2)\
- \009\009term.setTextColor(colors.lime)\
- \009\009term.write(\"Login: \"..usrName)\
- \009\009pwTxtBx = window.create(term.current(), 2, 4, 23, 1)\
- \009\009pwTxtBx.setBackgroundColor(colors.gray)\
- \009\009pwTxtBx.setTextColor(colors.lime)\
- \009\009pwTxtBx.clear()\
- \009\009pwTxtBx.write(\"Password...\")\
- \009end\
- \
- \009page1()\
- \009while running do\
- \009\009local event, button, x, y = os.pullEventRaw(\"mouse_click\")\
- \009\009if button == 1 and _p1 and x >= 11 and x <= 33 and y == 8 then\
- \009\009\009term.redirect(idTxtBx)\
- \009\009\009term.clear()\
- \009\009\009term.setCursorPos(1,1)\
- \009\009\009servId = limitReadNumber(23)\
- \009\009\009term.redirect(grayWindow)\
- \009\009\009if #servId > 0 then\
- \009\009\009\009servId = tonumber(servId)\
- \009\009\009\009succ, t = ping(servId)\
- \009\009\009\009if succ then\
- \009\009\009\009\009term.setCursorPos(2,6)\
- \009\009\009\009\009term.setBackgroundColor(colors.green)\
- \009\009\009\009\009term.setTextColor(colors.white)\
- \009\009\009\009\009term.write(\"Ping\")\
- \009\009\009\009\009connected = true\
- \009\009\009\009else\
- \009\009\009\009\009term.setCursorPos(2,6)\
- \009\009\009\009\009term.setBackgroundColor(colors.red)\
- \009\009\009\009\009term.setTextColor(colors.white)\
- \009\009\009\009\009term.write(\"Ping\")\
- \009\009\009\009\009connected = false\
- \009\009\009\009end\
- \
- \009\009\009end\
- \009\009elseif button == 1 and _p1 and connected and x >= 11 and x <= 14 and y == 12 then\
- \009\009\009_p1 = false\
- \009\009\009_p2 = true\
- \009\009\009page2()\
- \009\009elseif button == 1 and _p2 and x >= 11 and x <= 33 and y == 8 then\
- \009\009\009term.redirect(usrTxtBx)\
- \009\009\009term.clear()\
- \009\009\009term.setCursorPos(1,1)\
- \009\009\009usrName = limitRead(8)\
- \009\009\009term.redirect(grayWindow)\
- \009\009\009if #usrName > 0 then\
- \009\009\009\009succ, t = checkUsrName(usrName)\
- \009\009\009\009if succ == \"exists\" then\
- \009\009\009\009\009pageLogin()\
- \009\009\009\009elseif succ == \"new\" then\
- \009\009\009\009\009pageRegister()\
- \009\009\009\009elseif succ == \"timeout\" then\
- \009\009\009\009\009_p2 = false\
- \009\009\009\009\009_p1 = true\
- \009\009\009\009\009page1()\
- \009\009\009\009else\
- \009\009\009\009\009_p2 = false\
- \009\009\009\009\009_p1 = true\
- \009\009\009\009\009page1()\
- \009\009\009\009end\
- \009\009\009end\
- \009\009elseif button == 1 and _pRegister and x >= 11 and x <= 33 and y == 8 then\
- \009\009\009term.redirect(pwTxtBx)\
- \009\009\009term.clear()\
- \009\009\009term.setCursorPos(1,1)\
- \009\009\009tmppw = limitRead(23, \"*\")\
- \009\009\009term.redirect(grayWindow)\
- \009\009elseif button == 1 and _pRegister and x >= 11 and x <= 33 and y == 10 then\
- \009\009\009term.redirect(pwTxtBx2)\
- \009\009\009term.clear()\
- \009\009\009term.setCursorPos(1,1)\
- \009\009\009tmppw2 = limitRead(23, \"*\")\
- \009\009\009term.redirect(grayWindow)\
- \009\009\009if #tmppw2 > 0 and #tmppw > 0 then\
- \009\009\009\009if tmppw == tmppw2 then\
- \009\009\009\009\009succ, t = sendRegister()\
- \009\009\009\009\009if succ then\
- \009\009\009\009\009\009_pRegister = false\
- \009\009\009\009\009\009page2()\
- \009\009\009\009\009else\
- \009\009\009\009\009\009_pRegister = false\
- \009\009\009\009\009\009page1()\
- \009\009\009\009\009end\
- \009\009\009\009else\
- \009\009\009\009\009term.redirect(pwTxtBx2)\
- \009\009\009\009\009term.setCursorPos(1,1)\
- \009\009\009\009\009term.clear()\
- \009\009\009\009\009term.setTextColor(colors.red)\
- \009\009\009\009\009term.write(\"Password doesn't match.\")\
- \009\009\009\009\009term.setTextColor(colors.lime)\
- \009\009\009\009\009term.redirect(grayWindow)\
- \009\009\009\009end\
- \009\009\009end\
- \009\009elseif button == 1 and _pLogin and x >= 11 and x <= 33 and y == 8 then\
- \009\009\009term.redirect(pwTxtBx)\
- \009\009\009term.clear()\
- \009\009\009term.setCursorPos(1,1)\
- \009\009\009tmppw = limitRead(23, \"*\")\
- \009\009\009term.redirect(grayWindow)\
- \009\009\009if #tmppw > 0 then\
- \009\009\009\009succ, a, b = sendLogin()\
- \009\009\009\009if succ == \"success\" then\
- \009\009\009\009\009running = false\
- \009\009\009\009\009term.redirect(oldTerm)\
- \009\009\009\009\009clear(colors.black, colors.white)\
- \009\009\009\009\009shell.run(root..\"game/game.lua \"..usrName..\" \"..a..\" \"..root..\" \"..tostring(servId))\
- \009\009\009\009\009break\
- \009\009\009\009elseif succ == \"wrong pw\" then\
- \009\009\009\009\009term.redirect(pwTxtBx)\
- \009\009\009\009\009term.clear()\
- \009\009\009\009\009term.setCursorPos(1,1)\
- \009\009\009\009\009term.setTextColor(colors.red)\
- \009\009\009\009\009term.write(\"Wrong Password...\")\
- \009\009\009\009\009term.setTextColor(colors.lime)\
- \009\009\009\009\009term.redirect(grayWindow)\
- \009\009\009\009elseif succ == \"timeout\" then\
- \009\009\009\009\009_pLogin = false\
- \009\009\009\009\009page1()\
- \009\009\009\009end\
- \009\009\009end\
- \009\009end\
- \009end\
- end\
- \
- function ping(id)\
- \009rednet.send(id, msgs[1])\
- \009id, msg = rednet.receive(3)\
- \009if msg == msgs[2] then\
- \009\009return true\
- \009else\
- \009\009return false\
- \009end\
- end\
- \
- function sendLogin()\
- \009local usrData = {\
- \009\009name = \"\",\
- \009\009encpw = \"\",\
- \009}\
- \009usrData.name = usrName\
- \009usrData.encpw = sha.sha256(tmppw..usrName)\
- \009rednet.send(servId, msgs[4], textutils.serialize(usrData))\
- \009id, msg = rednet.receive(3)\
- \009if msg == msgs[2] then\
- \009\009return \"success\", usrData.encpw\
- \009elseif msg == msgs[6] then\
- \009\009return \"wrong pw\"\
- \009else\
- \009\009return \"timeout\"\
- \009end\
- \
- end\
- \
- function sendRegister()\
- \009local usrData = {\
- \009\009name = \"\",\
- \009\009encpw = \"\",\
- \009}\
- \009usrData.encpw = sha.sha256(tmppw..usrName)\
- \009usrData.name = usrName\
- \
- \009rednet.send(servId, msgs[5], textutils.serialize(usrData))\
- \009id, msg = rednet.receive(3)\
- \009if msg == msgs[2] then\
- \009\009return true\
- \009else\
- \009\009return false\
- \009end\
- end\
- \
- function checkUsrName(name)\
- \009rednet.send(servId, msgs[3], name)\
- \009id, msg = rednet.receive(3)\
- \009if msg == msgs[4] then\
- \009\009return \"exists\"\
- \009elseif msg == msgs[5] then\
- \
- \009\009return \"new\"\
- \009else\
- \009\009return \"timeout\"\
- \009end\
- end\
- \
- --Code\
- \
- drawLauncher()",
- "\009\
- \
- \
- -- \
- -- Adaptation of the Secure Hashing Algorithm (SHA-244/256)\
- -- Found Here: http://lua-users.org/wiki/SecureHashAlgorithm\
- -- \
- -- Using an adapted version of the bit library\
- -- Found Here: https://bitbucket.org/Boolsheet/bslf/src/1ee664885805/bit.lua\
- -- \
- \
- local MOD = 2^32\
- local MODM = MOD-1\
- \
- local function memoize(f)\
- local mt = {}\
- local t = setmetatable({}, mt)\
- function mt:__index(k)\
- local v = f(k)\
- t[k] = v\
- return v\
- end\
- return t\
- end\
- \
- local function make_bitop_uncached(t, m)\
- local function bitop(a, b)\
- local res,p = 0,1\
- while a ~= 0 and b ~= 0 do\
- local am, bm = a % m, b % m\
- res = res + t[am][bm] * p\
- a = (a - am) / m\
- b = (b - bm) / m\
- p = p*m\
- end\
- res = res + (a + b) * p\
- return res\
- end\
- return bitop\
- end\
- \
- local function make_bitop(t)\
- local op1 = make_bitop_uncached(t,2^1)\
- local op2 = memoize(function(a) return memoize(function(b) return op1(a, b) end) end)\
- return make_bitop_uncached(op2, 2 ^ (t.n or 1))\
- end\
- \
- local bxor1 = make_bitop({[0] = {[0] = 0,[1] = 1}, [1] = {[0] = 1, [1] = 0}, n = 4})\
- \
- local function bxor(a, b, c, ...)\
- local z = nil\
- if b then\
- a = a % MOD\
- b = b % MOD\
- z = bxor1(a, b)\
- if c then z = bxor(z, c, ...) end\
- return z\
- elseif a then return a % MOD\
- else return 0 end\
- end\
- \
- local function band(a, b, c, ...)\
- local z\
- if b then\
- a = a % MOD\
- b = b % MOD\
- z = ((a + b) - bxor1(a,b)) / 2\
- if c then z = bit32_band(z, c, ...) end\
- return z\
- elseif a then return a % MOD\
- else return MODM end\
- end\
- \
- local function bnot(x) return (-1 - x) % MOD end\
- \
- local function rshift1(a, disp)\
- if disp < 0 then return lshift(a,-disp) end\
- return math.floor(a % 2 ^ 32 / 2 ^ disp)\
- end\
- \
- local function rshift(x, disp)\
- if disp > 31 or disp < -31 then return 0 end\
- return rshift1(x % MOD, disp)\
- end\
- \
- local function lshift(a, disp)\
- if disp < 0 then return rshift(a,-disp) end\
- return (a * 2 ^ disp) % 2 ^ 32\
- end\
- \
- local function rrotate(x, disp)\
- x = x % MOD\
- disp = disp % 32\
- local low = band(x, 2 ^ disp - 1)\
- return rshift(x, disp) + lshift(low, 32 - disp)\
- end\
- \
- local k = {\
- 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,\
- 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,\
- 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,\
- 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,\
- 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,\
- 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,\
- 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,\
- 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,\
- 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,\
- 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,\
- 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,\
- 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,\
- 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,\
- 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,\
- 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,\
- 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,\
- }\
- \
- local function str2hexa(s)\
- return (string.gsub(s, \".\", function(c) return string.format(\"%02x\", string.byte(c)) end))\
- end\
- \
- local function num2s(l, n)\
- local s = \"\"\
- for i = 1, n do\
- local rem = l % 256\
- s = string.char(rem) .. s\
- l = (l - rem) / 256\
- end\
- return s\
- end\
- \
- local function s232num(s, i)\
- local n = 0\
- for i = i, i + 3 do n = n*256 + string.byte(s, i) end\
- return n\
- end\
- \
- local function preproc(msg, len)\
- local extra = 64 - ((len + 9) % 64)\
- len = num2s(8 * len, 8)\
- msg = msg .. \"\\128\" .. string.rep(\"\\0\", extra) .. len\
- assert(#msg % 64 == 0)\
- return msg\
- end\
- \
- local function initH256(H)\
- H[1] = 0x6a09e667\
- H[2] = 0xbb67ae85\
- H[3] = 0x3c6ef372\
- H[4] = 0xa54ff53a\
- H[5] = 0x510e527f\
- H[6] = 0x9b05688c\
- H[7] = 0x1f83d9ab\
- H[8] = 0x5be0cd19\
- return H\
- end\
- \
- local function digestblock(msg, i, H)\
- local w = {}\
- for j = 1, 16 do w[j] = s232num(msg, i + (j - 1)*4) end\
- for j = 17, 64 do\
- local v = w[j - 15]\
- local s0 = bxor(rrotate(v, 7), rrotate(v, 18), rshift(v, 3))\
- v = w[j - 2]\
- w[j] = w[j - 16] + s0 + w[j - 7] + bxor(rrotate(v, 17), rrotate(v, 19), rshift(v, 10))\
- end\
- \
- local a, b, c, d, e, f, g, h = H[1], H[2], H[3], H[4], H[5], H[6], H[7], H[8]\
- for i = 1, 64 do\
- local s0 = bxor(rrotate(a, 2), rrotate(a, 13), rrotate(a, 22))\
- local maj = bxor(band(a, b), band(a, c), band(b, c))\
- local t2 = s0 + maj\
- local s1 = bxor(rrotate(e, 6), rrotate(e, 11), rrotate(e, 25))\
- local ch = bxor (band(e, f), band(bnot(e), g))\
- local t1 = h + s1 + ch + k[i] + w[i]\
- h, g, f, e, d, c, b, a = g, f, e, d + t1, c, b, a, t1 + t2\
- end\
- \
- H[1] = band(H[1] + a)\
- H[2] = band(H[2] + b)\
- H[3] = band(H[3] + c)\
- H[4] = band(H[4] + d)\
- H[5] = band(H[5] + e)\
- H[6] = band(H[6] + f)\
- H[7] = band(H[7] + g)\
- H[8] = band(H[8] + h)\
- end\
- \
- function sha256(msg)\
- msg = preproc(msg, #msg)\
- local H = initH256({})\
- for i = 1, #msg, 64 do digestblock(msg, i, H) end\
- return str2hexa(num2s(H[1], 4) .. num2s(H[2], 4) .. num2s(H[3], 4) .. num2s(H[4], 4) ..\
- num2s(H[5], 4) .. num2s(H[6], 4) .. num2s(H[7], 4) .. num2s(H[8], 4))\
- end",
- "side = \"top\" --PLEASE CHANGE TO YOUR MODEM SIDE\
- os.loadAPI(root..\"API/sha\")\
- \
- \
- \
- \
- --[[\
- MAIN GAME\
- PLEASE EXECUTE LAUNCHER FIRST\
- ]]\
- \
- --Variablen\
- rednet.open(side)\
- _ver = 0.5\
- _verstr = \"0.5\"\
- running = true\
- menu = false\
- servId = 0\
- chatMax = 0\
- chatLeft = 0\
- chatMissing = 0\
- \
- chat = {\
- \
- }\
- \
- msgs = {\
- \009\"ping\",\
- \009\"true\",\
- \009\"username\",\
- \009\"exists\",\
- \009\"new\",\
- \009\"wrong pw\",\
- \009\"deleteacc\",\
- \009\"changepw\",\
- \009\"getplayerdata\",\
- \009\"spawnplayer\",\
- \009\"getworlddata\",\
- \009\"uploadplayerdata\",\
- \009\"getChat\",\
- \009\"sendMessage\"\
- }\
- \
- numbrs = {\
- \009\"0\",\
- \009\"1\",\
- \009\"2\",\
- \009\"3\",\
- \009\"4\",\
- \009\"5\",\
- \009\"6\",\
- \009\"7\",\
- \009\"8\",\
- \009\"9\",\
- }\
- \
- usrData = {\
- \009name = \"Sir\",\
- \009encpw = \"Nobody\",\
- }\
- \
- playerData = {\
- \009users = {\
- \
- \009},\
- \009inventory = {\
- \
- \009},\
- \009worlds = {\
- \
- \009},\
- \009posX = {\
- \
- \009},\
- \009posY = {\
- \
- \009}\
- }\
- \
- mapData = {\
- \009\
- }\
- \
- --Hauptfunktionen\
- function clear(bg, txt)\
- \009term.setCursorPos(1,1)\
- \009term.setBackgroundColor(bg)\
- \009term.setTextColor(txt)\
- \009term.clear()\
- end\
- \
- function limitRead(nLimit, replaceChar)\
- term.setCursorBlink(true)\
- local cX, cY = term.getCursorPos()\
- local rString = \"\"\
- if replaceChar == \"\" then replaceChar = nil end\
- repeat\
- local event, p1 = os.pullEventRaw()\
- if event == \"char\" then\
- -- Character event\
- if #rString + 1 <= nLimit then\
- rString = rString .. p1\
- write(replaceChar or p1)\
- end\
- elseif event == \"key\" and p1 == keys.backspace and #rString >= 1 then\
- -- Backspace\
- rString = string.sub(rString, 1, #rString-1)\
- xPos, yPos = term.getCursorPos()\
- term.setCursorPos(xPos-1, yPos)\
- write(\" \")\
- term.setCursorPos(xPos-1, yPos)\
- end\
- until event == \"key\" and p1 == keys.enter\
- term.setCursorBlink(false)\
- --print() -- Skip to the next line after clicking enter.\
- return rString\
- end\
- \
- function limitReadNumber(nLimit, replaceChar)\
- term.setCursorBlink(true)\
- local cX, cY = term.getCursorPos()\
- local rString = \"\"\
- if replaceChar == \"\" then replaceChar = nil end\
- repeat\
- local event, p1 = os.pullEventRaw()\
- if event == \"char\" then\
- -- Character event only numbers\
- for _, numbr in ipairs(numbrs) do\
- \009if p1 == numbrs[_] then\
- \009\009 \009if #rString + 1 <= nLimit then\
- \009\009 rString = rString .. p1\
- \009 \009 write(replaceChar or p1)\
- \009\009 end\
- \009\009end\
- \009end\
- elseif event == \"key\" and p1 == keys.backspace and #rString >= 1 then\
- -- Backspace\
- rString = string.sub(rString, 1, #rString-1)\
- xPos, yPos = term.getCursorPos()\
- term.setCursorPos(xPos-1, yPos)\
- write(\" \")\
- term.setCursorPos(xPos-1, yPos)\
- end\
- until event == \"key\" and p1 == keys.enter\
- term.setCursorBlink(false)\
- --print() -- Skip to the next line after clicking enter.\
- return rString\
- end\
- \
- --Funktionen\
- \
- function drawIntro(col)\
- \009clear(colors.black, colors.white)\
- \009term.setTextColor(col)\
- \009term.setCursorPos(1,8)\
- \009term.write(\"O~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~O\")\
- \009term.setCursorPos(1,9)\
- \009term.write(\"| A multiplayer RPG |\")\
- \009term.setCursorPos(1,10)\
- \009term.write(\"| By Piorjade |\")\
- \009term.setCursorPos(1,11)\
- \009term.write(\"| @2016 |\")\
- \009term.setCursorPos(1,12)\
- \009term.write(\"O~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~O\")\
- end\
- \
- function redrawMainMenu(c)\
- \009if c == 1 then\
- \009\009clear(colors.black, colors.white)\
- \009\009term.setCursorPos(2, 2)\
- \009\009term.write(\"Hello, \"..usrData.name)\
- \009\009term.setCursorPos(2, 4)\
- \009\009print(\"> Play\")\
- \009\009print(\" Change Password\")\
- \009\009print(\" Delete User\")\
- \009\009print(\" Exit\")\
- \009elseif c == 2 then\
- \009\009clear(colors.black, colors.white)\
- \009\009term.setCursorPos(2, 2)\
- \009\009term.write(\"Hello, \"..usrData.name)\
- \009\009term.setCursorPos(2, 4)\
- \009\009print(\" Play\")\
- \009\009print(\" > Change Password\")\
- \009\009print(\" Delete User\")\
- \009\009print(\" Exit\")\
- \009elseif c == 3 then\
- \009\009clear(colors.black, colors.white)\
- \009\009term.setCursorPos(2, 2)\
- \009\009term.write(\"Hello, \"..usrData.name)\
- \009\009term.setCursorPos(2, 4)\
- \009\009print(\" Play\")\
- \009\009print(\" Change Password\")\
- \009\009print(\" > Delete User\")\
- \009\009print(\" Exit\")\
- \009elseif c == 4 then\
- \009\009clear(colors.black, colors.white)\
- \009\009term.setCursorPos(2, 2)\
- \009\009term.write(\"Hello, \"..usrData.name)\
- \009\009term.setCursorPos(2, 4)\
- \009\009print(\" Play\")\
- \009\009print(\" Change Password\")\
- \009\009print(\" Delete User\")\
- \009\009print(\" > Exit\")\
- \009end\
- end\
- \
- function deleteAccount()\
- \009rednet.send(servId, msgs[7], textutils.serialize(usrData))\
- \009id, msg = rednet.receive(3)\
- \009if msg == msgs[2] then\
- \009\009return \"success\"\
- \009elseif msg == msgs[6] then\
- \009\009return \"wrong pw\"\
- \009else\
- \009\009return \"timeout\"\
- \009end\
- end\
- \
- function changePassword(pw)\
- \009local changed = {\
- \009\009oldData = {\
- \009\009\009name = \"\",\
- \009\009\009encpw = \"\",\
- \
- \009\009},\
- \009\009newData = {\
- \009\009\009name = \"\",\
- \009\009\009encpw = \"\",\
- \009\009},\
- \009}\
- \
- \009changed.oldData = usrData\
- \009changed.newData.name = usrData.name\
- \009changed.newData.encpw = sha.sha256(pw)\
- \009rednet.send(servId, msgs[8], textutils.serialize(changed))\
- \009id, msg = rednet.receive(3)\
- \009if msg == msgs[2] then\
- \009\009usrData = changed.newData\
- \009\009return \"success\"\
- \009elseif msg == msgs[6] then\
- \009\009return \"wrong pw\"\
- \009else\
- \009\009return \"timeout\"\
- \009end\
- \
- end\
- \
- function drawMainMenu()\
- \009local timer = 0.08\
- \009drawIntro(colors.black)\
- \009sleep(timer)\
- \009drawIntro(colors.gray)\
- \009sleep(timer)\
- \009drawIntro(colors.lightGray)\
- \009sleep(timer)\
- \009drawIntro(colors.white)\
- \009sleep(2.25)\
- \009drawIntro(colors.lightGray)\
- \009sleep(timer)\
- \009drawIntro(colors.gray)\
- \009sleep(timer)\
- \009drawIntro(colors.black)\
- \
- \009redrawMainMenu(1)\
- \009local _mm = 1\
- \009menu = true\
- \
- \009while menu do\
- \009\009local event, a, b, c = os.pullEventRaw(\"key\")\
- \009\009if a == keys.down and _mm < 4 then\
- \009\009\009redrawMainMenu(_mm+1)\
- \009\009\009_mm = _mm+1\
- \009\009elseif a == keys.up and _mm > 1 then\
- \009\009\009redrawMainMenu(_mm-1)\
- \009\009\009_mm = _mm-1\
- \009\009elseif a == keys.enter and _mm == 1 then\
- \009\009\009menu = false\
- \009\009\009drawGame()\
- \009\009\009--do stuff\
- \
- \009\009elseif a == keys.enter and _mm == 2 then\
- \009\009\009term.setCursorPos(20, 5)\
- \009\009\009local tmppw = limitRead(23, \"*\")\
- \009\009\009if #tmppw > 0 then\
- \009\009\009\009succ = changePassword(tmppw)\
- \009\009\009\009if succ == \"success\" then\
- \009\009\009\009\009term.setCursorPos(20, 6)\
- \009\009\009\009\009term.write(\"Success.\")\
- \009\009\009\009\009sleep(1.5)\
- \009\009\009\009\009shell.run(root..\"game/game.lua \"..usrData.name..\" \"..usrData.encpw..\" \"..root..\" 1\")\
- \009\009\009\009elseif succ == \"wrong pw\" then\
- \009\009\009\009\009menu = false\
- \009\009\009\009\009clear(colors.black, colors.white)\
- \009\009\009\009\009print(\"Error: wrong password!\")\
- \009\009\009\009\009sleep(1.5)\
- \009\009\009\009\009clear(colors.black, colors.white)\
- \009\009\009\009\009break\
- \009\009\009\009elseif succ == \"timeout\" then\
- \009\009\009\009\009menu = false\
- \009\009\009\009\009clear(colors.black, colors.white)\
- \009\009\009\009\009print(\"Error: Server timed out.\")\
- \009\009\009\009\009sleep(1.5)\
- \009\009\009\009\009clear(colors.black, colors.white)\
- \009\009\009\009\009break\
- \009\009\009\009end\
- \009\009\009end\
- \
- \009\009elseif a == keys.enter and _mm == 3 then\
- \009\009\009succ = deleteAccount()\
- \009\009\009if succ == \"success\" then\
- \009\009\009\009menu = false\
- \009\009\009\009clear(colors.black, colors.white)\
- \009\009\009\009print(\"Successfully deleted your account, thanks for playing.\")\
- \009\009\009\009sleep(1.5)\
- \009\009\009\009clear(colors.black, colors.white)\
- \009\009\009\009break\
- \009\009\009elseif succ == \"wrong pw\" then\
- \009\009\009\009menu = false\
- \009\009\009\009clear(colors.black, colors.white)\
- \009\009\009\009print(\"Error: wrong password!\")\
- \009\009\009\009sleep(1.5)\
- \009\009\009\009clear(colors.black, colors.white)\
- \009\009\009\009break\
- \009\009\009elseif succ == \"timeout\" then\
- \009\009\009\009menu = false\
- \009\009\009\009clear(colors.black, colors.white)\
- \009\009\009\009print(\"Error: Server timed out.\")\
- \009\009\009\009sleep(1.5)\
- \009\009\009\009clear(colors.black, colors.white)\
- \009\009\009\009break\
- \009\009\009end\
- \
- \009\009elseif a == keys.enter and _mm == 4 then\
- \009\009\009clear(colors.black, colors.white)\
- \009\009\009print(\"Thank you for playing.\")\
- \009\009\009break\
- \009\009end\
- \009end\
- end\
- \
- function sendspawn()\
- \009rednet.send(servId, msgs[10], usrData.name)\
- \009local id, msg, msg2 = rednet.receive(3)\
- \009if msg == msgs[2] then\
- \009\009playerData = textutils.unserialize(msg2)\
- \009\009term.setCursorPos(31,8)\
- \009\009return true\
- \009end\
- end\
- \
- function getworld()\
- \009local usrnmbr = \"bob\"\
- \009local found = false\
- \009--[[for _, usr in ipairs(playerData.users) do\
- \009\009if usr == usrData.name then\
- \009\009\009usrnmbr = _\
- \009\009\009found = true\
- \009\009\009break\
- \009\009end\
- \009end\
- \009if found == false then print(\"player not found\") else print(\"found\") end]]\
- \
- \009\
- \009pInWorldList = window.create(oldTerm, 27, 1, 25, 9)\
- \009pInWorldList.setBackgroundColor(colors.gray)\
- \009pInWorldList.setTextColor(colors.lime)\
- \009pInWorldList.clear()\
- \
- \009--[[\
- \009\009\009\009CLIENT METHOD\
- \
- \009\009\009\009This method loads the maplayout and the data directly from the client.\
- \009\009\009\009I decided to use this while I was testing, because the server sometimes\
- \009\009\009\009failed to send the map. (more info in the SERVER METHOD comment)\
- \009]]\
- \
- \009local file = fs.open(root..\"maps/\"..playerData.worlds[usrData.name]..\"/data.lvlDat\",\"r\")\
- \009local dat = file.readAll()\
- \009mapData = textutils.unserialize(dat)\
- \009file.close()\
- \009_map = paintutils.loadImage(root..\"maps/\"..playerData.worlds[usrData.name]..\"/data.lvl\")\
- \009term.redirect(mapWindow)\
- \009clear(colors.black, colors.white)\
- \009paintutils.drawImage(_map, 1, 1)\
- \009term.redirect(oldTerm)\
- \009redrawEntitites()\
- \009--[[\
- \009\009\009\009SERVER METHOD\
- \
- \009\009\009\009This method use(d) rednet to DOWNLOAD the map from the server,\
- \009\009\009\009so only the server had to update the maps and the Client was basically\
- \009\009\009\009universal for ALL servers\
- \
- \009\009\009\009The problem here is that (at least for me in CCEmuRedux) the server sometimes failed\
- \009\009\009\009to send the map-data and layout, which leads to a black screen and no ability to move\
- \
- \
- \009\009\009\009If someone is able to fix this, please PM me on the forum, write a reply on the official topic,\
- \009\009\009\009or try to commit the fix on GitHub (idk how that works for unauthorized people lol)\
- \009]]\
- \
- \
- \
- \009--[[rednet.send(servId, msgs[11], playerData.worlds[usrData.name])\
- \
- \009id, msg, msg2 = rednet.receive(3)\
- \009if msg == msgs[2] then\
- \009\009term.setCursorPos(5,16)\
- \009\009term.write(\"TRUE\")\
- \009\009local map = textutils.unserialize(msg2)\
- \009\009local file = fs.open(root..\"game/map\",\"w\")\
- \009\009file.write(map.layout) \009\009\009\009\009\
- \009\009file.close()\009\009\009\009\009\009\009\009\009\009\009\009\009BUG WITH THIS: the server sometimes sends an empty map layout which leads to breaking the game\
- \009\009mapData = map.data\
- \009\009_map = paintutils.loadImage(root..\"game/map\")\
- \009\009sleep(0.1)\
- \009\009--fs.delete(root..\"game/map\")\
- \009\009clear(colors.black, colors.white)\
- \009\009paintutils.drawImage(_map, 1, 1)\
- \009\009--local file = fs.open(\"/tmp\",\"w\")\
- \009\009--file.write(textutils.serialize(mapData))\009\009\009ENABLE FOR DEBUGGING\
- \009\009--file.close()\
- \009\009redrawEntitites()\
- \009end]]\
- end\
- \
- function redrawMap()\
- \009term.redirect(mapWindow)\
- \009paintutils.drawImage(_map, 1, 1)\
- \009term.redirect(oldTerm)\
- end\
- \
- function redrawEntitites()\
- \009term.redirect(mapWindow)\
- \009local counter = 0\
- \009local myworld = playerData.worlds[usrData.name]\
- \009--[[for _, player in pairs(playerData.users) do\
- \009\009if player == usrData.name then\
- \009\009\009myworld = playerData.worlds[player]\
- \009\009end\
- \009\009\
- \009end]]\
- \009for _, player in pairs(playerData.users) do\
- \009\009if playerData.worlds[player] == myworld then\
- \009\009\009local x = playerData.posX[_]\
- \009\009\009local y = playerData.posY[_]\
- \009\009\009term.setCursorPos(tonumber(x), tonumber(y))\
- \009\009\009term.setTextColor(colors.white)\
- \009\009\009term.setBackgroundColor(colors.black)\
- \009\009\009term.write(\"P\")\
- \009\009\009term.redirect(pInWorldList)\
- \009\009\009term.setCursorPos(1,1+counter)\
- \009\009\009term.setTextColor(colors.lime)\
- \009\009\009term.setBackgroundColor(colors.gray)\
- \009\009\009term.write(player)\
- \009\009\009term.setBackgroundColor(colors.black)\
- \009\009\009term.setTextColor(colors.white)\
- \009\009\009term.redirect(mapWindow)\
- \009\009\009counter = counter+1\
- \009\009end\
- \009end\
- \009for _, ladderY in ipairs(mapData.laddersY) do\
- \009\009term.setCursorPos(mapData.laddersX[_], ladderY)\
- \009\009term.setBackgroundColor(colors.brown)\
- \009\009term.setTextColor(colors.yellow)\
- \009\009term.write(\"H\")\
- \009end\
- \009term.redirect(oldTerm)\
- end\
- \
- function getEntities()\
- \009while true do\
- \009\009sleep(0.1)\
- \009\009rednet.send(servId, msgs[9])\
- \009\009id, msg, msg2 = rednet.receive(0.1)\
- \009\009if msg == msgs[2] then\
- \009\009\009playerData = textutils.unserialize(msg2)\
- \009\009\009local counter = 0\
- \009\009\009term.setBackgroundColor(colors.black)\
- \009\009\009term.setTextColor(colors.white)\
- \009\009\009redrawMap()\
- \009\009\009redrawEntitites()\
- \009\009--[[else\
- \009\009\009clear(colors.black, colors.white)\
- \009\009\009print(\"Timeout.\")\
- \009\009\009sleep(1.5)\
- \009\009\009os.reboot()]]\
- \009\009end\
- \009end\
- end\009\
- \
- function uploadEntities()\
- \009local changed = {\
- \009\009playerData = {\
- \
- \009\009},\
- \009\009changer = {\
- \009\009\009name = \"\",\
- \009\009}\
- \009}\
- \
- \009changed.playerData = playerData\
- \009changed.changer.name = usrData.name\
- \
- \009rednet.send(servId, msgs[12], textutils.serialize(changed))\
- \
- \009id, msg = rednet.receive(0.1)\
- \
- \009--[[if msg ~=msgs[2] then\
- \009\009clear(colors.black, colors.white)\
- \009\009print(\"Timeout.\")\
- \009end]]\
- end\
- \
- function move()\
- \009local lagfaktor = 0.2\
- \009while true do\
- \009\009local event, key = os.pullEvent(\"key_up\")\
- \009\009local usrnmbr = 0\
- \009\009if key == keys.right then\
- \009\009\009--[[for _, usr in pairs(playerData.users) do\
- \009\009\009\009if usr == usrData.name then\
- \009\009\009\009\009usrnmbr = _\
- \009\009\009\009end\
- \009\009\009end]]\
- \009\009\009oldX = tonumber(playerData.posX[usrData.name])\
- \009\009\009oldY = tonumber(playerData.posY[usrData.name])\
- \009\009\009local block = false\
- \009\009\009for _, bY in ipairs(mapData.blocksY) do\
- \009\009\009\009\009if oldX+1 == mapData.blocksX[_] and oldY == bY then\
- \009\009\009\009\009\009term.setCursorPos(27, 3)\
- \009\009\009\009\009\009term.setTextColor(colors.white)\
- \009\009\009\009\009\009term.write(\"BLOCK\")\
- \009\009\009\009\009\009block = true\
- \009\009\009\009\009\009break\
- \009\009\009\009\009else\
- \009\009\009\009\009\009block = false\
- \009\009\009\009\009end\
- \009\009\009end\
- \009\009\009if block ~= true then\
- \009\009\009\009term.setCursorPos(27, 3)\
- \009\009\009\009term.setTextColor(colors.white)\
- \009\009\009\009term.write(\"BLECK\")\
- \009\009\009\009playerData.posX[usrData.name] = playerData.posX[usrData.name]+1\
- \009\009\009\009uploadEntities()\
- \009\009\009\009redrawMap()\
- \009\009\009\009redrawEntitites()\
- \009\009\009end\009\
- \009\009\009sleep(lagfaktor)\
- \009\009elseif key == keys.left then\
- \009\009\009--[[for _, usr in ipairs(playerData.users) do\
- \009\009\009\009if usr == usrData.name then\
- \009\009\009\009\009usrnmbr = _\
- \009\009\009\009end\
- \009\009\009end]]\
- \009\009\009oldX = tonumber(playerData.posX[usrData.name])\
- \009\009\009oldY = tonumber(playerData.posY[usrData.name])\
- \009\009\009local block = false\
- \009\009\009for _, bY in ipairs(mapData.blocksY) do\
- \009\009\009\009\009if oldX-1 == mapData.blocksX[_] and oldY == bY then\
- \009\009\009\009\009\009term.setCursorPos(27, 3)\
- \009\009\009\009\009\009term.setTextColor(colors.white)\
- \009\009\009\009\009\009term.write(\"BLOCK\")\
- \009\009\009\009\009\009block = true\
- \009\009\009\009\009\009break\
- \009\009\009\009\009else\
- \009\009\009\009\009\009block = false\
- \009\009\009\009\009end\
- \009\009\009end\
- \009\009\009if block ~= true then\
- \009\009\009\009term.setCursorPos(27, 3)\
- \009\009\009\009term.setTextColor(colors.white)\
- \009\009\009\009term.write(\"BLECK\")\
- \009\009\009\009playerData.posX[usrData.name] = playerData.posX[usrData.name]-1\
- \009\009\009\009uploadEntities()\
- \009\009\009\009redrawMap()\
- \009\009\009\009redrawEntitites()\
- \009\009\009end\009\
- \009\009\009sleep(lagfaktor)\
- \009\009elseif key == keys.down then\
- \009\009\009oldY = tonumber(playerData.posY[usrData.name])\
- \009\009\009oldX = tonumber(playerData.posX[usrData.name])\
- \009\009\009local block = false\
- \009\009\009for _, bY in ipairs(mapData.blocksY) do\
- \009\009\009\009\009if oldY+1 == bY and oldX == mapData.blocksX[_] then\
- \009\009\009\009\009\009term.setCursorPos(27, 3)\
- \009\009\009\009\009\009term.setTextColor(colors.white)\
- \009\009\009\009\009\009term.write(\"BLOCK\")\
- \009\009\009\009\009\009block = true\
- \009\009\009\009\009\009break\
- \009\009\009\009\009else\
- \009\009\009\009\009\009\
- \009\009\009\009\009\009block = false\
- \009\009\009\009\009end\
- \009\009\009end\
- \009\009\009if block ~= true then\
- \009\009\009\009term.setCursorPos(27, 3)\
- \009\009\009\009term.setTextColor(colors.white)\
- \009\009\009\009term.write(\"BLECK\")\
- \
- \009\009\009\009playerData.posY[usrData.name] = playerData.posY[usrData.name]+1\
- \009\009\009\009uploadEntities()\
- \009\009\009\009redrawMap()\
- \009\009\009\009redrawEntitites()\
- \009\009\009end\
- \009\009\009sleep(lagfaktor)\
- \009\009elseif key == keys.up then\
- \009\009\009oldY = tonumber(playerData.posY[usrData.name])\
- \009\009\009oldX = tonumber(playerData.posX[usrData.name])\
- \009\009\009local block = false\
- \009\009\009for _, bY in ipairs(mapData.blocksY) do\
- \009\009\009\009\009if oldY-1 == bY and oldX == mapData.blocksX[_] then\
- \009\009\009\009\009\009term.setCursorPos(27, 3)\
- \009\009\009\009\009\009term.setTextColor(colors.white)\
- \009\009\009\009\009\009term.write(\"BLOCK\")\
- \009\009\009\009\009\009block = true\
- \009\009\009\009\009\009break\
- \009\009\009\009\009else\
- \009\009\009\009\009\009\
- \009\009\009\009\009\009block = false\
- \009\009\009\009\009end\
- \009\009\009end\
- \009\009\009if block ~= true then\
- \009\009\009\009term.setCursorPos(27, 3)\
- \009\009\009\009term.setTextColor(colors.white)\
- \009\009\009\009term.write(\"BLECK\")\
- \
- \009\009\009\009playerData.posY[usrData.name] = playerData.posY[usrData.name]-1\
- \009\009\009\009uploadEntities()\
- \009\009\009\009redrawMap()\
- \009\009\009\009redrawEntitites()\
- \009\009\009end\
- \009\009\009sleep(lagfaktor)\
- \009\009elseif key == keys.enter then\
- \009\009\009oldY = tonumber(playerData.posY[usrData.name])\
- \009\009\009oldX = tonumber(playerData.posX[usrData.name])\
- \009\009\009local block = true\
- \009\009\009local ladderdest = \"house1\"\
- \009\009\009for _, bY in ipairs(mapData.laddersY) do\
- \009\009\009\009if oldY == bY+1 and oldX == mapData.laddersX[_] or oldY == bY-1 and oldX == mapData.laddersX[_] or oldY == bY and oldX == mapData.laddersX[_]-1 or oldY == bY and oldX == mapData.laddersX[_]+1 then\
- \009\009\009\009\009term.setCursorPos(27,3)\
- \009\009\009\009\009term.setTextColor(colors.white)\
- \009\009\009\009\009term.write(\"BLACK\")\
- \009\009\009\009\009block = false\
- \009\009\009\009\009ladderdest = mapData.ladderDestination[_]\
- \009\009\009\009\009\009break\
- \009\009\009\009else\
- \
- \009\009\009\009\009block = true\
- \009\009\009\009end\
- \009\009\009end\
- \009\009\009if block ~= true then\
- \009\009\009\009playerData.worlds[usrData.name] = ladderdest\
- \009\009\009\009uploadEntities()\
- \009\009\009\009--drawGame()\
- \009\009\009\009getworld()\
- \009\009\009\009--[[redrawMap()\
- \009\009\009\009redrawEntitites()]]\
- \009\009\009end\
- \009\009\009sleep(lagfaktor)\
- \009\009end\
- \
- \009end\
- end\
- \
- function getChat()\
- \009while true do\
- \
- \009\009local id, msg, msg2 = rednet.receive(tostring(servId), 0.1)\
- \009\009if tonumber(msg2) == servId then\
- \009\009\009chatWindow.scroll(-1)\
- \009\009\009chatWindow.setCursorPos(1,1)\
- \009\009\009term.redirect(chatWindow)\
- \009\009\009term.write(msg)\
- \009\009\009term.redirect(oldTerm)\
- \009\009end\
- \009end\
- end\
- \
- \
- function sendMessage()\
- \009--while true do\
- \009\009--local _, k = os.pullEvent(\"key\")\
- \009\009--if k == keys.t then\
- \009\009\009--reading = true\
- \009\009\009term.redirect(chatBox)\
- \009\009\009term.setBackgroundColor(colors.lightGray)\
- \009\009\009term.setTextColor(colors.lime)\
- \009\009\009term.clear()\
- \009\009\009term.setCursorPos(1,1)\
- \009\009\009term.write(\"> \")\
- \009\009\009term.setCursorBlink(true)\
- \009\009\009local e = limitRead(15)\
- \009\009\009term.setCursorBlink(false)\
- \009\009\009--reading = false\
- \009\009\009term.redirect(oldTerm)\
- \009\009\009\
- \009\009\009chatWindow.scroll(-1)\
- \009\009\009chatWindow.setCursorPos(1,1)\
- \009\009\009chatWindow.setBackgroundColor(colors.gray)\
- \009\009\009chatWindow.setTextColor(colors.lime)\
- \009\009\009chatWindow.write(usrData.name..\": \"..e)\
- \009\009\009\
- \009\009\009rednet.broadcast(usrData.name..\": \"..e, tostring(servId))\
- \009\009\009\
- \009\009--end\
- \009--end\
- end\
- \
- function drawGame()\
- \009clear(colors.black, colors.white)\
- \009game = true\
- \009a = sendspawn()\
- \009if a == false then\
- \009\009print(\"Error: Unknown.\")\
- \009\009game= false\
- \009end\
- \009\
- \009chatWindow = window.create(oldTerm, 1, 11, 25, 8)\
- \009chatWindow.setBackgroundColor(colors.gray)\
- \009chatWindow.setTextColor(colors.lime)\
- \009chatWindow.clear()\
- \009chatBox = window.create(oldTerm, 1, 19, 25, 1)\
- \009chatBox.setBackgroundColor(colors.lightGray)\
- \009chatBox.setTextColor(colors.lime)\
- \009chatBox.clear()\
- \009mapWindow = window.create(oldTerm, 1, 1, 25, 9)\
- \009mapWindow.setBackgroundColor(colors.black)\
- \009mapWindow.setTextColor(colors.white)\
- \009mapWindow.clear()\
- \009getworld()\
- \009local c1 = coroutine.create(getEntities)\
- \009local c2 = coroutine.create(move)\
- \009local c3 = coroutine.create(getChat)\
- \009local c5 = coroutine.create(sendMessage)\
- \
- \009local evt = {}\
- \009while true do\
- \009\009\
- \009\009if evt[2] ~= keys.t or evt[2] ~= keys.delete then\
- \009\009\009coroutine.resume(c1, unpack(evt))\
- \009\009\009coroutine.resume(c2, unpack(evt))\
- \009\009\009coroutine.resume(c3, unpack(evt))\
- \009\009end\
- \009\009--coroutine.resume(c5, unpack(evt))\
- \009\009evt = {os.pullEvent()}\
- \009\009if evt[1] == \"key\" and evt[2] == keys.delete then\
- \009\009\009clear(colors.black, colors.white)\
- \009\009\009break\
- \009\009elseif evt[1] == \"key\" and evt[2] == keys.t then\
- \009\009\009sendMessage()\
- \009\009\009evt = {}\
- \009\009\009c1 = nil\
- \009\009\009c2 = nil\
- \009\009\009c3 = nil\
- \009\009\009c1 = coroutine.create(getEntities)\
- \009\009\009c2 = coroutine.create(move)\
- \009\009\009c3 = coroutine.create(getChat)\
- \009\009\009coroutine.resume(c1, unpack(evt))\
- \009\009\009coroutine.resume(c2, unpack(evt))\
- \009\009\009coroutine.resume(c3, unpack(evt))\
- \009\009end\
- \009end\
- end\
- \
- --Code\
- \
- \
- local args = {...}\
- \
- if #args == 4 then\
- \009root = args[3]\
- \009servId = tonumber(args[4])\
- \009os.loadAPI(root..\"/API/sha\")\
- \009usrData.name = args[1]\
- \009usrData.encpw = args[2]\
- \009--do stuff\
- else\
- \009clear(colors.black, colors.white)\
- \009print(\"Please execute the launcher...\")\
- end\
- oldTerm = term.native()\
- drawMainMenu()",
- "",
- "--[[\
- Map maker for my MMORPG\
- Intended to be used by gameserver-owners!\
- ]]\
- \
- --Variablen\
- \
- objects = {\
- \009[\"door\"] = true,\
- \009[\"ladder\"] = true,\
- \009[\"wall\"] = true,\
- \009[\"remove\"] = true\
- }\
- \
- mapData = {\
- \009blocksX = {\
- \
- \009},\
- \009blocksY = {\
- \
- \009},\
- \009laddersX = {\
- \
- \009},\
- \009laddersY = {\
- \
- \009},\
- \009ladderDestination = {\
- \
- \009},\
- \009doorsX = {\
- \
- \009},\
- \009doorsY = {\
- \
- \009},\
- \009spawnX = 1,\
- \009spawnY = 1,\
- }\
- \
- selectedObj = \"\"\
- \
- --Funktionen\
- \
- function limitRead(nLimit, replaceChar)\
- term.setCursorBlink(true)\
- local cX, cY = term.getCursorPos()\
- local rString = \"\"\
- if replaceChar == \"\" then replaceChar = nil end\
- repeat\
- local event, p1 = os.pullEventRaw()\
- if event == \"char\" then\
- -- Character event\
- if #rString + 1 <= nLimit then\
- rString = rString .. p1\
- write(replaceChar or p1)\
- end\
- elseif event == \"key\" and p1 == keys.backspace and #rString >= 1 then\
- -- Backspace\
- rString = string.sub(rString, 1, #rString-1)\
- xPos, yPos = term.getCursorPos()\
- term.setCursorPos(xPos-1, yPos)\
- write(\" \")\
- term.setCursorPos(xPos-1, yPos)\
- end\
- until event == \"key\" and p1 == keys.enter\
- term.setCursorBlink(false)\
- --print() -- Skip to the next line after clicking enter.\
- return rString\
- end\
- \
- function clear(bg, fg)\
- \009term.setCursorPos(1,1)\
- \009term.setBackgroundColor(bg)\
- \009term.setTextColor(colors.white)\
- \009term.clear()\
- end\
- \
- function editor()\
- \009clear(colors.black, colors.white)\
- \009editing = true\
- \009oldTerm = term.native()\
- \009paintutils.drawImage(_layout, 1, 1)\
- \009mapWindow = window.create(oldTerm, 1, 1, 25, 9)\
- \009term.redirect(mapWindow)\
- \009paintutils.drawImage(_map, 1, 1)\
- \009maxX = 25\
- \009maxY = 9\
- \009term.redirect(oldTerm)\
- \009searchBox = window.create(oldTerm, 2, 12, 23, 1)\
- \009searchBox.setBackgroundColor(colors.gray)\
- \009searchBox.setTextColor(colors.lime)\
- \009searchBox.clear()\
- \009searchBox.write(\"Enter function...\")\
- \009while true do\
- \009\009local event, button, x, y = os.pullEventRaw()\
- \
- \009\009if event == \"mouse_click\" and button == 1 and x >= 2 and x <= 24 and y == 12 then\
- \009\009\009term.redirect(searchBox)\
- \009\009\009term.setCursorPos(1,1)\
- \009\009\009term.clear()\
- \009\009\009local eingabe = limitRead(23)\
- \009\009\009if #eingabe > 0 then\
- \009\009\009\009for key, a in pairs(objects) do\
- \009\009\009\009\009if eingabe == key then\
- \009\009\009\009\009\009selectedObj = eingabe\
- \009\009\009\009\009\009term.setCursorPos(1,1)\
- \009\009\009\009\009\009term.clear()\
- \009\009\009\009\009\009term.write(selectedObj)\
- \009\009\009\009\009\009break\
- \009\009\009\009\009else\
- \009\009\009\009\009\009term.setCursorPos(1,1)\
- \009\009\009\009\009\009term.clear()\
- \009\009\009\009\009\009term.write(\"Object not found.\")\
- \009\009\009\009\009end\
- \009\009\009\009end\
- \009\009\009end\
- \009\009\009term.redirect(oldTerm)\
- \009\009elseif event == \"mouse_click\" and button == 1 and x >= 1 and x <= 25 and y >= 1 and y <= 9 then\
- \009\009\009if selectedObj ~= \"\" then\
- \009\009\009\009if selectedObj == \"wall\" then\
- \009\009\009\009\009term.setCursorPos(x, y)\
- \009\009\009\009\009term.setBackgroundColor(colors.brown)\
- \009\009\009\009\009term.setTextColor(colors.white)\
- \009\009\009\009\009term.write(\"W\")\
- \009\009\009\009\009table.insert(mapData.blocksX, x)\
- \009\009\009\009\009table.insert(mapData.blocksY, y)\
- \009\009\009\009\009redrawBlocks()\
- \009\009\009\009elseif selectedObj == \"remove\" then\
- \009\009\009\009\009for _, a in ipairs(mapData.blocksX) do\
- \009\009\009\009\009\009if a == x and y == mapData.blocksY[_] then\
- \009\009\009\009\009\009\009table.remove(mapData.blocksX, _)\
- \009\009\009\009\009\009\009table.remove(mapData.blocksY, _)\
- \009\009\009\009\009\009\009paintutils.drawImage(_map, 1, 1)\
- \009\009\009\009\009\009\009redrawBlocks()\
- \009\009\009\009\009\009end\
- \009\009\009\009\009end\
- \009\009\009\009\009for _, a in ipairs(mapData.laddersX) do\
- \009\009\009\009\009\009if a == x and y == mapData.laddersY[_] then\
- \009\009\009\009\009\009\009table.remove(mapData.laddersX, _)\
- \009\009\009\009\009\009\009table.remove(mapData.laddersY, _)\
- \009\009\009\009\009\009\009paintutils.drawImage(_map, 1, 1)\
- \009\009\009\009\009\009\009redrawBlocks()\
- \009\009\009\009\009\009end\
- \009\009\009\009\009end\
- \009\009\009\009elseif selectedObj == \"ladder\" then\
- \009\009\009\009\009term.setCursorPos(x, y)\
- \009\009\009\009\009term.setBackgroundColor(colors.brown)\
- \009\009\009\009\009term.setTextColor(colors.white)\
- \009\009\009\009\009term.write(\"H\")\
- \009\009\009\009\009term.redirect(searchBox)\
- \009\009\009\009\009term.setCursorPos(1,1)\
- \009\009\009\009\009term.clear()\
- \009\009\009\009\009term.write(\"Please write destination\")\
- \009\009\009\009\009sleep(2)\
- \009\009\009\009\009term.setCursorPos(1,1)\
- \009\009\009\009\009term.clear()\
- \009\009\009\009\009repeat\
- \009\009\009\009\009\009local eingabe = limitRead(23)\
- \009\009\009\009\009\009term.setCursorPos(1,1)\
- \009\009\009\009\009\009term.clear()\
- \009\009\009\009\009until #eingabe > 0\
- \009\009\009\009\009term.redirect(oldTerm)\
- \009\009\009\009\009table.insert(mapData.laddersX, x)\
- \009\009\009\009\009table.insert(mapData.laddersY, y)\
- \009\009\009\009\009table.insert(mapData.ladderDestination, eingabe)\
- \009\009\009\009\009redrawBlocks()\
- \009\009\009\009end\
- \009\009\009end\
- \009\009elseif event == \"key\" and button == keys.delete then\
- \009\009\009local file = fs.open(fldr..\"data.lvlDat\",\"w\")\
- \009\009\009file.write(textutils.serialize(mapData))\
- \009\009\009file.close()\
- \
- \009\009\009break\
- \009\009end\
- \009end\
- end\
- \
- function redrawBlocks()\
- \009for _, x in ipairs(mapData.blocksX) do\
- \009\009term.setCursorPos(x, mapData.blocksY[_])\
- \009\009term.setBackgroundColor(colors.brown)\
- \009\009term.setTextColor(colors.white)\
- \009\009term.write(\"W\")\
- \009end\
- \009for _, x in ipairs(mapData.laddersX) do\
- \009\009term.setCursorPos(x, mapData.laddersY[_])\
- \009\009term.setBackgroundColor(colors.black)\
- \009\009term.setTextColor(colors.white)\
- \009\009term.write(\"L\")\
- \009end\
- end\
- \
- \
- --Code\
- \
- local args = {...}\
- \
- if #args ~= 2 then\
- \009print(\"Usage: <thisfile> <pathToMapPicture> <editorLayoutDirectory>\")\
- else\
- \009if fs.exists(args[1]) then\
- \009\009fldr = args[1]\
- \009\009_map = paintutils.loadImage(args[1]..\"data.lvl\")\
- \009\009_layout = paintutils.loadImage(args[2])\
- \009\009editor()\
- \009end\
- \009--do stuff\
- end",
- "bbbbb 7 \
- bbbbbbbbbbbbbbbbbbbbbbbbb7 \
- 7 \
- 7 \
- 7 \
- 7 \
- 7 \
- 7 \
- 7 \
- 777777777777777777777777777777777777777777777777777\
- 7 \
- 7 \
- 7 \
- 7 \
- 7 \
- 7 \
- 7 \
- 7 \
- 7 ",
- "--[[\
- NPaintPro\
- By NitrogenFingers\
- ]]--\
- \
- --The screen size\
- local w,h = term.getSize()\
- --Whether or not the program is currently waiting on user input\
- local inMenu = false\
- --Whether or not a drop down menu is active\
- local inDropDown = false\
- --Whether or not animation tools are enabled (use -a to turn them on)\
- local animated = false\
- --Whether or not the text tools are enabled (use -t to turn them on)\
- local textual = false\
- --Whether or not \"blueprint\" display mode is on\
- local blueprint = false\
- --Whether or not the \"layer\" display is on\
- local layerDisplay = false\
- --Whether or not the interface is presently hidden\
- local interfaceHidden = false\
- --Whether or not the \"direction\" display is on\
- local printDirection = false\
- --The tool/mode npaintpro is currently in. Default is \"paint\"\
- --For a list of modes, check out the help file\
- local state = \"paint\"\
- --Whether or not the program is presently running\
- local isRunning = true\
- --The rednet address of the 3D printer, if one has been attached\
- local printer = nil\
- \
- --The list of every frame, containing every image in the picture/animation\
- --Note: nfp files always have the picture at frame 1\
- local frames = { }\
- --How many frames are currently in the given animation.\
- local frameCount = 1\
- --The Colour Picker column\
- local column = {}\
- --The offset of visible colours in the picker column, if the screen cannot fit all 16\
- local columnoffset = 0\
- --The currently selected left and right colours\
- local lSel,rSel = colours.white,nil\
- --The amount of scrolling on the X and Y axis\
- local sx,sy = 0,0\
- --The alpha channel colour\
- --Change this to change default canvas colour\
- local alphaC = colours.black\
- --The currently selected frame. Default is 1\
- local sFrame = 1\
- --The contents of the image buffer- contains contents, width and height\
- local buffer = nil\
- --The position, width and height of the selection rectangle\
- local selectrect = nil\
- \
- --Whether or not text tools are enabled for this document\
- local textEnabled = false\
- --The X and Y positions of the text cursor\
- local textCurX, textCurY = 1,1\
- \
- --The currently calculated required materials\
- local requiredMaterials = {}\
- --Whether or not required materials are being displayed in the pallette\
- local requirementsDisplayed = false\
- --A list of the rednet ID's all in-range printers located\
- local printerList = { }\
- --A list of the names of all in-range printers located. Same as the printerList in reference\
- local printerNames = { }\
- --The selected printer\
- local selectedPrinter = 1\
- --The X,Y,Z and facing of the printer\
- local px,py,pz,pfx,pfz = 0,0,0,0,0\
- --The form of layering used\
- local layering = \"up\"\
- \
- --The animation state of the selection rectangle and image buffer\
- local rectblink = 0\
- --The ID for the timer\
- local recttimer = nil\
- --The radius of the brush tool\
- local brushsize = 3\
- --Whether or not \"record\" mode is activated (animation mode only)\
- local record = false\
- --The time between each frame when in play mode (animation mode only)\
- local animtime = 0.3\
- \
- --The current \"cursor position\" in text mode\
- local cursorTexX,cursorTexY = 1,1\
- \
- --A list of hexidecimal conversions from numbers to hex digits\
- local hexnums = { [10] = \"a\", [11] = \"b\", [12] = \"c\", [13] = \"d\", [14] = \"e\" , [15] = \"f\" }\
- --The NPaintPro logo (divine, isn't it?)\
- local logo = {\
- \"fcc 3 339\";\
- \" fcc 9333 33\";\
- \" fcc 933 333 33\";\
- \" fcc 933 33 33\";\
- \" fcc 933 33 33\";\
- \" c88 333 93333\";\
- \" 888 333 9333\";\
- \" 333 3 333 939\";\
- }\
- --The Layer Up and Layer Forward printing icons\
- local layerUpIcon = {\
- \"0000000\";\
- \"0088880\";\
- \"0888870\";\
- \"07777f0\";\
- \"0ffff00\";\
- \"0000000\";\
- }\
- local layerForwardIcon = {\
- \"0000000\";\
- \"000fff0\";\
- \"00777f0\";\
- \"0888700\";\
- \"0888000\";\
- \"0000000\";\
- }\
- --The available menu options in the ctrl menu\
- local mChoices = {\"Save\",\"Exit\"}\
- --The available modes from the dropdown menu- tables indicate submenus (include a name!)\
- local ddModes = { { \"paint\", \"brush\", \"pippette\", \"flood\", \"move\", \"clear\", \"select\", name = \"painting\" }, { \"alpha to left\", \"alpha to right\", \"hide interface\", name = \"display\" }, \"help\", { \"print\", \"save\", \"exit\", name = \"file\" }, name = \"menu\" }\
- --The available modes from the selection right-click menu\
- local srModes = { \"cut\", \"copy\", \"paste\", \"clear\", \"hide\", name = \"selection\" }\
- --The list of available help topics for each mode 127\
- local helpTopics = {\
- [1] = {\
- name = \"Paint Mode\",\
- key = nil,\
- animonly = false,\
- textonly = false,\
- message = \"The default mode for NPaintPro, for painting pixels.\"\
- ..\" Controls here that are not overridden will apply for all other modes. Leaving a mode by selecting that mode \"\
- ..\" again will always send the user back to paint mode.\",\
- controls = {\
- { \"Arrow keys\", \"Scroll the canvas\" },\
- { \"Left Click\", \"Paint/select left colour\" },\
- { \"Right Click\", \"Paint/select right colour\" },\
- { \"Z Key\", \"Clear image on screen\" },\
- { \"Tab Key\", \"Hide selection rectangle if visible\" },\
- { \"Q Key\", \"Set alpha mask to left colour\" },\
- { \"W Key\", \"Set alpha mask to right colour\" },\
- { \"Number Keys\", \"Swich between frames 1-9\" },\
- { \"</> keys\", \"Move to the next/last frame\" },\
- { \"R Key\", \"Removes every frame after the current frame\"}\
- }\
- },\
- [2] = {\
- name = \"Brush Mode\",\
- key = \"b\",\
- animonly = false,\
- textonly = false,\
- message = \"Brush mode allows painting a circular area of variable diameter rather than a single pixel, working in \"..\
- \"the exact same way as paint mode in all other regards.\",\
- controls = {\
- { \"Left Click\", \"Paints a brush blob with the left colour\" },\
- { \"Right Click\", \"Paints a brush blob with the right colour\" },\
- { \"Number Keys\", \"Changes the radius of the brush blob from 2-9\" }\
- }\
- },\
- [3] = {\
- name = \"Pippette Mode\",\
- key = \"p\",\
- animonly = false,\
- textonly = false,\
- message = \"Pippette mode allows the user to click the canvas and set the colour clicked to the left or right \"..\
- \"selected colour, for later painting.\",\
- controls = {\
- { \"Left Click\", \"Sets clicked colour to the left selected colour\" },\
- { \"Right Click\", \"Sets clicked colour to the right selected colour\" }\
- }\
- },\
- [4] = {\
- name = \"Move Mode\",\
- key = \"m\",\
- animonly = false,\
- textonly = false,\
- message = \"Mode mode allows the moving of the entire image on the screen. This is especially useful for justifying\"..\
- \" the image to the top-left for animations or game assets.\",\
- controls = {\
- { \"Left/Right Click\", \"Moves top-left corner of image to selected square\" },\
- { \"Arrow keys\", \"Moves image one pixel in any direction\" }\
- }\
- },\
- [5] = {\
- name = \"Flood Mode\",\
- key = \"f\",\
- animonly = false,\
- textonly = false,\
- message = \"Flood mode allows the changing of an area of a given colour to that of the selected colour. \"..\
- \"The tool uses a flood4 algorithm and will not fill diagonally. Transparency cannot be flood filled.\",\
- controls = {\
- { \"Left Click\", \"Flood fills selected area to left colour\" },\
- { \"Right Click\", \"Flood fills selected area to right colour\" }\
- }\
- },\
- [6] = {\
- name = \"Select Mode\",\
- key = \"s\",\
- animonly = false,\
- textonly = false,\
- message = \"Select mode allows the creation and use of the selection rectangle, to highlight specific areas on \"..\
- \"the screen and perform operations on the selected area of the image. The selection rectangle can contain an \"..\
- \"image on the clipboard- if it does, the image will flash inside the rectangle, and the rectangle edges will \"..\
- \"be light grey instead of dark grey.\",\
- controls = {\
- { \"C Key\", \"Copy: Moves selection into the clipboard\" },\
- { \"X Key\", \"Cut: Clears canvas under the rectangle, and moves it into the clipboard\" },\
- { \"V Key\", \"Paste: Copys clipboard to the canvas\" },\
- { \"Z Key\", \"Clears clipboard\" },\
- { \"Left Click\", \"Moves top-left corner of rectangle to selected pixel\" },\
- { \"Right Click\", \"Opens selection menu\" },\
- { \"Arrow Keys\", \"Moves rectangle one pixel in any direction\" }\
- }\
- },\
- [7] = {\
- name = \"Corner Select Mode\",\
- key = nil,\
- animonly = false,\
- textonly = false,\
- message = \"If a selection rectangle isn't visible, this mode is selected automatically. It allows the \"..\
- \"defining of the corners of the rectangle- one the top-left and bottom-right corners have been defined, \"..\
- \"NPaintPro switches to selection mode. Note rectangle must be at least 2 pixels wide and high.\",\
- controls = {\
- { \"Left/Right Click\", \"Defines a corner of the selection rectangle\" }\
- }\
- },\
- [8] = {\
- name = \"Play Mode\",\
- key = \"space\",\
- animonly = true,\
- textonly = false,\
- message = \"Play mode will loop through each frame in your animation at a constant rate. Editing tools are \"..\
- \"locked in this mode, and the coordinate display will turn green to indicate it is on.\",\
- controls = {\
- { \"</> Keys\", \"Increases/Decreases speed of the animation\" },\
- { \"Space Bar\", \"Returns to paint mode\" }\
- }\
- },\
- [9] = {\
- name = \"Record Mode\",\
- key = \"\\\\\",\
- animonly = true,\
- textonly = false,\
- message = \"Record mode is not a true mode, but influences how other modes work. Changes made that modify the \"..\
- \"canvas in record mode will affect ALL frames in the animation. The coordinates will turn red to indicate that \"..\
- \"record mode is on.\",\
- controls = {\
- { \"\", \"Affects:\" },\
- { \"- Paint Mode\", \"\" },\
- { \"- Brush Mode\", \"\" },\
- { \"- Cut and Paste in Select Mode\", \"\"},\
- { \"- Move Mode\", \"\"}\
- }\
- },\
- \009\009[10] = {\
- \009\009\009\009name = \"Hide Interface\",\
- \009\009\009\009key = \"~\",\
- \009\009\009\009animonly = false,\
- \009\009\009\009textonly = false,\
- \009\009\009\009message = \"Hides the sidebar and colour picker so only the image is visible.\"..\
- \009\009\009\009\" The program can be started with the interface hidden using the -d command line option.\"..\
- \009\009\009\009\" When hidden, if a file is animated it will automatically go to play mode.\\n\"..\
- \009\009\009\009\"Note that all other input is locked until the display is revealed again in this\"..\
- \009\009\009\009\" mode.\",\
- \009\009\009\009controls = {\
- { \"</> Keys\", \"Increases/Decreases speed of the animation\" },\
- \009\009\009\009\009{ \"~ Key\", \"Shows interface\"}\
- \009\009\009\009}\
- \009\009},\
- [11] = {\
- name = \"Help Mode\",\
- key = \"h\",\
- animonly = false,\
- textonly = false,\
- message = \"Displays this help screen. Clicking on options will display help on that topic. Clicking out of the screen\"..\
- \" will leave this mode.\",\
- controls = {\
- { \"Left/Right Click\", \"Displays a topic/Leaves the mode\" }\
- }\
- },\
- [12] = {\
- name = \"File Mode\",\
- key = nil,\
- animonly = false,\
- textonly = false,\
- message = \"Clicking on the mode display at the bottom of the screen will open the options menu. Here you can\"..\
- \" activate all of the modes in the program with a simple mouse click. Pressing left control will open up the\"..\
- \" file menu automatically.\",\
- controls = {\
- { \"leftCtrl\", \"Opens the file menu\" },\
- { \"leftAlt\", \"Opens the paint menu\" }\
- }\
- },\
- [13] = {\
- name = \"Text Mode\",\
- key = \"t\",\
- animonly = false,\
- textonly = true,\
- message = \"In this mode, the user is able to type letters onto the document for display. The left colour \"..\
- \"pallette value determines what colour the text will be, and the right determines what colour the background \"..\
- \"will be (set either to nil to keep the same colours as already there).\",\
- controls = {\
- { \"Backspace\", \"Deletes the character on the previous line\" },\
- { \"Arrow Keys\", \"Moves the cursor in any direction\" },\
- { \"Left Click\", \"Moves the cursor to beneath the mouse cursor\" }\
- }\
- },\
- [14] = {\
- name = \"Textpaint Mode\",\
- key = \"y\",\
- animonly = false,\
- textonly = true,\
- message = \"Allows the user to paint any text on screen to the desired colour with the mouse. If affects the text colour\"..\
- \" values rather than the background values, but operates identically to paint mode in all other regards.\",\
- controls = {\
- { \"Left Click\", \"Paints the text with the left colour\" },\
- { \"Right Click\", \"Paints the text with the right colour\" }\
- }\
- },\
- [15] = {\
- name = \"About NPaintPro\",\
- keys = nil,\
- animonly = false,\
- textonly = false,\
- message = \"NPaintPro: The feature-bloated paint program for ComputerCraft by Nitrogen Fingers.\",\
- controls = {\
- { \"Testers:\", \" \"},\
- { \" \", \"Faubiguy\"},\
- { \" \", \"TheOriginalBIT\"}\
- }\
- }\
- }\
- --The \"bounds\" of the image- the first/last point on both axes where a pixel appears\
- local toplim,botlim,leflim,riglim = nil,nil,nil,nil\
- --The selected path\
- local sPath = nil\
- \
- \
- --Screen Size Parameters- decided dynamically further down the program\
- --Whether or not the help screen is available\
- local helpAvailable = true\
- --Whether or not the main menu is available\
- local mainAvailable = true\
- --Whether or not selection box dropdowns are available\
- local boxdropAvailable = true\
- --Whether or not a manual file descriptor option is available (part of the title)\
- local filemakerAvailable = true\
- \
- --[[ \
- Section: Helpers \
- ]]--\
- \
- --[[Converts a colour parameter into a single-digit hex coordinate for the colour\
- Params: colour:int = The colour to be converted\
- Returns:string A string conversion of the colour\
- ]]--\
- local function getHexOf(colour)\
- if not colour or not tonumber(colour) then\
- return \" \"\
- end\
- local value = math.log(colour)/math.log(2)\
- if value > 9 then\
- value = hexnums[value]\
- end\
- return value\
- end\
- \
- --[[Converts a hex digit into a colour value\
- Params: hex:?string = the hex digit to be converted\
- Returns:string A colour value corresponding to the hex, or nil if the character is invalid\
- ]]--\
- local function getColourOf(hex)\
- local value = tonumber(hex, 16)\
- if not value then return nil end\
- value = math.pow(2,value)\
- return value\
- end\
- \
- --[[Finds the largest width and height of the text in a given menu. Should conform to the format\
- \009of all standard menus (number indexed values and a 'name' field).\
- \009This is done recursively. It's just easier that way.\
- \009Params: menu:table = the table being tested for the max width and height\
- \009Returns:number,number = the max width and height of the text or names of any menu or submenu.\
- ]]--\
- local function findMaxWH(menu)\
- \009local wmax,hmax = #menu.name, #menu\
- \009for _,entry in pairs(menu) do\
- \009\009if type(entry) == \"table\" then\
- \009\009\009local nw,nh = findMaxWH(entry)\
- \009\009\009wmax = math.max(wmax,nw)\
- \009\009\009hmax = math.max(hmax,nh)\
- \009\009else\
- \009\009\009wmax = math.max(wmax,#entry)\
- \009\009end\
- \009end\
- \009return wmax,hmax\
- end\
- \
- --[[Determines what services are available depending on the size of the screen. Certain features\
- \009may be disabled with screen real estate does not allow for it.\
- \009Params: none\
- \009Returns:nil\
- ]]--\
- local function determineAvailableServices()\
- \009--Help files were designed to fit a 'standard' CC screen, of 51 x 19. The height of the screen\
- \009--needs to match the number of available options plus white space, but for consistency with\
- \009--the files themselves, a natural size of 51 is required for the screen width as well.\
- \009if w < 51 or h < #helpTopics+3 then helpAvailable = false end\
- \009if not helpAvailable then table.remove(ddModes,3) end\
- \009--These hard-coded values mirror the drawLogo values, with extra consideration for the \
- \009--additional menu options\
- \009if h < 14 or w < 24 then filemakerAvailable = false end\
- \009\
- \009--Menus can't cover the picker and need 2 spaces for branches. 4 whitespace on X total.\
- \009--Menus need a title and can't eclipse the footer. 2 whitespace on Y total.\
- \009local wmin,hmin = findMaxWH(ddModes)\
- \009if w < wmin+4 or h < hmin+2 then mainAvailable = false end\
- \009wmin,hmin = findMaxWH(srModes)\
- \009if w < wmin+4 or h < hmin+2 then boxdropAvailable = false end\
- end\
- \
- --[[Finds the biggest and smallest bounds of the image- the outside points beyond which pixels do not appear\
- These values are assigned to the \"lim\" parameters for access by other methods\
- Params: forAllFrames:bool = True if all frames should be used to find bounds, otherwise false or nil\
- Returns:nil\
- ]]--\
- local function updateImageLims(forAllFrames)\
- local f,l = sFrame,sFrame\
- if forAllFrames == true then f,l = 1,framecount end\
- \
- toplim,botlim,leflim,riglim = nil,nil,nil,nil\
- for locf = f,l do\
- for y,_ in pairs(frames[locf]) do\
- if type(y) == \"number\" then\
- for x,_ in pairs(frames[locf][y]) do\
- if frames[locf][y][x] ~= nil then\
- if leflim == nil or x < leflim then leflim = x end\
- if toplim == nil or y < toplim then toplim = y end\
- if riglim == nil or x > riglim then riglim = x end\
- if botlim == nil or y > botlim then botlim = y end\
- end\
- end\
- end\
- end\
- end\
- \
- --There is just... no easier way to do this. It's horrible, but necessary\
- if textEnabled then\
- for locf = f,l do\
- for y,_ in pairs(frames[locf].text) do\
- for x,_ in pairs(frames[locf].text[y]) do\
- if frames[locf].text[y][x] ~= nil then\
- if leflim == nil or x < leflim then leflim = x end\
- if toplim == nil or y < toplim then toplim = y end\
- if riglim == nil or x > riglim then riglim = x end\
- if botlim == nil or y > botlim then botlim = y end\
- end\
- end\
- end\
- for y,_ in pairs(frames[locf].textcol) do\
- for x,_ in pairs(frames[locf].textcol[y]) do\
- if frames[locf].textcol[y][x] ~= nil then\
- if leflim == nil or x < leflim then leflim = x end\
- if toplim == nil or y < toplim then toplim = y end\
- if riglim == nil or x > riglim then riglim = x end\
- if botlim == nil or y > botlim then botlim = y end\
- end\
- end\
- end\
- end\
- end\
- end\
- \
- --[[Determines how much of each material is required for a print. Done each time printing is called.\
- Params: none\
- Returns:table A complete list of how much of each material is required.\
- ]]--\
- function calculateMaterials()\
- updateImageLims(animated)\
- requiredMaterials = {}\
- for i=1,16 do\
- requiredMaterials[i] = 0\
- end\
- \
- if not toplim then return end\
- \
- for i=1,#frames do\
- for y = toplim, botlim do\
- for x = leflim, riglim do\
- if type(frames[i][y][x]) == \"number\" then\
- requiredMaterials[math.log10(frames[i][y][x])/math.log10(2) + 1] =\
- requiredMaterials[math.log10(frames[i][y][x])/math.log10(2) + 1] + 1\
- end \
- end\
- end\
- end\
- end\
- \
- \
- --[[Updates the rectangle blink timer. Should be called anywhere events are captured, along with a timer capture.\
- Params: nil\
- Returns:nil\
- ]]--\
- local function updateTimer(id)\
- if id == recttimer then\
- recttimer = os.startTimer(0.5)\
- rectblink = (rectblink % 2) + 1\
- end\
- end\
- \
- --[[Constructs a message based on the state currently selected\
- Params: nil\
- Returns:string A message regarding the state of the application\
- ]]--\
- local function getStateMessage()\
- local msg = \" \"..string.upper(string.sub(state, 1, 1))..string.sub(state, 2, #state)..\" mode\"\
- if state == \"brush\" then msg = msg..\", size=\"..brushsize end\
- return msg\
- end\
- \
- --[[Calls the rednet_message event, but also looks for timer events to keep then\
- system timer ticking.\
- Params: timeout:number how long before the event times out\
- Returns:number the id of the sender\
- :number the message send\
- ]]--\
- local function rsTimeReceive(timeout)\
- local timerID\
- if timeout then timerID = os.startTimer(timeout) end\
- \
- local id,key,msg = nil,nil\
- while true do\
- id,key,msg = os.pullEvent()\
- \
- if id == \"timer\" then\
- if key == timerID then return\
- else updateTimer(key) end\
- end\
- if id == \"rednet_message\" then\
- return key,msg\
- end\
- end\
- end\
- \
- --[[Draws a picture, in paint table format on the screen\
- Params: image:table = the image to display\
- xinit:number = the x position of the top-left corner of the image\
- yinit:number = the y position of the top-left corner of the image\
- alpha:number = the color to display for the alpha channel. Default is white.\
- Returns:nil\
- ]]--\
- local function drawPictureTable(image, xinit, yinit, alpha)\
- if not alpha then alpha = 1 end\
- for y=1,#image do\
- for x=1,#image[y] do\
- term.setCursorPos(xinit + x-1, yinit + y-1)\
- local col = getColourOf(string.sub(image[y], x, x))\
- if not col then col = alpha end\
- term.setBackgroundColour(col)\
- term.write(\" \")\
- end\
- end\
- end\
- \
- --[[ \
- Section: Loading \
- ]]--\
- \
- --[[Loads a non-animted paint file into the program\
- Params: path:string = The path in which the file is located\
- Returns:nil\
- ]]--\
- local function loadNFP(path)\
- sFrame = 1\
- frames[sFrame] = { }\
- if fs.exists(path) then\
- local file = io.open(path, \"r\" )\
- local sLine = file:read()\
- local num = 1\
- while sLine do\
- table.insert(frames[sFrame], num, {})\
- for i=1,#sLine do\
- frames[sFrame][num][i] = getColourOf(string.sub(sLine,i,i))\
- end\
- num = num+1\
- sLine = file:read()\
- end\
- file:close()\
- end\
- end\
- \
- --[[Loads a text-paint file into the program\
- Params: path:string = The path in which the file is located\
- Returns:nil\
- ]]--\
- local function loadNFT(path)\
- sFrame = 1\
- frames[sFrame] = { }\
- frames[sFrame].text = { }\
- frames[sFrame].textcol = { }\
- \
- if fs.exists(path) then\
- local file = io.open(path, \"r\")\
- local sLine = file:read()\
- local num = 1\
- while sLine do\
- table.insert(frames[sFrame], num, {})\
- table.insert(frames[sFrame].text, num, {})\
- table.insert(frames[sFrame].textcol, num, {})\
- \
- --As we're no longer 1-1, we keep track of what index to write to\
- local writeIndex = 1\
- --Tells us if we've hit a 30 or 31 (BG and FG respectively)- next char specifies the curr colour\
- local bgNext, fgNext = false, false\
- --The current background and foreground colours\
- local currBG, currFG = nil,nil\
- term.setCursorPos(1,1)\
- for i=1,#sLine do\
- local nextChar = string.sub(sLine, i, i)\
- if nextChar:byte() == 30 then\
- bgNext = true\
- elseif nextChar:byte() == 31 then\
- fgNext = true\
- elseif bgNext then\
- currBG = getColourOf(nextChar)\
- bgNext = false\
- elseif fgNext then\
- currFG = getColourOf(nextChar)\
- fgNext = false\
- else\
- if nextChar ~= \" \" and currFG == nil then\
- currFG = colours.white\
- end\
- frames[sFrame][num][writeIndex] = currBG\
- frames[sFrame].textcol[num][writeIndex] = currFG\
- frames[sFrame].text[num][writeIndex] = nextChar\
- writeIndex = writeIndex + 1\
- end\
- end\
- num = num+1\
- sLine = file:read()\
- end\
- file:close()\
- end\
- end\
- \
- --[[Loads an animated paint file into the program\
- Params: path:string = The path in which the file is located\
- Returns:nil\
- ]]--\
- local function loadNFA(path)\
- frames[sFrame] = { }\
- if fs.exists(path) then\
- local file = io.open(path, \"r\" )\
- local sLine = file:read()\
- local num = 1\
- while sLine do\
- table.insert(frames[sFrame], num, {})\
- if sLine == \"~\" then\
- sFrame = sFrame + 1\
- frames[sFrame] = { }\
- num = 1\
- else\
- for i=1,#sLine do\
- frames[sFrame][num][i] = getColourOf(string.sub(sLine,i,i))\
- end\
- num = num+1\
- end\
- sLine = file:read()\
- end\
- file:close()\
- end\
- framecount = sFrame\
- sFrame = 1\
- end\
- \
- --[[Saves a non-animated paint file to the specified path\
- Params: path:string = The path to save the file to\
- Returns:nil\
- ]]--\
- local function saveNFP(path)\
- local sDir = string.sub(sPath, 1, #sPath - #fs.getName(sPath))\
- if not fs.exists(sDir) then\
- fs.makeDir(sDir)\
- end\
- \
- local file = io.open(path, \"w\")\
- updateImageLims(false)\
- if not toplim then\
- file:close()\
- return\
- end\
- for y=1,botlim do\
- local line = \"\"\
- if frames[sFrame][y] then\
- for x=1,riglim do\
- line = line..getHexOf(frames[sFrame][y][x])\
- end\
- end\
- file:write(line..\"\\n\")\
- end\
- file:close()\
- end\
- \
- --[[Saves a text-paint file to the specified path\
- Params: path:string = The path to save the file to\
- Returns:nil\
- ]]--\
- local function saveNFT(path)\
- local sDir = string.sub(sPath, 1, #sPath - #fs.getName(sPath))\
- if not fs.exists(sDir) then\
- fs.makeDir(sDir)\
- end\
- \
- local file = io.open(path, \"w\")\
- updateImageLims(false)\
- if not toplim then\
- file:close()\
- return\
- end\
- for y=1,botlim do\
- local line = \"\"\
- local currBG, currFG = nil,nil\
- for x=1,riglim do\
- if frames[sFrame][y] and frames[sFrame][y][x] ~= currBG then\
- line = line..string.char(30)..getHexOf(frames[sFrame][y][x])\
- currBG = frames[sFrame][y][x]\
- end\
- if frames[sFrame].textcol[y] and frames[sFrame].textcol[y][x] ~= currFG then\
- line = line..string.char(31)..getHexOf(frames[sFrame].textcol[y][x])\
- currFG = frames[sFrame].textcol[y][x]\
- end\
- if frames[sFrame].text[y] then\
- local char = frames[sFrame].text[y][x]\
- if not char then char = \" \" end\
- line = line..char\
- end\
- end\
- file:write(line..\"\\n\")\
- end\
- file:close()\
- end\
- \
- --[[Saves a animated paint file to the specified path\
- Params: path:string = The path to save the file to\
- Returns:nil\
- ]]--\
- local function saveNFA(path)\
- local sDir = string.sub(sPath, 1, #sPath - #fs.getName(sPath))\
- if not fs.exists(sDir) then\
- fs.makeDir(sDir)\
- end\
- \
- local file = io.open(path, \"w\")\
- updateImageLims(true)\
- if not toplim then\
- file:close()\
- return\
- end\
- for i=1,#frames do\
- for y=1,botlim do\
- local line = \"\"\
- if frames[i][y] then\
- for x=1,riglim do\
- line = line..getHexOf(frames[i][y][x])\
- end\
- end\
- file:write(line..\"\\n\")\
- end\
- if i < #frames then file:write(\"~\\n\") end\
- end\
- file:close()\
- end\
- \
- --[[Runs a special pre-program dialogue to determine the filename and filepath. Done if\
- \009there's room, and a file name hasn't been specified\
- \009Params: none\
- \009Returns:bool= true if file is created; false otherwise\
- ]]--\
- local function runFileMaker()\
- \009local newFName = \"\"\
- \009local fileType = 1\
- \009if animated then fileType = 2\
- \009elseif textEnabled then fileType = 3 end\
- \009\
- \009local tlx,tly = math.floor(w/2 - #logo[1]/2), math.floor(h/2 + #logo/2 + 1)\
- \
- \009--This is done on top of the logo, so it backpedals a bit.\
- \009term.setCursorPos(tlx, tly)\
- \009term.clearLine()\
- \009term.write(\"Name: \")\
- \009term.setCursorPos(tlx, tly + 1)\
- \009term.clearLine()\
- \009term.write(\"Filetype: Sprite\")\
- \009term.setCursorPos(tlx + 12, tly + 2)\
- \009term.write(\"Animation\")\
- \009term.setCursorPos(tlx + 12, tly + 3)\
- \009term.write(\"Text\")\
- \009\
- \009while true do\
- \009\009term.setCursorPos(tlx + 6, tly)\
- \009\009term.setBackgroundColour(colours.lightGrey)\
- \009\009term.setTextColour(colours.grey)\
- \009\009term.write(newFName..string.rep(\" \", 15-#newFName))\
- \009\009term.setBackgroundColour(colours.white)\
- \009\009term.setTextColour(colours.black)\
- \009\009local extension = \".nfp\"\
- \009\009if fileType == 2 then extension = \".nfa\"\
- \009\009elseif fileType == 3 then extension = \".nft\" end\
- \009\009term.write(extension)\
- \009\009\
- \009\009term.setBackgroundColour(colours.lightGrey)\
- \009\009term.setTextColour(colours.grey)\
- \009\009for i=1,3 do\
- \009\009\009term.setCursorPos(tlx + 24, tly + i)\
- \009\009\009if i==fileType then term.write(\"X\")\
- \009\009\009else term.write(\" \") end\
- \009\009end\
- \009\009\
- \009\009local fPath = shell.resolve(newFName..extension)\
- \009\009term.setCursorPos(tlx, tly + 3)\
- \009\009local fileValid = true\
- \009\009if (fs.exists(fPath) and fs.isDir(fPath)) or newFName == \"\" then\
- \009\009\009term.setBackgroundColour(colours.white)\
- \009\009\009term.setTextColour(colours.red)\
- \009\009\009term.write(\"Invalid \")\
- \009\009\009fileValid = false\
- \009\009elseif fs.exists(fPath) then\
- \009\009\009term.setBackgroundColour(colours.grey)\
- \009\009\009term.setTextColour(colours.lightGrey)\
- \009\009\009term.write(\" Edit \")\
- \009\009else\
- \009\009\009term.setBackgroundColour(colours.grey)\
- \009\009\009term.setTextColour(colours.lightGrey)\
- \009\009\009term.write(\" Create \")\
- \009\009end\
- \009\009\
- \009\009term.setTextColour(colours.grey)\
- \009\009term.setCursorPos(tlx + 6 + #newFName, tly)\
- \009\009term.setCursorBlink(true)\
- \009\009\
- \009\009local id,p1,p2,p3 = os.pullEvent()\
- \009\009if id == \"key\" then\
- \009\009\009if p1 == keys.backspace and #newFName > 0 then \
- \009\009\009\009newFName = string.sub(newFName, 1, #newFName-1)\
- \009\009\009elseif p1 == keys.enter and fileValid then\
- \009\009\009\009sPath = fPath\
- \009\009\009\009return true\
- \009\009\009end\
- \009\009elseif id == \"char\" and p1 ~= \".\" and p1 ~= \" \" and #newFName < 15 then\
- \009\009\009newFName = newFName..p1\
- \009\009elseif id == \"mouse_click\" then\
- \009\009\009--The option boxes. Man, hardcoding is ugly...\
- \009\009\009if p2 == tlx + 24 then\
- \009\009\009\009for i=1,3 do \
- \009\009\009\009\009if p3 == tly+i then fileType = i end \
- \009\009\009\009end\
- \009\009\009end\
- \009\009\009if p3 == tly + 3 and p2 >= tlx and p2 <= tlx + 8 and fileValid then\
- \009\009\009\009sPath = fPath\
- \009\009\009\009return true\
- \009\009\009end\
- \009\009end\
- \009end\
- end\
- \
- --[[Initializes the program, by loading in the paint file. Called at the start of each program.\
- Params: none\
- Returns:nil\
- ]]--\
- local function init()\
- if textEnabled then\
- loadNFT(sPath)\
- table.insert(ddModes, 2, { \"text\", \"textpaint\", name = \"text\"})\
- elseif animated then\
- loadNFA(sPath)\
- table.insert(ddModes, #ddModes, { \"record\", \"play\", name = \"anim\" })\
- table.insert(ddModes, #ddModes, { \"go to\", \"remove\", name = \"frames\"})\
- table.insert(ddModes[2], #ddModes[2], \"blueprint on\")\
- table.insert(ddModes[2], #ddModes[2], \"layers on\")\
- else\
- loadNFP(sPath)\
- table.insert(ddModes[2], #ddModes[2], \"blueprint on\")\
- end\
- \009\009\
- for i=0,15 do\
- table.insert(column, math.pow(2,i))\
- end\
- end\
- \
- --[[ \
- Section: Drawing \
- ]]--\
- \
- \
- --[[Draws the rather superflous logo. Takes about 1 second, before user is able to move to the\
- actual program.\
- Params: none\
- Returns:bool= true if the file select ran successfully; false otherwise.\
- ]]--\
- local function drawLogo()\
- term.setBackgroundColour(colours.white)\
- term.clear()\
- \009\009if h >= 12 and w >= 24 then\
- \009\009\009drawPictureTable(logo, w/2 - #logo[1]/2, h/2 - #logo/2, colours.white)\
- \009\009\009term.setBackgroundColour(colours.white)\
- \009\009\009term.setTextColour(colours.black)\
- \009\009\009local msg = \"NPaintPro\"\
- \009\009\009term.setCursorPos(w/2 - #msg/2, h/2 + #logo/2 + 1)\
- \009\009\009term.write(msg)\
- \009\009\009msg = \"By NitrogenFingers\"\
- \009\009\009term.setCursorPos(w/2 - #msg/2, h/2 + #logo/2 + 2)\
- \009\009\009term.write(msg)\
- elseif w >= 15 then\
- \009\009\009local msg = \"NPaintPro\"\
- \009\009\009term.setCursorPos(math.ceil(w/2 - #msg/2), h/2)\
- \009\009\009term.setTextColour(colours.cyan)\
- \009\009\009term.write(msg)\
- \009\009\009msg = \"NitrogenFingers\"\
- \009\009\009term.setCursorPos(math.ceil(w/2 - #msg/2), h/2 + 1)\
- \009\009\009term.setTextColour(colours.black)\
- \009\009\009term.write(msg)\
- \009\009else\
- \009\009\009local msg = \"NPP\"\
- \009\009\009term.setCursorPos(math.ceil(w/2 - #msg/2), math.floor(h/2))\
- \009\009\009term.setTextColour(colours.cyan)\
- \009\009\009term.write(msg)\
- \009\009\009msg = \"By NF\"\
- \009\009\009term.setCursorPos(math.ceil(w/2 - #msg/2), math.ceil(h/2))\
- \009\009\009term.setTextColour(colours.black)\
- \009\009\009term.write(msg)\
- \009\009end\
- os.pullEvent()\
- end\
- \
- --[[Clears the display to the alpha channel colour, draws the canvas, the image buffer and the selection\
- rectanlge if any of these things are present.\
- Params: none\
- Returns:nil\
- ]]--\
- local function drawCanvas()\
- --We have to readjust the position of the canvas if we're printing\
- turtlechar = \"@\"\
- if state == \"active print\" then\
- if layering == \"up\" then\
- if py >= 1 and py <= #frames then\
- sFrame = py\
- end\
- if pz < sy then sy = pz\
- elseif pz > sy + h - 1 then sy = pz + h - 1 end\
- if px < sx then sx = px\
- elseif px > sx + w - 2 then sx = px + w - 2 end\
- else\
- if pz >= 1 and pz <= #frames then\
- sFrame = pz\
- end\
- \
- if py < sy then sy = py\
- elseif py > sy + h - 1 then sy = py + h - 1 end\
- if px < sx then sx = px\
- elseif px > sx + w - 2 then sx = px + w - 2 end\
- end\
- \
- if pfx == 1 then turtlechar = \">\"\
- elseif pfx == -1 then turtlechar = \"<\"\
- elseif pfz == 1 then turtlechar = \"V\"\
- elseif pfz == -1 then turtlechar = \"^\"\
- end\
- end\
- \
- --Picture next\
- local topLayer, botLayer\
- if layerDisplay then\
- topLayer = sFrame\
- botLayer = 1\
- else\
- topLayer,botLayer = sFrame,sFrame\
- end\
- \
- \009 --How far the canvas draws. If the interface is visible, it stops short of that.\
- \009 local wlim,hlim = 0,0\
- \009\009if not interfaceHidden then\
- \009\009\009wlim = 2\
- \009\009\009hlim = 1\
- \009\009end\
- \009 \
- for currframe = botLayer,topLayer,1 do\
- for y=sy+1,sy+h-hlim do\
- if frames[currframe][y] then\
- for x=sx+1,sx+w-wlim do\
- term.setCursorPos(x-sx,y-sy)\
- if frames[currframe][y][x] then\
- term.setBackgroundColour(frames[currframe][y][x])\
- if textEnabled and frames[currframe].textcol[y][x] and frames[currframe].text[y][x] then\
- term.setTextColour(frames[currframe].textcol[y][x])\
- term.write(frames[currframe].text[y][x])\
- else\
- term.write(\" \")\
- end\
- else\
- tileExists = false\
- for i=currframe-1,botLayer,-1 do\
- if frames[i][y][x] then\
- tileExists = true\
- break\
- end\
- end\
- \
- if not tileExists then\
- if blueprint then\
- term.setBackgroundColour(colours.blue)\
- term.setTextColour(colours.white)\
- if x == sx+1 and y % 4 == 1 then\
- term.write(\"\"..((y/4) % 10))\
- elseif y == sy + 1 and x % 4 == 1 then\
- term.write(\"\"..((x/4) % 10))\
- elseif x % 2 == 1 and y % 2 == 1 then\
- term.write(\"+\")\
- elseif x % 2 == 1 then\
- term.write(\"|\")\
- elseif y % 2 == 1 then\
- term.write(\"-\")\
- else\
- term.write(\" \")\
- end\
- else\
- term.setBackgroundColour(alphaC)\
- if textEnabled and frames[currframe].textcol[y][x] and frames[currframe].text[y][x] then\
- term.setTextColour(frames[currframe].textcol[y][x])\
- term.write(frames[currframe].text[y][x])\
- else\
- term.write(\" \")\
- end\
- end\
- end\
- end\
- end\
- else\
- for x=sx+1,sx+w-wlim do\
- term.setCursorPos(x-sx,y-sy)\
- \
- tileExists = false\
- for i=currframe-1,botLayer,-1 do\
- if frames[i][y] and frames[i][y][x] then\
- tileExists = true\
- break\
- end\
- end\
- \
- if not tileExists then\
- if blueprint then\
- term.setBackgroundColour(colours.blue)\
- term.setTextColour(colours.white)\
- if x == sx+1 and y % 4 == 1 then\
- term.write(\"\"..((y/4) % 10))\
- elseif y == sy + 1 and x % 4 == 1 then\
- term.write(\"\"..((x/4) % 10))\
- elseif x % 2 == 1 and y % 2 == 1 then\
- term.write(\"+\")\
- elseif x % 2 == 1 then\
- term.write(\"|\")\
- elseif y % 2 == 1 then\
- term.write(\"-\")\
- else\
- term.write(\" \")\
- end\
- else\
- term.setBackgroundColour(alphaC)\
- term.write(\" \")\
- end\
- end\
- end\
- end\
- end\
- end\
- \
- --Then the printer, if he's on\
- if state == \"active print\" then\
- local bgColour = alphaC\
- if layering == \"up\" then\
- term.setCursorPos(px-sx,pz-sy)\
- if frames[sFrame] and frames[sFrame][pz-sy] and frames[sFrame][pz-sy][px-sx] then\
- bgColour = frames[sFrame][pz-sy][px-sx]\
- elseif blueprint then bgColour = colours.blue end\
- else\
- term.setCursorPos(px-sx,py-sy)\
- if frames[sFrame] and frames[sFrame][py-sy] and frames[sFrame][py-sy][px-sx] then\
- bgColour = frames[sFrame][py-sy][px-sx]\
- elseif blueprint then bgColour = colours.blue end\
- end\
- \
- term.setBackgroundColour(bgColour)\
- if bgColour == colours.black then term.setTextColour(colours.white)\
- else term.setTextColour(colours.black) end\
- \
- term.write(turtlechar)\
- end\
- \
- --Then the buffer\
- if selectrect then\
- if buffer and rectblink == 1 then\
- for y=selectrect.y1, math.min(selectrect.y2, selectrect.y1 + buffer.height-1) do\
- for x=selectrect.x1, math.min(selectrect.x2, selectrect.x1 + buffer.width-1) do\
- if buffer.contents[y-selectrect.y1+1][x-selectrect.x1+1] then\
- term.setCursorPos(x+sx,y+sy)\
- term.setBackgroundColour(buffer.contents[y-selectrect.y1+1][x-selectrect.x1+1])\
- term.write(\" \")\
- end\
- end\
- end\
- end\
- \
- --This draws the \"selection\" box\
- local add = nil\
- if buffer then\
- term.setBackgroundColour(colours.lightGrey)\
- else\
- term.setBackgroundColour(colours.grey)\
- end\
- for i=selectrect.x1, selectrect.x2 do\
- add = (i + selectrect.y1 + rectblink) % 2 == 0\
- term.setCursorPos(i-sx,selectrect.y1-sy)\
- if add then term.write(\" \") end\
- add = (i + selectrect.y2 + rectblink) % 2 == 0\
- term.setCursorPos(i-sx,selectrect.y2-sy)\
- if add then term.write(\" \") end\
- end\
- for i=selectrect.y1 + 1, selectrect.y2 - 1 do\
- add = (i + selectrect.x1 + rectblink) % 2 == 0\
- term.setCursorPos(selectrect.x1-sx,i-sy)\
- if add then term.write(\" \") end\
- add = (i + selectrect.x2 + rectblink) % 2 == 0\
- term.setCursorPos(selectrect.x2-sx,i-sy)\
- if add then term.write(\" \") end\
- end\
- end\
- end\
- \
- --[[Draws the colour picker on the right side of the screen, the colour pallette and the footer with any\
- messages currently being displayed\
- Params: none\
- Returns:nil\
- ]]--\
- local function drawInterface()\
- --Picker\
- \009\009local coffset,ioffset = 0,0\
- \009\009local maxcsize = h-2\
- \009\009if h < #column + 2 then\
- \009\009\009maxcsize = h-4\
- \009\009\009coffset = columnoffset\
- \009\009\009ioffset = 1\
- \009\009\009term.setBackgroundColour(colours.lightGrey)\
- \009\009\009term.setTextColour(colours.grey)\
- \009\009\009term.setCursorPos(w-1,1)\
- \009\009\009term.write(\"^^\")\
- \009\009\009term.setCursorPos(w-1,h-2)\
- \009\009\009term.write(\"VV\")\
- \009\009end\
- for i=1,math.min(#column+1,maxcsize) do\
- \009\009\009term.setCursorPos(w-1, i + ioffset)\
- \009\009\009local ci = i+coffset\
- \009\009\009if ci == #column+1 then\
- \009\009\009\009term.setBackgroundColour(colours.black)\
- \009\009\009\009term.setTextColour(colours.red)\
- \009\009\009\009term.write(\"XX\")\
- \009\009\009elseif state == \"print\" then\
- \009\009\009\009term.setBackgroundColour(column[ci])\
- \009\009\009\009if column[ci] == colours.black then\
- \009\009\009\009\009term.setTextColour(colours.white)\
- \009\009\009\009else term.setTextColour(colours.black) end\
- \009\009\009\009\
- \009\009\009\009if requirementsDisplayed then\
- \009\009\009\009\009\009if requiredMaterials[i] < 10 then term.write(\" \") end\
- \009\009\009\009\009\009term.setCursorPos(w-#tostring(requiredMaterials[i])+1, i)\
- \009\009\009\009\009\009term.write(requiredMaterials[i])\
- \009\009\009\009else\
- \009\009\009\009\009\009if i+coffset < 10 then term.write(\" \") end\
- \009\009\009\009\009\009term.write(i+coffset)\
- \009\009\009\009end\
- \009\009\009else\
- \009\009\009\009term.setBackgroundColour(column[ci])\
- \009\009\009\009term.write(\" \")\
- \009\009\009end\
- end\
- \009\009--Filling the whitespace with... 'greyspace' *shudder*\
- \009\009if h > #column+3 then\
- \009\009\009term.setTextColour(colours.grey)\
- \009\009\009term.setBackgroundColour(colours.lightGrey)\
- \009\009\009for y=#column+2,h-2 do\
- \009\009\009\009term.setCursorPos(w-1,y)\
- \009\009\009\009term.write(\"| \")\
- \009\009\009end\
- \009\009end\
- --Pallette\
- term.setCursorPos(w-1,h-1)\
- if not lSel then\
- term.setBackgroundColour(colours.black)\
- term.setTextColour(colours.red)\
- term.write(\"X\")\
- else\
- term.setBackgroundColour(lSel)\
- term.setTextColour(lSel)\
- term.write(\" \")\
- end\
- if not rSel then\
- term.setBackgroundColour(colours.black)\
- term.setTextColour(colours.red)\
- term.write(\"X\")\
- else\
- term.setBackgroundColour(rSel)\
- term.setTextColour(rSel)\
- term.write(\" \")\
- end\
- --Footer\
- if inMenu then return end\
- \
- term.setCursorPos(1, h)\
- term.setBackgroundColour(colours.lightGrey)\
- term.setTextColour(colours.grey)\
- term.clearLine()\
- \009\009if mainAvailable then\
- \009\009\009if inDropDown then\
- \009\009\009\009\009term.write(string.rep(\" \", #ddModes.name + 2))\
- \009\009\009else\
- \009\009\009\009\009term.setBackgroundColour(colours.grey)\
- \009\009\009\009\009term.setTextColour(colours.lightGrey)\
- \009\009\009\009\009term.write(ddModes.name..\" \")\
- \009\009\009end\
- \009\009end\
- term.setBackgroundColour(colours.lightGrey)\
- term.setTextColour(colours.grey)\
- term.write(getStateMessage())\
- \
- local coords=\"X:\"..sx..\" Y:\"..sy\
- if animated then coords = coords..\" Frame:\"..sFrame..\"/\"..framecount..\" \" end\
- term.setCursorPos(w-#coords+1,h)\
- if state == \"play\" then term.setBackgroundColour(colours.lime)\
- elseif record then term.setBackgroundColour(colours.red) end\
- term.write(coords)\
- \
- if animated then\
- term.setCursorPos(w-1,h)\
- term.setBackgroundColour(colours.grey)\
- term.setTextColour(colours.lightGrey)\
- term.write(\"<>\")\
- end\
- end\
- \
- --[[Runs an interface where users can select topics of help. Will return once the user quits the help screen.\
- Params: none\
- Returns:nil\
- ]]--\
- local function drawHelpScreen()\
- local selectedHelp = nil\
- while true do\
- term.setBackgroundColour(colours.lightGrey)\
- term.clear()\
- if not selectedHelp then\
- term.setCursorPos(4, 1)\
- term.setTextColour(colours.brown)\
- term.write(\"Available modes (click for info):\")\
- for i=1,#helpTopics do\
- term.setCursorPos(2, 2 + i)\
- term.setTextColour(colours.black)\
- term.write(helpTopics[i].name)\
- if helpTopics[i].key then\
- term.setTextColour(colours.red)\
- term.write(\" (\"..helpTopics[i].key..\")\")\
- end\
- end\
- term.setCursorPos(4,h)\
- term.setTextColour(colours.black)\
- term.write(\"Press any key to exit\")\
- else\
- term.setCursorPos(4,1)\
- term.setTextColour(colours.brown)\
- term.write(helpTopics[selectedHelp].name)\
- if helpTopics[selectedHelp].key then\
- term.setTextColour(colours.red)\
- term.write(\" (\"..helpTopics[selectedHelp].key..\")\")\
- end\
- term.setCursorPos(1,3)\
- term.setTextColour(colours.black)\
- print(helpTopics[selectedHelp].message..\"\\n\")\
- for i=1,#helpTopics[selectedHelp].controls do\
- term.setTextColour(colours.brown)\
- term.write(helpTopics[selectedHelp].controls[i][1]..\" \")\
- term.setTextColour(colours.black)\
- print(helpTopics[selectedHelp].controls[i][2])\
- end\
- end\
- \
- local id,p1,p2,p3 = os.pullEvent()\
- \
- if id == \"timer\" then updateTimer(p1)\
- elseif id == \"key\" then\
- if selectedHelp then selectedHelp = nil\
- else break end\
- elseif id == \"mouse_click\" then\
- if not selectedHelp then\
- if p3 >=3 and p3 <= 2+#helpTopics then\
- selectedHelp = p3-2\
- else break end\
- else\
- selectedHelp = nil\
- end\
- end\
- end\
- end\
- \
- --[[Draws a message in the footer bar. A helper for DrawInterface, but can be called for custom messages, if the\
- inMenu paramter is set to true while this is being done (remember to set it back when done!)\
- Params: message:string = The message to be drawn\
- Returns:nil\
- ]]--\
- local function drawMessage(message)\
- term.setCursorPos(1,h)\
- term.setBackgroundColour(colours.lightGrey)\
- term.setTextColour(colours.grey)\
- term.clearLine()\
- term.write(message)\
- end\
- \
- --[[\
- Section: Generic Interfaces\
- ]]--\
- \
- \
- --[[One of my generic text printing methods, printing a message at a specified position with width and offset.\
- No colour materials included.\
- Params: msg:string = The message to print off-center\
- height:number = The starting height of the message\
- width:number = The limit as to how many characters long each line may be\
- offset:number = The starting width offset of the message\
- Returns:number the number of lines used in printing the message\
- ]]--\
- local function wprintOffCenter(msg, height, width, offset)\
- local inc = 0\
- local ops = 1\
- while #msg - ops > width do\
- local nextspace = 0\
- while string.find(msg, \" \", ops + nextspace) and\
- string.find(msg, \" \", ops + nextspace) - ops < width do\
- nextspace = string.find(msg, \" \", nextspace + ops) + 1 - ops\
- end\
- local ox,oy = term.getCursorPos()\
- term.setCursorPos(width/2 - (nextspace)/2 + offset, height + inc)\
- inc = inc + 1\
- term.write(string.sub(msg, ops, nextspace + ops - 1))\
- ops = ops + nextspace\
- end\
- term.setCursorPos(width/2 - #string.sub(msg, ops)/2 + offset, height + inc)\
- term.write(string.sub(msg, ops))\
- \
- return inc + 1\
- end\
- \
- --[[Draws a message that must be clicked on or a key struck to be cleared. No options, so used for displaying\
- generic information.\
- Params: ctitle:string = The title of the confirm dialogue\
- msg:string = The message displayed in the dialogue\
- Returns:nil\
- ]]--\
- local function displayConfirmDialogue(ctitle, msg)\
- local dialogoffset = 8\
- --We actually print twice- once to get the lines, second time to print proper. Easier this way.\
- local lines = wprintOffCenter(msg, 5, w - (dialogoffset+2) * 2, dialogoffset + 2)\
- \
- term.setCursorPos(dialogoffset, 3)\
- term.setBackgroundColour(colours.grey)\
- term.setTextColour(colours.lightGrey)\
- term.write(string.rep(\" \", w - dialogoffset * 2))\
- term.setCursorPos(dialogoffset + (w - dialogoffset * 2)/2 - #ctitle/2, 3)\
- term.write(ctitle)\
- term.setTextColour(colours.grey)\
- term.setBackgroundColour(colours.lightGrey)\
- term.setCursorPos(dialogoffset, 4)\
- term.write(string.rep(\" \", w - dialogoffset * 2))\
- for i=5,5+lines do\
- term.setCursorPos(dialogoffset, i)\
- term.write(\" \"..string.rep(\" \", w - (dialogoffset) * 2 - 2)..\" \")\
- end\
- wprintOffCenter(msg, 5, w - (dialogoffset+2) * 2, dialogoffset + 2)\
- \
- --In the event of a message, the player hits anything to continue\
- while true do\
- local id,key = os.pullEvent()\
- if id == \"timer\" then updateTimer(key);\
- elseif id == \"key\" or id == \"mouse_click\" or id == \"mouse_drag\" then break end\
- end\
- end\
- \
- --[[Produces a nice dropdown menu based on a table of strings. Depending on the position, this will auto-adjust the position\
- of the menu drawn, and allows nesting of menus and sub menus. Clicking anywhere outside the menu will cancel and return nothing\
- Params: x:int = the x position the menu should be displayed at\
- y:int = the y position the menu should be displayed at\
- options:table = the list of options available to the user, as strings or submenus (tables of strings, with a name parameter)\
- Returns:string the selected menu option.\
- ]]--\
- local function displayDropDown(x, y, options)\
- inDropDown = true\
- --Figures out the dimensions of our thing\
- local longestX = #options.name\
- for i=1,#options do\
- local currVal = options[i]\
- if type(currVal) == \"table\" then currVal = currVal.name end\
- \
- longestX = math.max(longestX, #currVal)\
- end\
- local xOffset = math.max(0, longestX - ((w-2) - x) + 1)\
- local yOffset = math.max(0, #options - ((h-1) - y))\
- \
- local clickTimes = 0\
- local tid = nil\
- local selection = nil\
- while clickTimes < 2 do\
- drawCanvas()\
- drawInterface()\
- \
- term.setCursorPos(x-xOffset,y-yOffset)\
- term.setBackgroundColour(colours.grey)\
- term.setTextColour(colours.lightGrey)\
- term.write(options.name..string.rep(\" \", longestX-#options.name + 2))\
- \
- for i=1,#options do\
- term.setCursorPos(x-xOffset, y-yOffset+i)\
- if i==selection and clickTimes % 2 == 0 then\
- term.setBackgroundColour(colours.grey)\
- term.setTextColour(colours.lightGrey)\
- else\
- term.setBackgroundColour(colours.lightGrey)\
- term.setTextColour(colours.grey)\
- end\
- local currVal = options[i]\
- if type(currVal) == \"table\" then\
- term.write(currVal.name..string.rep(\" \", longestX-#currVal.name + 1))\
- term.setBackgroundColour(colours.grey)\
- term.setTextColour(colours.lightGrey)\
- term.write(\">\")\
- else\
- term.write(currVal..string.rep(\" \", longestX-#currVal + 2))\
- end\
- end\
- \
- local id, p1, p2, p3 = os.pullEvent()\
- if id == \"timer\" then\
- if p1 == tid then\
- clickTimes = clickTimes + 1\
- if clickTimes > 2 then\
- break\
- else\
- tid = os.startTimer(0.1)\
- end\
- else\
- updateTimer(p1)\
- drawCanvas()\
- drawInterface()\
- end\
- elseif id == \"mouse_click\" then\
- if p2 >=x-xOffset and p2 <= x-xOffset + longestX + 1 and p3 >= y-yOffset+1 and p3 <= y-yOffset+#options then\
- selection = p3-(y-yOffset)\
- tid = os.startTimer(0.1)\
- else\
- selection = \"\"\
- break\
- end\
- end\
- end\
- \
- if type(selection) == \"number\" then\
- selection = options[selection]\
- end\
- \
- if type(selection) == \"string\" then\
- inDropDown = false\
- return selection\
- elseif type(selection) == \"table\" then\
- return displayDropDown(x, y, selection)\
- end\
- end\
- \
- --[[A custom io.read() function with a few differences- it limits the number of characters being printed,\
- waits a 1/100th of a second so any keys still in the event library are removed before input is read and\
- the timer for the selectionrectangle is continuously updated during the process.\
- Params: lim:int = the number of characters input is allowed\
- Returns:string the inputted string, trimmed of leading and tailing whitespace\
- ]]--\
- local function readInput(lim)\
- term.setCursorBlink(true)\
- \
- local inputString = \"\"\
- if not lim or type(lim) ~= \"number\" or lim < 1 then lim = w - ox end\
- local ox,oy = term.getCursorPos()\
- --We only get input from the footer, so this is safe. Change if recycling\
- term.setBackgroundColour(colours.lightGrey)\
- term.setTextColour(colours.grey)\
- term.write(string.rep(\" \", lim))\
- term.setCursorPos(ox, oy)\
- --As events queue immediately, we may get an unwanted key... this will solve that problem\
- local inputTimer = os.startTimer(0.01)\
- local keysAllowed = false\
- \
- while true do\
- local id,key = os.pullEvent()\
- \
- if keysAllowed then\
- if id == \"key\" and key == 14 and #inputString > 0 then\
- inputString = string.sub(inputString, 1, #inputString-1)\
- term.setCursorPos(ox + #inputString,oy)\
- term.write(\" \")\
- elseif id == \"key\" and key == 28 and inputString ~= string.rep(\" \", #inputString) then\
- break\
- elseif id == \"key\" and key == keys.leftCtrl then\
- return \"\"\
- elseif id == \"char\" and #inputString < lim then\
- inputString = inputString..key\
- end\
- end\
- \
- if id == \"timer\" then\
- if key == inputTimer then\
- keysAllowed = true\
- else\
- updateTimer(key)\
- drawCanvas()\
- drawInterface()\
- term.setBackgroundColour(colours.lightGrey)\
- term.setTextColour(colours.grey)\
- end\
- end\
- term.setCursorPos(ox,oy)\
- term.write(inputString)\
- term.setCursorPos(ox + #inputString, oy)\
- end\
- \
- while string.sub(inputString, 1, 1) == \" \" do\
- inputString = string.sub(inputString, 2, #inputString)\
- end\
- while string.sub(inputString, #inputString, #inputString) == \" \" do\
- inputString = string.sub(inputString, 1, #inputString-1)\
- end\
- term.setCursorBlink(false)\
- \
- return inputString\
- end\
- \
- --[[ \
- Section: Image tools\
- ]]--\
- \
- \
- --[[Copies all pixels beneath the selection rectangle into the image buffer. Empty buffers are converted to nil.\
- Params: removeImage:bool = true if the image is to be erased after copying, false otherwise\
- Returns:nil\
- ]]--\
- local function copyToBuffer(removeImage)\
- buffer = { width = selectrect.x2 - selectrect.x1 + 1, height = selectrect.y2 - selectrect.y1 + 1, contents = { } }\
- \
- local containsSomething = false\
- for y=1,buffer.height do\
- buffer.contents[y] = { }\
- local f,l = sFrame,sFrame\
- if record then f,l = 1, framecount end\
- \
- for fra = f,l do\
- if frames[fra][selectrect.y1 + y - 1] then\
- for x=1,buffer.width do\
- buffer.contents[y][x] = frames[sFrame][selectrect.y1 + y - 1][selectrect.x1 + x - 1]\
- if removeImage then frames[fra][selectrect.y1 + y - 1][selectrect.x1 + x - 1] = nil end\
- if buffer.contents[y][x] then containsSomething = true end\
- end\
- end\
- end\
- end\
- --I don't classify an empty buffer as a real buffer- confusing to the user.\
- if not containsSomething then buffer = nil end\
- end\
- \
- --[[Replaces all pixels under the selection rectangle with the image buffer (or what can be seen of it). Record-dependent.\
- Params: removeBuffer:bool = true if the buffer is to be emptied after copying, false otherwise\
- Returns:nil\
- ]]--\
- local function copyFromBuffer(removeBuffer)\
- if not buffer then return end\
- \
- for y = 1, math.min(buffer.height,selectrect.y2-selectrect.y1+1) do\
- local f,l = sFrame, sFrame\
- if record then f,l = 1, framecount end\
- \
- for fra = f,l do\
- if not frames[fra][selectrect.y1+y-1] then frames[fra][selectrect.y1+y-1] = { } end\
- for x = 1, math.min(buffer.width,selectrect.x2-selectrect.x1+1) do\
- frames[fra][selectrect.y1+y-1][selectrect.x1+x-1] = buffer.contents[y][x]\
- end\
- end\
- end\
- \
- if removeBuffer then buffer = nil end\
- end\
- \
- --[[Moves the entire image (or entire animation) to the specified coordinates. Record-dependent.\
- Params: newx:int = the X coordinate to move the image to\
- newy:int = the Y coordinate to move the image to\
- Returns:nil\
- ]]--\
- local function moveImage(newx,newy)\
- if not leflim or not toplim then return end\
- if newx <=0 or newy <=0 then return end\
- local f,l = sFrame,sFrame\
- if record then f,l = 1,framecount end\
- \
- for i=f,l do\
- local newlines = { }\
- for y=toplim,botlim do\
- local line = frames[i][y]\
- if line then\
- newlines[y-toplim+newy] = { }\
- for x,char in pairs(line) do\
- newlines[y-toplim+newy][x-leflim+newx] = char\
- end\
- end\
- end\
- --Exceptions that allow us to move the text as well\
- if textEnabled then\
- newlines.text = { }\
- for y=toplim,botlim do\
- local line = frames[i].text[y]\
- if line then\
- newlines.text[y-toplim+newy] = { }\
- for x,char in pairs(line) do\
- newlines.text[y-toplim+newy][x-leflim+newx] = char\
- end\
- end\
- end\
- \
- newlines.textcol = { }\
- for y=toplim,botlim do\
- local line = frames[i].textcol[y]\
- if line then\
- newlines.textcol[y-toplim+newy] = { }\
- for x,char in pairs(line) do\
- newlines.textcol[y-toplim+newy][x-leflim+newx] = char\
- end\
- end\
- end\
- end\
- \
- frames[i] = newlines\
- end\
- end\
- \
- --[[Prompts the user to clear the current frame or all frames. Record-dependent.,\
- Params: none\
- Returns:nil\
- ]]--\
- local function clearImage()\
- inMenu = true\
- if not animated then\
- drawMessage(\"Clear image? Y/N: \")\
- elseif record then\
- drawMessage(\"Clear ALL frames? Y/N: \")\
- else\
- drawMessage(\"Clear current frame? Y/N :\")\
- end\
- if string.find(string.upper(readInput(1)), \"Y\") then\
- local f,l = sFrame,sFrame\
- if record then f,l = 1,framecount end\
- \
- for i=f,l do\
- frames[i] = { }\
- end\
- end\
- inMenu = false\
- end\
- \
- --[[A recursively called method (watch out for big calls!) in which every pixel of a set colour is\
- changed to another colour. Does not work on the nil colour, for obvious reasons.\
- Params: x:int = The X coordinate of the colour to flood-fill\
- y:int = The Y coordinate of the colour to flood-fill\
- targetColour:colour = the colour that is being flood-filled\
- newColour:colour = the colour with which to replace the target colour\
- Returns:nil\
- ]]--\
- local function floodFill(x, y, targetColour, newColour)\
- if not newColour or not targetColour then return end\
- local nodeList = { }\
- \
- table.insert(nodeList, {x = x, y = y})\
- \
- while #nodeList > 0 do\
- local node = nodeList[1]\
- if frames[sFrame][node.y] and frames[sFrame][node.y][node.x] == targetColour then\
- frames[sFrame][node.y][node.x] = newColour\
- table.insert(nodeList, { x = node.x + 1, y = node.y})\
- table.insert(nodeList, { x = node.x, y = node.y + 1})\
- if x > 1 then table.insert(nodeList, { x = node.x - 1, y = node.y}) end\
- if y > 1 then table.insert(nodeList, { x = node.x, y = node.y - 1}) end\
- end\
- table.remove(nodeList, 1)\
- end\
- end\
- \
- --[[ \
- Section: Animation Tools \
- ]]--\
- \
- --[[Enters play mode, allowing the animation to play through. Interface is restricted to allow this,\
- and method only leaves once the player leaves play mode.\
- Params: none\
- Returns:nil\
- ]]--\
- local function playAnimation()\
- state = \"play\"\
- selectedrect = nil\
- \
- local animt = os.startTimer(animtime)\
- repeat\
- drawCanvas()\
- drawInterface()\
- \
- local id,key,_,y = os.pullEvent()\
- \
- if id==\"timer\" then\
- if key == animt then\
- animt = os.startTimer(animtime)\
- sFrame = (sFrame % framecount) + 1\
- else\
- updateTimer(key)\
- end\
- elseif id==\"key\" then\
- if key == keys.comma and animtime > 0.1 then animtime = animtime - 0.05\
- elseif key == keys.period and animtime < 0.5 then animtime = animtime + 0.05\
- elseif key == keys.space then state = \"paint\" end\
- elseif id==\"mouse_click\" and y == h then\
- state = \"paint\"\
- end\
- until state ~= \"play\"\
- os.startTimer(0.5)\
- end\
- \
- --[[Changes the selected frame (sFrame) to the chosen frame. If this frame is above the framecount,\
- additional frames are created with a copy of the image on the selected frame.\
- Params: newframe:int = the new frame to move to\
- Returns:nil\
- ]]--\
- local function changeFrame(newframe)\
- inMenu = true\
- if not tonumber(newframe) then\
- term.setCursorPos(1,h)\
- term.setBackgroundColour(colours.lightGrey)\
- term.setTextColour(colours.grey)\
- term.clearLine()\
- \
- term.write(\"Go to frame: \")\
- newframe = tonumber(readInput(2))\
- if not newframe or newframe <= 0 then\
- inMenu = false\
- return\
- end\
- elseif newframe <= 0 then return end\
- \
- if newframe > framecount then\
- for i=framecount+1,newframe do\
- frames[i] = {}\
- for y,line in pairs(frames[sFrame]) do\
- frames[i][y] = { }\
- for x,v in pairs(line) do\
- frames[i][y][x] = v\
- end\
- end\
- end\
- framecount = newframe\
- end\
- sFrame = newframe\
- inMenu = false\
- end\
- \
- --[[Removes every frame leading after the frame passed in\
- Params: frame:int the non-inclusive lower bounds of the delete\
- Returns:nil\
- ]]--\
- local function removeFramesAfter(frame)\
- inMenu = true\
- if frame==framecount then return end\
- drawMessage(\"Remove frames \"..(frame+1)..\"/\"..framecount..\"? Y/N :\")\
- local answer = string.upper(readInput(1))\
- \
- if string.find(answer, string.upper(\"Y\")) ~= 1 then\
- inMenu = false\
- return\
- end\
- \
- for i=frame+1, framecount do\
- frames[i] = nil\
- end\
- framecount = frame\
- inMenu = false\
- end\
- \
- --[[\
- Section: Printing Tools\
- ]]--\
- \
- --[[Constructs a new facing to the left of the current facing\
- Params: curx:number = The facing on the X axis\
- curz:number = The facing on the Z axis\
- hand:string = The hand of the axis (\"right\" or \"left\")\
- Returns:number,number = the new facing on the X and Z axis after a left turn\
- ]]--\
- local function getLeft(curx, curz)\
- local hand = \"left\"\
- if layering == \"up\" then hand = \"right\" end\
- \
- if hand == \"right\" then\
- if curx == 1 then return 0,-1 end\
- if curx == -1 then return 0,1 end\
- if curz == 1 then return 1,0 end\
- if curz == -1 then return -1,0 end\
- else\
- if curx == 1 then return 0,1 end\
- if curx == -1 then return 0,-1 end\
- if curz == 1 then return -1,0 end\
- if curz == -1 then return 1,0 end\
- end\
- end\
- \
- --[[Constructs a new facing to the right of the current facing\
- Params: curx:number = The facing on the X axis\
- curz:number = The facing on the Z axis\
- hand:string = The hand of the axis (\"right\" or \"left\")\
- Returns:number,number = the new facing on the X and Z axis after a right turn\
- ]]--\
- local function getRight(curx, curz)\
- local hand = \"left\"\
- if layering == \"up\" then hand = \"right\" end\
- \
- if hand == \"right\" then\
- if curx == 1 then return 0,1 end\
- if curx == -1 then return 0,-1 end\
- if curz == 1 then return -1,0 end\
- if curz == -1 then return 1,0 end\
- else\
- if curx == 1 then return 0,-1 end\
- if curx == -1 then return 0,1 end\
- if curz == 1 then return 1,0 end\
- if curz == -1 then return -1,0 end\
- end\
- end\
- \
- \
- --[[Sends out a rednet signal requesting local printers, and will listen for any responses. Printers found are added to the\
- printerList (for ID's) and printerNames (for names)\
- Params: nil\
- Returns:nil\
- ]]--\
- local function locatePrinters()\
- printerList = { }\
- printerNames = { name = \"Printers\" }\
- local oldState = state\
- state = \"Locating printers, please wait... \"\
- drawCanvas()\
- drawInterface()\
- state = oldState\
- \
- local modemOpened = false\
- for k,v in pairs(rs.getSides()) do\
- if peripheral.isPresent(v) and peripheral.getType(v) == \"modem\" then\
- rednet.open(v)\
- modemOpened = true\
- break\
- end\
- end\
- \
- if not modemOpened then\
- displayConfirmDialogue(\"Modem not found!\", \"No modem peripheral. Must have network modem to locate printers.\")\
- return false\
- end\
- \
- rednet.broadcast(\"$3DPRINT IDENTIFY\")\
- \
- while true do\
- local id, msg = rsTimeReceive(1)\
- \
- if not id then break end\
- if string.find(msg, \"$3DPRINT IDACK\") == 1 then\
- msg = string.gsub(msg, \"$3DPRINT IDACK \", \"\")\
- table.insert(printerList, id)\
- table.insert(printerNames, msg)\
- end\
- end\
- \
- if #printerList == 0 then\
- displayConfirmDialogue(\"Printers not found!\", \"No active printers found in proximity of this computer.\")\
- return false\
- else\
- return true\
- end\
- end\
- \
- --[[Sends a request to the printer. Waits on a response and updates the state of the application accordingly.\
- Params: command:string the command to send\
- param:string a parameter to send, if any\
- Returns:nil\
- ]]--\
- local function sendPC(command,param)\
- local msg = \"$PC \"..command\
- if param then msg = msg..\" \"..param end\
- rednet.send(printerList[selectedPrinter], msg)\
- \
- while true do\
- local id,key = rsTimeReceive()\
- if id == printerList[selectedPrinter] then\
- if key == \"$3DPRINT ACK\" then\
- break\
- elseif key == \"$3DPRINT DEP\" then\
- displayConfirmDialogue(\"Printer Empty\", \"The printer has exhasted a material. Please refill slot \"..param..\
- \", and click this message when ready to continue.\")\
- rednet.send(printerList[selectedPrinter], msg)\
- elseif key == \"$3DPRINT OOF\" then\
- displayConfirmDialogue(\"Printer Out of Fuel\", \"The printer has no fuel. Please replace the material \"..\
- \"in slot 1 with a fuel source, then click this message.\")\
- rednet.send(printerList[selectedPrinter], \"$PC SS 1\")\
- id,key = rsTimeReceive()\
- rednet.send(printerList[selectedPrinter], \"$PC RF\")\
- id,key = rsTimeReceive()\
- rednet.send(printerList[selectedPrinter], msg)\
- end\
- end\
- end\
- \
- --Changes to position are handled after the event has been successfully completed\
- if command == \"FW\" then\
- px = px + pfx\
- pz = pz + pfz\
- elseif command == \"BK\" then\
- px = px - pfx\
- pz = pz - pfz\
- elseif command == \"UP\" then\
- if layering == \"up\" then\
- py = py + 1\
- else\
- py = py - 1\
- end\
- elseif command == \"DW\" then\
- if layering == \"up\" then\
- py = py - 1\
- else \
- py = py + 1\
- end\
- elseif command == \"TL\" then\
- pfx,pfz = getLeft(pfx,pfz)\
- elseif command == \"TR\" then\
- pfx,pfz = getRight(pfx,pfz)\
- elseif command == \"TU\" then\
- pfx = -pfx\
- pfz = -pfz\
- end\
- \
- drawCanvas()\
- drawInterface()\
- end\
- \
- --[[A printing function that commands the printer to turn to face the desired direction, if it is not already doing so\
- Params: desx:number = the normalized x direction to face\
- desz:number = the normalized z direction to face\
- Returns:nil\
- ]]--\
- local function turnToFace(desx,desz)\
- if desx ~= 0 then\
- if pfx ~= desx then\
- local temppfx,_ = getLeft(pfx,pfz)\
- if temppfx == desx then\
- sendPC(\"TL\")\
- elseif temppfx == -desx then\
- sendPC(\"TR\")\
- else\
- sendPC(\"TU\")\
- end\
- end\
- else\
- print(\"on the z axis\")\
- if pfz ~= desz then\
- local _,temppfz = getLeft(pfx,pfz)\
- if temppfz == desz then\
- sendPC(\"TL\")\
- elseif temppfz == -desz then\
- sendPC(\"TR\")\
- else\
- sendPC(\"TU\")\
- end\
- end\
- end\
- end\
- \
- --[[Performs the print\
- Params: nil\
- Returns:nil\
- ]]--\
- local function performPrint()\
- state = \"active print\"\
- if layering == \"up\" then\
- --An up layering starts our builder bot on the bottom left corner of our build\
- px,py,pz = leflim, 0, botlim + 1\
- pfx,pfz = 0,-1\
- \
- --We move him forward and up a bit from his original position.\
- sendPC(\"FW\")\
- sendPC(\"UP\")\
- --For each layer that needs to be completed, we go up by one each time\
- for layers=1,#frames do\
- --We first decide if we're going forwards or back, depending on what side we're on\
- local rowbot,rowtop,rowinc = nil,nil,nil\
- if pz == botlim then\
- rowbot,rowtop,rowinc = botlim,toplim,-1\
- else\
- rowbot,rowtop,rowinc = toplim,botlim,1\
- end\
- \
- for rows = rowbot,rowtop,rowinc do\
- --Then we decide if we're going left or right, depending on what side we're on\
- local linebot,linetop,lineinc = nil,nil,nil\
- if px == leflim then\
- --Facing from the left side has to be easterly- it's changed here\
- turnToFace(1,0)\
- linebot,linetop,lineinc = leflim,riglim,1\
- else\
- --Facing from the right side has to be westerly- it's changed here\
- turnToFace(-1,0)\
- linebot,linetop,lineinc = riglim,leflim,-1\
- end\
- \
- for lines = linebot,linetop,lineinc do\
- --We move our turtle forward, placing the right material at each step\
- local material = frames[py][pz][px]\
- if material then\
- material = math.log10(frames[py][pz][px])/math.log10(2) + 1\
- sendPC(\"SS\", material)\
- sendPC(\"PD\")\
- end\
- if lines ~= linetop then\
- sendPC(\"FW\")\
- end\
- end\
- \
- --The printer then has to do a U-turn, depending on which way he's facing and\
- --which way he needs to go\
- local temppfx,temppfz = getLeft(pfx,pfz)\
- if temppfz == rowinc and rows ~= rowtop then\
- sendPC(\"TL\")\
- sendPC(\"FW\")\
- sendPC(\"TL\")\
- elseif temppfz == -rowinc and rows ~= rowtop then\
- sendPC(\"TR\")\
- sendPC(\"FW\")\
- sendPC(\"TR\")\
- end\
- end\
- --Now at the end of a run he does a 180 and moves up to begin the next part of the print\
- sendPC(\"TU\")\
- if layers ~= #frames then\
- sendPC(\"UP\")\
- end\
- end\
- --All done- now we head back to where we started.\
- if px ~= leflim then\
- turnToFace(-1,0)\
- while px ~= leflim do\
- sendPC(\"FW\")\
- end\
- end\
- if pz ~= botlim then\
- turnToFace(0,-1)\
- while pz ~= botlim do\
- sendPC(\"BK\")\
- end\
- end\
- turnToFace(0,-1)\
- sendPC(\"BK\")\
- while py > 0 do\
- sendPC(\"DW\")\
- end\
- else\
- --The front facing is at the top-left corner, facing south not north\
- px,py,pz = leflim, botlim, 1\
- pfx,pfz = 0,1\
- --We move the printer to the last layer- he prints from the back forwards\
- while pz < #frames do\
- sendPC(\"FW\")\
- end\
- \
- --For each layer in the frame we build our wall, the move back\
- for layers = 1,#frames do\
- --We first decide if we're going left or right based on our position\
- local rowbot,rowtop,rowinc = nil,nil,nil\
- if px == leflim then\
- rowbot,rowtop,rowinc = leflim,riglim,1\
- else\
- rowbot,rowtop,rowinc = riglim,leflim,-1\
- end\
- \
- for rows = rowbot,rowtop,rowinc do\
- --Then we decide if we're going up or down, depending on our given altitude\
- local linebot,linetop,lineinc = nil,nil,nil\
- if py == botlim then\
- linebot,linetop,lineinc = botlim,toplim,-1\
- else\
- linebot,linetop,lineinc = toplim,botlim,1\
- end\
- \
- for lines = linebot,linetop,lineinc do\
- --We move our turtle up/down, placing the right material at each step\
- local material = frames[pz][py][px]\
- if material then\
- material = math.log10(frames[pz][py][px])/math.log10(2) + 1\
- sendPC(\"SS\", material)\
- sendPC(\"PF\")\
- end\
- if lines ~= linetop then\
- if lineinc == 1 then sendPC(\"DW\")\
- else sendPC(\"UP\") end\
- end\
- end\
- \
- if rows ~= rowtop then\
- turnToFace(rowinc,0)\
- sendPC(\"FW\")\
- turnToFace(0,1)\
- end\
- end\
- \
- if layers ~= #frames then\
- sendPC(\"TU\")\
- sendPC(\"FW\")\
- sendPC(\"TU\")\
- end\
- end\
- --He's easy to reset\
- while px ~= leflim do\
- turnToFace(-1,0)\
- sendPC(\"FW\")\
- end\
- turnToFace(0,1)\
- end\
- \
- sendPC(\"DE\")\
- \
- displayConfirmDialogue(\"Print complete\", \"The 3D print was successful.\")\
- end\
- \
- --[[ \
- Section: Interface \
- ]]--\
- \
- --[[Runs the printing interface. Allows users to find/select a printer, the style of printing to perform and to begin the operation\
- Params: none\
- Returns:boolean true if printing was started, false otherwse\
- ]]--\
- local function runPrintInterface()\
- calculateMaterials()\
- --There's nothing on canvas yet!\
- if not botlim then\
- displayConfirmDialogue(\"Cannot Print Empty Canvas\", \"There is nothing on canvas that \"..\
- \"can be printed, and the operation cannot be completed.\")\
- return false\
- end\
- --No printers nearby\
- if not locatePrinters() then\
- return false\
- end\
- \
- layering = \"up\"\
- requirementsDisplayed = false\
- selectedPrinter = 1\
- while true do\
- drawCanvas()\
- term.setBackgroundColour(colours.lightGrey)\
- for i=1,10 do\
- term.setCursorPos(1,i)\
- term.clearLine()\
- end\
- drawInterface()\
- term.setBackgroundColour(colours.lightGrey)\
- term.setTextColour(colours.black)\
- \
- local msg = \"3D Printing\"\
- term.setCursorPos(w/2-#msg/2 - 2, 1)\
- term.write(msg)\
- term.setBackgroundColour(colours.grey)\
- term.setTextColour(colours.lightGrey)\
- if(requirementsDisplayed) then\
- msg = \"Count:\"\
- else\
- msg = \" Slot:\"\
- end\
- term.setCursorPos(w-3-#msg, 1)\
- term.write(msg)\
- term.setBackgroundColour(colours.lightGrey)\
- term.setTextColour(colours.black)\
- \
- term.setCursorPos(7, 2)\
- term.write(\"Layering\")\
- drawPictureTable(layerUpIcon, 3, 3, colours.white)\
- drawPictureTable(layerForwardIcon, 12, 3, colours.white)\
- if layering == \"up\" then\
- term.setBackgroundColour(colours.red)\
- else\
- term.setBackgroundColour(colours.lightGrey)\
- end\
- term.setCursorPos(3, 9)\
- term.write(\"Upwards\")\
- if layering == \"forward\" then\
- term.setBackgroundColour(colours.red)\
- else\
- term.setBackgroundColour(colours.lightGrey)\
- end\
- term.setCursorPos(12, 9)\
- term.write(\"Forward\")\
- \
- term.setBackgroundColour(colours.lightGrey)\
- term.setTextColour(colours.black)\
- term.setCursorPos(31, 2)\
- term.write(\"Printer ID\")\
- term.setCursorPos(33, 3)\
- if #printerList > 1 then\
- term.setBackgroundColour(colours.grey)\
- term.setTextColour(colours.lightGrey)\
- else\
- term.setTextColour(colours.red)\
- end\
- term.write(\" \"..printerNames[selectedPrinter]..\" \")\
- \
- term.setBackgroundColour(colours.grey)\
- term.setTextColour(colours.lightGrey)\
- term.setCursorPos(25, 10)\
- term.write(\" Cancel \")\
- term.setCursorPos(40, 10)\
- term.write(\" Print \")\
- \
- local id, p1, p2, p3 = os.pullEvent()\
- \
- if id == \"timer\" then\
- updateTimer(p1)\
- elseif id == \"mouse_click\" then\
- --Layering Buttons\
- if p2 >= 3 and p2 <= 9 and p3 >= 3 and p3 <= 9 then\
- layering = \"up\"\
- elseif p2 >= 12 and p2 <= 18 and p3 >= 3 and p3 <= 9 then\
- layering = \"forward\"\
- --Count/Slot\
- elseif p2 >= w - #msg - 3 and p2 <= w - 3 and p3 == 1 then\
- requirementsDisplayed = not requirementsDisplayed\
- --Printer ID\
- elseif p2 >= 33 and p2 <= 33 + #printerNames[selectedPrinter] and p3 == 3 and #printerList > 1 then\
- local chosenName = displayDropDown(33, 3, printerNames)\
- for i=1,#printerNames do\
- if printerNames[i] == chosenName then\
- selectedPrinter = i\
- break;\
- end\
- end\
- --Print and Cancel\
- elseif p2 >= 25 and p2 <= 32 and p3 == 10 then\
- break\
- elseif p2 >= 40 and p2 <= 46 and p3 == 10 then\
- rednet.send(printerList[selectedPrinter], \"$3DPRINT ACTIVATE\")\
- ready = false\
- while true do\
- local id,msg = rsTimeReceive(10)\
- \
- if id == printerList[selectedPrinter] and msg == \"$3DPRINT ACTACK\" then\
- ready = true\
- break\
- end\
- end\
- if ready then\
- performPrint()\
- break\
- else\
- displayConfirmDialogue(\"Printer Didn't Respond\", \"The printer didn't respond to the activation command. Check to see if it's online\")\
- end\
- end\
- end\
- end\
- state = \"paint\"\
- end\
- \
- --[[Performs a legacy save. When the dropdown menu is unavailable, it requests the user to save\
- \009or exit using keyboard shortcuts rather than selecting a menu option from the dropdown.\
- \009Pressing the control key again will cancel the save operation.\
- \009Params: none\
- \009Returns:string = the selection made\
- ]]--\
- local function performLegacySaveExit()\
- \009local saveMsg = \"(S)ave/(E)xit?\"\
- \009if w < #saveMsg then saveMsg = \"S/E?\" end\
- \009\
- \009term.setCursorPos(1,h)\
- \009term.setBackgroundColour(colours.lightGrey)\
- \009term.setTextColour(colours.grey)\
- \009term.clearLine()\
- \009term.write(saveMsg)\
- \009\
- \009while true do\
- \009\009local id,val = os.pullEvent()\
- \009\009if id == \"timer\" then updateTimer(val)\
- \009\009elseif id == \"key\" then\
- \009\009\009if val == keys.s then return \"save\" \
- \009\009\009elseif val == keys.e then\
- \009\009\009\009--Get rid of the extra event\
- \009\009\009\009os.pullEvent(\"char\")\
- \009\009\009\009return \"exit\"\
- \009\009\009elseif val == keys.leftCtrl then return nil\
- \009\009\009end\
- \009\009end\
- \009end\
- end\
- \
- --[[This function changes the current paint program to another tool or mode, depending on user input. Handles\
- any necessary changes in logic involved in that.\
- Params: mode:string = the name of the mode to change to\
- Returns:nil\
- ]]--\
- local function performSelection(mode)\
- if not mode or mode == \"\" then return\
- \
- elseif mode == \"help\" and helpAvailable then\
- drawHelpScreen()\
- \
- elseif mode == \"blueprint on\" then\
- blueprint = true\
- \009\009\009\009for i=1,#ddModes[2] do if ddModes[2][i] == \"blueprint on\" then\
- \009\009\009\009\009ddModes[2][i] = \"blueprint off\"\
- \009\009\009\009end end\
- \
- elseif mode == \"blueprint off\" then\
- blueprint = false\
- \009\009\009\009for i=1,#ddModes[2] do if ddModes[2][i] == \"blueprint off\" then\
- \009\009\009\009\009ddModes[2][i] = \"blueprint on\"\
- \009\009\009\009end end\
- \
- elseif mode == \"layers on\" then\
- layerDisplay = true\
- \009\009\009\009for i=1,#ddModes[2] do if ddModes[2][i] == \"layers on\" then\
- \009\009\009\009\009ddModes[2][i] = \"layers off\"\
- \009\009\009\009end end\
- \
- elseif mode == \"layers off\" then\
- layerDisplay = false\
- \009\009\009\009for i=1,#ddModes[2] do if ddModes[2][i] == \"layers off\" then\
- \009\009\009\009\009ddModes[2][i] = \"layers on\"\
- \009\009\009\009end end\
- \
- elseif mode == \"direction on\" then\
- printDirection = true\
- \009\009\009\009for i=1,#ddModes[2] do if ddModes[2][i] == \"direction on\" then\
- \009\009\009\009\009ddModes[2][i] = \"direction off\"\
- \009\009\009\009end end\
- \
- elseif mode == \"direction off\" then\
- printDirection = false\
- \009\009\009\009for i=1,#ddModes[2] do if ddModes[2][i] == \"direction off\" then\
- \009\009\009\009\009ddModes[2][i] = \"direction on\"\
- \009\009\009\009end end\
- \009\009\
- \009\009elseif mode == \"hide interface\" then\
- \009\009\009\009interfaceHidden = true\
- \009\009\009\
- \009\009elseif mode == \"show interface\" then\
- \009\009\009\009interfaceHidden = false\
- \
- elseif mode == \"go to\" then\
- changeFrame()\
- \
- elseif mode == \"remove\" then\
- removeFramesAfter(sFrame)\
- \
- elseif mode == \"play\" then\
- playAnimation()\
- \
- elseif mode == \"copy\" then\
- if selectrect and selectrect.x1 ~= selectrect.x2 then\
- copyToBuffer(false)\
- end\
- \
- elseif mode == \"cut\" then\
- if selectrect and selectrect.x1 ~= selectrect.x2 then\
- copyToBuffer(true)\
- end\
- \
- elseif mode == \"paste\" then\
- if selectrect and selectrect.x1 ~= selectrect.x2 then\
- copyFromBuffer(false)\
- end\
- \
- elseif mode == \"hide\" then\
- selectrect = nil\
- if state == \"select\" then state = \"corner select\" end\
- \009\009\009 \
- elseif mode == \"alpha to left\" then\
- if lSel then alphaC = lSel end\
- \
- elseif mode == \"alpha to right\" then\
- if rSel then alphaC = rSel end\
- \
- elseif mode == \"record\" then\
- record = not record\
- \
- elseif mode == \"clear\" then\
- if state==\"select\" then buffer = nil\
- else clearImage() end\
- \
- elseif mode == \"select\" then\
- if state==\"corner select\" or state==\"select\" then\
- state = \"paint\"\
- elseif selectrect and selectrect.x1 ~= selectrect.x2 then\
- state = \"select\"\
- else\
- state = \"corner select\"\
- end\
- \
- elseif mode == \"print\" then\
- state = \"print\"\
- runPrintInterface()\
- state = \"paint\"\
- \
- elseif mode == \"save\" then\
- if animated then saveNFA(sPath)\
- elseif textEnabled then saveNFT(sPath)\
- else saveNFP(sPath) end\
- \
- elseif mode == \"exit\" then\
- isRunning = false\
- \
- elseif mode ~= state then state = mode\
- else state = \"paint\"\
- end\
- end\
- \
- --[[The main function of the program, reads and handles all events and updates them accordingly. Mode changes,\
- painting to the canvas and general selections are done here.\
- Params: none\
- Returns:nil\
- ]]--\
- local function handleEvents()\
- recttimer = os.startTimer(0.5)\
- while isRunning do\
- drawCanvas()\
- if not interfaceHidden then drawInterface() end\
- \
- if state == \"text\" then\
- term.setCursorPos(textCurX - sx, textCurY - sy)\
- term.setCursorBlink(true)\
- end\
- \
- local id,p1,p2,p3 = os.pullEvent()\
- term.setCursorBlink(false)\
- if id==\"timer\" then\
- updateTimer(p1)\
- elseif (id==\"mouse_click\" or id==\"mouse_drag\") and not interfaceHidden then\
- if p2 >=w-1 and p3 < #column+1 then\
- \009\009\009\009\009\009\009\009local off = 0\
- \009\009\009\009\009\009\009\009local cansel = true\
- \009\009\009\009\009\009\009\009if h < #column + 2 then\
- \009\009\009\009\009\009\009\009\009if p3 == 1 then \
- \009\009\009\009\009\009\009\009\009\009if columnoffset > 0 then columnoffset = columnoffset-1 end\
- \009\009\009\009\009\009\009\009\009\009cansel = false\
- \009\009\009\009\009\009\009\009\009elseif p3 == h-2 then\
- \009\009\009\009\009\009\009\009\009\009if columnoffset < #column-(h-4)+1 then columnoffset = columnoffset+1 end\
- \009\009\009\009\009\009\009\009\009\009cansel = false\
- \009\009\009\009\009\009\009\009\009else\
- \009\009\009\009\009\009\009\009\009\009off = columnoffset - 1\
- \009\009\009\009\009\009\009\009\009end\
- \009\009\009\009\009\009\009\009end\
- \009\009\009\009\009\009\009\009--This rather handily accounts for the nil case (p3+off=#column+1)\
- \009\009\009\009\009\009\009\009if p1==1 and cansel then lSel = column[p3+off]\
- elseif p1==2 and cansel then rSel = column[p3+off] end\
- elseif p2 >=w-1 and p3==#column+1 then\
- if p1==1 then lSel = nil\
- else rSel = nil end\
- elseif p2==w-1 and p3==h and animated then\
- changeFrame(sFrame-1)\
- elseif p2==w and p3==h and animated then\
- changeFrame(sFrame+1)\
- elseif p2 <= #ddModes.name + 2 and p3==h and mainAvailable then\
- local sel = displayDropDown(1, h-1, ddModes)\
- performSelection(sel)\
- elseif p2 < w-1 and p3 <= h-1 then\
- if state==\"pippette\" then\
- if p1==1 then\
- if frames[sFrame][p3+sy] and frames[sFrame][p3+sy][p2+sx] then\
- lSel = frames[sFrame][p3+sy][p2+sx]\
- end\
- elseif p1==2 then\
- if frames[sFrame][p3+sy] and frames[sFrame][p3+sy][p2+sx] then\
- rSel = frames[sFrame][p3+sy][p2+sx]\
- end\
- end\
- elseif state==\"move\" then\
- updateImageLims(record)\
- moveImage(p2,p3)\
- elseif state==\"flood\" then\
- if p1 == 1 and lSel and frames[sFrame][p3+sy] then\
- floodFill(p2,p3,frames[sFrame][p3+sy][p2+sx],lSel)\
- elseif p1 == 2 and rSel and frames[sFrame][p3+sy] then\
- floodFill(p2,p3,frames[sFrame][p3+sy][p2+sx],rSel)\
- end\
- elseif state==\"corner select\" then\
- if not selectrect then\
- selectrect = { x1=p2+sx, x2=p2+sx, y1=p3+sy, y2=p3+sy }\
- elseif selectrect.x1 ~= p2+sx and selectrect.y1 ~= p3+sy then\
- if p2+sx<selectrect.x1 then selectrect.x1 = p2+sx\
- else selectrect.x2 = p2+sx end\
- \
- if p3+sy<selectrect.y1 then selectrect.y1 = p3+sy\
- else selectrect.y2 = p3+sy end\
- \
- state = \"select\"\
- end\
- elseif state==\"textpaint\" then\
- local paintCol = lSel\
- if p1 == 2 then paintCol = rSel end\
- if frames[sFrame].textcol[p3+sy] then\
- frames[sFrame].textcol[p3+sy][p2+sx] = paintCol\
- end\
- elseif state==\"text\" then\
- textCurX = p2 + sx\
- textCurY = p3 + sy\
- elseif state==\"select\" then\
- if p1 == 1 then\
- local swidth = selectrect.x2 - selectrect.x1\
- local sheight = selectrect.y2 - selectrect.y1\
- \
- selectrect.x1 = p2 + sx\
- selectrect.y1 = p3 + sy\
- selectrect.x2 = p2 + swidth + sx\
- selectrect.y2 = p3 + sheight + sy\
- elseif p1 == 2 and p2 < w-2 and p3 < h-1 and boxdropAvailable then\
- inMenu = true\
- local sel = displayDropDown(p2, p3, srModes)\
- inMenu = false\
- performSelection(sel)\
- end\
- else\
- local f,l = sFrame,sFrame\
- if record then f,l = 1,framecount end\
- local bwidth = 0\
- if state == \"brush\" then bwidth = brushsize-1 end\
- \
- for i=f,l do\
- for x = math.max(1,p2+sx-bwidth),p2+sx+bwidth do\
- for y = math.max(1,p3+sy-bwidth), p3+sy+bwidth do\
- if math.abs(x - (p2+sx)) + math.abs(y - (p3+sy)) <= bwidth then\
- if not frames[i][y] then frames[i][y] = {} end\
- if p1==1 then frames[i][y][x] = lSel\
- else frames[i][y][x] = rSel end\
- \
- if textEnabled then\
- if not frames[i].text[y] then frames[i].text[y] = { } end\
- if not frames[i].textcol[y] then frames[i].textcol[y] = { } end\
- end\
- end\
- end\
- end\
- end\
- end\
- end\
- elseif id==\"char\" then\
- if state==\"text\" then\
- if not frames[sFrame][textCurY] then frames[sFrame][textCurY] = { } end\
- if not frames[sFrame].text[textCurY] then frames[sFrame].text[textCurY] = { } end\
- if not frames[sFrame].textcol[textCurY] then frames[sFrame].textcol[textCurY] = { } end\
- \
- if rSel then frames[sFrame][textCurY][textCurX] = rSel end\
- if lSel then\
- frames[sFrame].text[textCurY][textCurX] = p1\
- frames[sFrame].textcol[textCurY][textCurX] = lSel\
- else\
- frames[sFrame].text[textCurY][textCurX] = \" \"\
- frames[sFrame].textcol[textCurY][textCurX] = rSel\
- end\
- \
- textCurX = textCurX+1\
- if textCurX > w + sx - 2 then sx = textCurX - w + 2 end\
- elseif tonumber(p1) then\
- if state==\"brush\" and tonumber(p1) > 1 then\
- brushsize = tonumber(p1)\
- elseif animated and tonumber(p1) > 0 then\
- changeFrame(tonumber(p1))\
- end\
- end\
- elseif id==\"key\" then\
- \009\009\009\009\009\009--All standard interface methods are locked when the interface is hidden\
- \009\009\009\009\009\009if interfaceHidden then\
- \009\009\009\009\009\009\009if p1==keys.grave then\
- \009\009\009\009\009\009\009\009performSelection(\"show interface\") \
- \009\009\009\009\009\009\009end\
- --Text needs special handlers (all other keyboard shortcuts are of course reserved for typing)\
- elseif state==\"text\" then\
- if p1==keys.backspace and textCurX > 1 then\
- textCurX = textCurX-1\
- if frames[sFrame].text[textCurY] then\
- frames[sFrame].text[textCurY][textCurX] = nil\
- frames[sFrame].textcol[textCurY][textCurX] = nil\
- end\
- if textCurX < sx then sx = textCurX end\
- elseif p1==keys.left and textCurX > 1 then\
- textCurX = textCurX-1\
- if textCurX-1 < sx then sx = textCurX-1 end\
- elseif p1==keys.right then\
- textCurX = textCurX+1\
- if textCurX > w + sx - 2 then sx = textCurX - w + 2 end\
- elseif p1==keys.up and textCurY > 1 then\
- textCurY = textCurY-1\
- if textCurY-1 < sy then sy = textCurY-1 end\
- elseif p1==keys.down then\
- textCurY = textCurY+1\
- if textCurY > h + sy - 1 then sy = textCurY - h + 1 end\
- end\
- \
- elseif p1==keys.leftCtrl then\
- local sel = nil\
- \009\009\009\009\009\009\009\009if mainAvailable then \
- \009\009\009\009\009\009\009\009\009sel = displayDropDown(1, h-1, ddModes[#ddModes])\
- \009\009\009\009\009\009\009\009else sel = performLegacySaveExit() end\
- performSelection(sel)\
- elseif p1==keys.leftAlt then\
- local sel = displayDropDown(1, h-1, ddModes[1])\
- performSelection(sel)\
- elseif p1==keys.h then\
- performSelection(\"help\")\
- elseif p1==keys.x then\
- performSelection(\"cut\")\
- elseif p1==keys.c then\
- performSelection(\"copy\")\
- elseif p1==keys.v then\
- performSelection(\"paste\")\
- elseif p1==keys.z then\
- performSelection(\"clear\")\
- elseif p1==keys.s then\
- performSelection(\"select\")\
- elseif p1==keys.tab then\
- performSelection(\"hide\")\
- elseif p1==keys.q then\
- performSelection(\"alpha to left\")\
- elseif p1==keys.w then\
- performSelection(\"alpha to right\")\
- elseif p1==keys.f then\
- performSelection(\"flood\")\
- elseif p1==keys.b then\
- performSelection(\"brush\")\
- elseif p1==keys.m then\
- performSelection(\"move\")\
- elseif p1==keys.backslash and animated then\
- performSelection(\"record\")\
- elseif p1==keys.p then\
- performSelection(\"pippette\")\
- elseif p1==keys.g and animated then\
- performSelection(\"go to\")\
- \009\009\009\009\009\009elseif p1==keys.grave then \
- \009\009\009\009\009\009\009\009performSelection(\"hide interface\")\
- elseif p1==keys.period and animated then\
- changeFrame(sFrame+1)\
- elseif p1==keys.comma and animated then\
- changeFrame(sFrame-1)\
- elseif p1==keys.r and animated then\
- performSelection(\"remove\")\
- elseif p1==keys.space and animated then\
- performSelection(\"play\")\
- elseif p1==keys.t and textEnabled then\
- performSelection(\"text\")\
- sleep(0.01)\
- elseif p1==keys.y and textEnabled then\
- performSelection(\"textpaint\")\
- elseif p1==keys.left then\
- if state == \"move\" and toplim then\
- updateImageLims(record)\
- if toplim and leflim then\
- moveImage(leflim-1,toplim)\
- end\
- elseif state==\"select\" and selectrect.x1 > 1 then\
- selectrect.x1 = selectrect.x1-1\
- selectrect.x2 = selectrect.x2-1\
- elseif sx > 0 then sx=sx-1 end\
- elseif p1==keys.right then\
- if state == \"move\" then\
- updateImageLims(record)\
- if toplim and leflim then\
- moveImage(leflim+1,toplim)\
- end\
- elseif state==\"select\" then\
- selectrect.x1 = selectrect.x1+1\
- selectrect.x2 = selectrect.x2+1\
- else sx=sx+1 end\
- elseif p1==keys.up then\
- if state == \"move\" then\
- updateImageLims(record)\
- if toplim and leflim then\
- moveImage(leflim,toplim-1)\
- end\
- elseif state==\"select\" and selectrect.y1 > 1 then\
- selectrect.y1 = selectrect.y1-1\
- selectrect.y2 = selectrect.y2-1\
- elseif sy > 0 then sy=sy-1 end\
- elseif p1==keys.down then\
- if state == \"move\" then\
- updateImageLims(record)\
- if toplim and leflim then\
- moveImage(leflim,toplim+1)\
- end\
- elseif state==\"select\" then\
- selectrect.y1 = selectrect.y1+1\
- selectrect.y2 = selectrect.y2+1\
- else sy=sy+1 end\
- end\
- end\
- end\
- end\
- \
- --[[\
- Section: Main \
- ]]--\
- \
- --The first thing done is deciding what features we actually have, given the screen size\
- if w < 7 or h < 4 then\
- \009--NPaintPro simply doesn't work at certain configurations\
- \009shell.run(\"clear\")\
- \009print(\"Screen too small\")\
- \009os.pullEvent(\"key\")\
- \009return\
- end\
- --And reduces the number of features in others.\
- determineAvailableServices()\
- \
- --There is no b&w support for NPP.\
- if not term.isColour() then\
- \009shell.run(\"clear\")\
- \009print(\"NPaintPro\\nBy NitrogenFingers\\n\\nNPaintPro can only be run on advanced \"..\
- \009\"computers. Please reinstall on an advanced computer.\")\
- return\
- end\
- \
- --Taken almost directly from edit (for consistency)\
- local tArgs = {...}\
- \
- --Command line options can appear before the file path to specify the file format\
- local ca = 1\
- while ca <= #tArgs do\
- \009if tArgs[ca] == \"-a\" then animated = true\
- \009elseif tArgs[ca] == \"-t\" then textEnabled = true\
- \009elseif tArgs[ca] == \"-d\" then interfaceHidden = true\
- \009elseif string.sub(tArgs[ca], 1, 1) == \"-\" then\
- \009\009print(\"Unrecognized option: \"..tArgs[ca])\
- \009\009return\
- \009else break end\
- \009ca = ca + 1\
- end\
- \
- --Presently, animations and text files are not supported\
- if animated and textEnabled then\
- print(\"No support for animated text files- cannot have both -a and -t\")\
- \009return\
- end\
- \
- --Filepaths must be added if the screen is too small\
- if #tArgs < ca then\
- \009if not filemakerAvailable then\
- \009\009print(\"Usage: npaintpro [-a,-t,-d] <path>\")\
- \009\009return\
- \009else\
- \009\009--Otherwise do the logo draw early, to determine the file.\
- \009\009drawLogo()\
- \009\009if not runFileMaker() then return end\
- \009end\
- else\
- \009if not interfaceHidden then drawLogo() end\
- \009sPath = shell.resolve(tArgs[ca])\
- end\
- \
- if fs.exists(sPath) then\
- if fs.isDir(sPath) then\
- print(\"Cannot edit a directory.\")\
- return\
- elseif string.find(sPath, \".nfp\") ~= #sPath-3 and string.find(sPath, \".nfa\") ~= #sPath-3 and\
- string.find(sPath, \".nft\") ~= #sPath-3 then\
- print(\"Can only edit .nfp, .nft and .nfa files:\",string.find(sPath, \".nfp\"),#sPath-3)\
- return\
- end\
- \
- if string.find(sPath, \".nfa\") == #sPath-3 then\
- animated = true\
- end\
- \
- if string.find(sPath, \".nft\") == #sPath-3 then\
- textEnabled = true\
- end \
- \
- if string.find(sPath, \".nfp\") == #sPath-3 and animated then\
- print(\"Convert to nfa? Y/N\")\
- if string.find(string.lower(io.read()), \"y\") then\
- local nsPath = string.sub(sPath, 1, #sPath-1)..\"a\"\
- fs.move(sPath, nsPath)\
- sPath = nsPath\
- else\
- animated = false\
- end\
- end\
- \
- --Again this is possible, I just haven't done it. Maybe I will?\
- if textEnabled and (string.find(sPath, \".nfp\") == #sPath-3 or string.find(sPath, \".nfa\") == #sPath-3) then\
- print(\"Cannot convert to nft\")\
- end\
- else\
- if not animated and not textEnabled and string.find(sPath, \".nfp\") ~= #sPath-3 then\
- sPath = sPath..\".nfp\"\
- elseif animated and string.find(sPath, \".nfa\") ~= #sPath-3 then\
- sPath = sPath..\".nfa\"\
- elseif textEnabled and string.find(sPath, \".nft\") ~= #sPath-3 then\
- sPath = sPath..\".nft\"\
- end\
- end\
- \
- init()\
- handleEvents()\
- \
- term.setBackgroundColour(colours.black)\
- shell.run(\"clear\")",
- "7777777777777777777777777\
- 7ccccccccccccccccccccccc7\
- 7ccccccccccccccccccccccc7\
- 7ccccccccccccccccccccccc7\
- 7ccccccccccccccccccccccc7\
- 7ccccccccccccccccccccccc7\
- 7ccccccccccccccccccccccc7\
- 7ccccccccccccccccccccccc7\
- 7777777777777777777777777",
- "{\
- blocksY = {\
- 9,\
- 9,\
- 9,\
- 9,\
- 9,\
- 9,\
- 9,\
- 9,\
- 9,\
- 8,\
- 7,\
- 5,\
- 6,\
- 4,\
- 3,\
- 2,\
- 1,\
- 1,\
- 1,\
- 1,\
- 1,\
- 1,\
- 1,\
- 1,\
- 1,\
- 1,\
- 1,\
- 1,\
- 1,\
- 9,\
- 9,\
- 9,\
- 9,\
- 9,\
- 9,\
- 9,\
- 9,\
- 9,\
- 9,\
- 9,\
- 9,\
- 9,\
- 9,\
- 9,\
- 9,\
- 9,\
- 8,\
- 7,\
- 6,\
- 5,\
- 3,\
- 4,\
- 2,\
- 1,\
- 1,\
- 1,\
- 1,\
- 1,\
- 1,\
- 1,\
- 1,\
- 1,\
- 1,\
- 1,\
- 1,\
- },\
- blocksX = {\
- 1,\
- 2,\
- 3,\
- 4,\
- 6,\
- 5,\
- 7,\
- 9,\
- 8,\
- 1,\
- 1,\
- 1,\
- 1,\
- 1,\
- 1,\
- 1,\
- 1,\
- 2,\
- 3,\
- 4,\
- 6,\
- 7,\
- 5,\
- 8,\
- 9,\
- 11,\
- 12,\
- 10,\
- 13,\
- 10,\
- 11,\
- 13,\
- 12,\
- 14,\
- 16,\
- 15,\
- 17,\
- 18,\
- 20,\
- 21,\
- 19,\
- 22,\
- 24,\
- 25,\
- 22,\
- 23,\
- 25,\
- 25,\
- 25,\
- 25,\
- 25,\
- 25,\
- 25,\
- 25,\
- 24,\
- 23,\
- 22,\
- 21,\
- 20,\
- 19,\
- 18,\
- 17,\
- 16,\
- 15,\
- 14,\
- },\
- doorsX = {},\
- spawnY = 1,\
- spawnX = 1,\
- laddersX = {\
- 7,\
- },\
- doorsY = {},\
- laddersY = {\
- 8,\
- },\
- ladderDestination = {\
- \"house2\",\
- },\
- }",
- "--Editor (yaay make your own levels based on this \"engine\")\
- --Again, written by me c:\
- --(I know, I'm shit at programming but hey why not C:)\
- \
- --Variablen\
- _ver = 0.1\
- _verstr = \"0.1\"\
- pfad = \"\"\
- \
- lvlData = {\
- \009spawnPosX=\"1\",\
- \009spawnPosY=\"1\",\
- \009blocksX = {\
- \
- \009},\
- \009blocksY = {\
- \
- \009}\
- }\
- \
- --Funktionen\
- function clear(bg, fg)\
- \009term.setCursorPos(1,1)\
- \009term.setBackgroundColor(bg)\
- \009term.setTextColor(fg)\
- \009term.clear()\
- end\
- \
- function menu()\
- \009clear(colors.black, colors.white)\
- \009term.setBackgroundColor(colors.lime)\
- \009term.setCursorPos(25, 6)\
- \009term.write(\"NEW\")\
- \009term.setCursorPos(24, 8)\
- \009term.write(\"LOAD\")\
- \009term.setCursorPos(24, 10)\
- \009term.write(\"EXIT\")\
- \009menu = true\
- \009while menu do\
- \009\009local event, button, x, y = os.pullEventRaw(\"mouse_click\")\
- \009\009if button == 1 and x >= 25 and x <= 27 and y == 6 then\
- \009\009\009menu = false\
- \009\009\009menu2()\
- \009\009end\
- \009end\
- end\
- \
- function menu2()\
- \009clear(colors.black, colors.white)\
- \009oldTerm = term.native()\
- \009local graywindow = window.create(oldTerm, 15, 5, 20, 5)\
- \009term.redirect(graywindow)\
- \009term.setBackgroundColor(colors.lightGray)\
- \009term.setCursorPos(1,1)\
- \009term.clear()\
- \009local textBox = window.create(term.current(), 2, 2, 18, 1)\
- \009textBox.setBackgroundColor(colors.gray)\
- \009textBox.setTextColor(colors.lime)\
- \009textBox.clear()\
- \009textBox.write(\"Enter Name/Desti..\")\
- \009term.setBackgroundColor(colors.gray)\
- \009term.setTextColor(colors.white)\
- \009term.setCursorPos(2, 4)\
- \009term.write(\"New\")\
- \009term.setCursorPos(16, 4)\
- \009term.write(\"Load\")\
- \009menu = true\
- \009while menu do\
- \009\009local event, button, x, y = os.pullEvent(\"mouse_click\")\
- \009\009if button == 1 and x >= 16 and x <= 34 and y == 6 then\
- \009\009\009term.redirect(textBox)\
- \009\009\009term.clear()\
- \009\009\009term.setCursorPos(1,1)\
- \009\009\009local eingabe = read()\
- \009\009\009pfad = eingabe\
- \009\009\009term.setCursorPos(1,1)\
- \009\009\009term.clear()\
- \009\009\009term.write(eingabe)\
- \009\009\009term.redirect(graywindow)\
- \009\009elseif button == 1 and x >= 16 and x <= 18 and y == 8 then\
- \009\009\009if fs.exists(pfad..\".lvl\") then\
- \009\009\009\009textBox.setCursorPos(1,1)\
- \009\009\009\009textBox.clear()\
- \009\009\009\009textBox.setTextColor(colors.red)\
- \009\009\009\009textBox.write(\"Already exists.\")\
- \009\009\009\009textBox.setTextColor(colors.lime)\
- \009\009\009elseif pfad == \"\" or pfad == nil then\
- \009\009\009\009textBox.setCursorPos(1,1)\
- \009\009\009\009textBox.clear()\
- \009\009\009\009textBox.setTextColor(colors.red)\
- \009\009\009\009textBox.write(\"Please fill in.\")\
- \009\009\009\009textBox.setTextColor(colors.lime)\
- \009\009\009else\
- \009\009\009\009term.redirect(oldTerm)\
- \009\009\009\009term.setCursorPos(1,1)\
- \009\009\009\009clear(colors.black, colors.white)\
- \009\009\009\009menu = false\
- \009\009\009\009print(\"Please draw your LevelDESIGN.\")\
- \009\009\009\009print(\"This will be that, what you see when playing the level.\")\
- \009\009\009\009sleep(3)\
- \009\009\009\009shell.run(\"paint \"..pfad..\".lvl\")\
- \009\009\009\009\
- \009\009\009\009editor()\
- \009\009\009end\
- \009\009elseif button == 1 and x >= 30 and x <= 34 and y == 8 then\
- \009\009\009if fs.exists(pfad..\".lvl\") and fs.exists(pfad..\".lvlDat\") then\
- \009\009\009\009term.redirect(oldTerm)\
- \009\009\009\009menu = false\
- \009\009\009\009editor(\"true\")\
- \009\009\009elseif fs.exists(pfad..\".lvl\") then\
- \009\009\009\009term.redirect(oldTerm)\
- \009\009\009\009menu = false\
- \009\009\009\009editor(\"false\")\
- \009\009\009else\
- \009\009\009\009textBox.setCursorPos(1,1)\
- \009\009\009\009textBox.clear()\
- \009\009\009\009textBox.setTextColor(colors.red)\
- \009\009\009\009textBox.write(\"Doesn't exist.\")\
- \009\009\009\009textBox.setTextColor(colors.lime)\
- \009\009\009end\
- \009\009end\
- \009end\
- \
- end\
- \
- function loadDat()\
- \009local file = fs.open(pfad..\".lvlDat\",\"r\")\
- \009local inhalt = file.readAll()\
- \009lvlData = textutils.unserialize(inhalt)\
- \009file.close()\
- end\
- \
- function editor(loadData)\
- \009clear(colors.black, colors.white)\
- \009lvl = paintutils.loadImage(pfad..\".lvl\")\
- \009paintutils.drawImage(lvl, 1, 1)\
- \009if loadData == \"true\" then\
- \009\009loadDat()\
- \009\009reloadMap()\
- \009end\
- \009term.setCursorPos(1,19)\
- \009term.setBackgroundColor(colors.lightGray)\
- \009term.clearLine()\
- \009term.setBackgroundColor(colors.lime)\
- \009term.write(\" Block \")\
- \009term.setBackgroundColor(colors.lightGray)\
- \009term.write(\" \")\
- \009term.setBackgroundColor(colors.lime)\
- \009term.write(\" Spawn \")\
- \009term.setBackgroundColor(colors.lightGray)\
- \009term.write(\" \")\
- \009term.setBackgroundColor(colors.lime)\
- \009term.write(\" Remove \")\
- \009editing = true\
- \009while editing do\
- \009\009local event, button, x, y = os.pullEventRaw()\
- \009\009if event == \"mouse_click\" and button == 1 and x >= 1 and x <= 7 and y == 19 then\
- \009\009\009currentBlock = \"block\"\
- \009\009elseif event == \"mouse_click\" and button == 1 and x >= 9 and x <= 15 and y == 19 then\
- \009\009\009currentBlock = \"spawn\"\
- \009\009elseif event == \"mouse_click\" and button == 1 and x >= 17 and x <= 24 and y == 19 then\
- \009\009\009currentBlock = \"remove\"\
- \009\009elseif event == \"mouse_click\" and button == 1 and x >= 1 and x <= 51 and y >= 1 and y <= 18 then\
- \009\009\009if currentBlock == \"block\" then\
- \009\009\009\009term.setCursorPos(x, y)\
- \009\009\009\009term.setBackgroundColor(colors.brown)\
- \009\009\009\009term.setTextColor(colors.white)\
- \009\009\009\009term.write(\"B\")\
- \009\009\009\009local x = tostring(x)\
- \009\009\009\009local y = tostring(y)\
- \009\009\009\009table.insert(lvlData.blocksX, x)\
- \009\009\009\009table.insert(lvlData.blocksY, y)\
- \009\009\009\009reloadMap()\
- \009\009\009elseif currentBlock == \"spawn\" then\
- \009\009\009\009term.setCursorPos(x, y)\
- \009\009\009\009term.setBackgroundColor(colors.blue)\
- \009\009\009\009term.setTextColor(colors.white)\
- \009\009\009\009term.write(\"S\")\
- \009\009\009\009local x = tostring(x)\
- \009\009\009\009local y = tostring(y)\
- \009\009\009\009lvlData.spawnPosX = x\
- \009\009\009\009lvlData.spawnPosY = y\
- \009\009\009\009reloadMap()\
- \009\009\009elseif currentBlock == \"remove\" then\
- \009\009\009\009for _, block in ipairs(lvlData.blocksX) do\
- \009\009\009\009\009local blockY = tonumber(lvlData.blocksY[_])\
- \009\009\009\009\009local block = tonumber(block)\
- \009\009\009\009\009if x == block and y == blockY then\
- \009\009\009\009\009\009lvlData.blocksX[_] = nil\
- \009\009\009\009\009\009lvlData.blocksY[_] = nil\
- \009\009\009\009\009end\
- \009\009\009\009end\
- \009\009\009\009if x == lvlData.spawnPosX and y == lvlData.spawnPosY then\
- \009\009\009\009\009lvlData.spawnPosX = \"1\"\
- \009\009\009\009\009lvlData.spawnPosY = \"1\"\
- \009\009\009\009end\
- \009\009\009\009reloadMap()\
- \009\009\009end\
- \009\009elseif event == \"key\" and button == keys.s then\
- \009\009\009local file = fs.open(pfad..\".lvlDat\",\"w\")\
- \009\009\009local lvlData = textutils.serialize(lvlData)\
- \009\009\009file.write(lvlData)\
- \009\009\009file.close()\
- \009\009\009clear(colors.black, colors.white)\
- \
- \009\009\009editing = false\
- \009\009\009break\
- \009\009end\
- \
- \009end\
- end\
- \
- function reloadMap()\
- \009clear(colors.black, colors.white)\
- \009term.setCursorPos(1,19)\
- \009term.setBackgroundColor(colors.lightGray)\
- \009term.clearLine()\
- \009term.setBackgroundColor(colors.lime)\
- \009term.write(\" Block \")\
- \009term.setBackgroundColor(colors.lightGray)\
- \009term.write(\" \")\
- \009term.setBackgroundColor(colors.lime)\
- \009term.write(\" Spawn \")\
- \009term.setBackgroundColor(colors.lightGray)\
- \009term.write(\" \")\
- \009term.setBackgroundColor(colors.lime)\
- \009term.write(\" Remove \")\
- \009term.setCursorPos(1,1)\
- \009paintutils.drawImage(lvl, 1, 1)\
- \009for _, block in ipairs(lvlData.blocksX) do\
- \009\009local blockY = tonumber(lvlData.blocksY[_])\
- \009\009local block = tonumber(block)\
- \009\009term.setCursorPos(block, blockY)\
- \009\009term.setBackgroundColor(colors.brown)\
- \009\009term.setTextColor(colors.white)\
- \009\009term.write(\"B\")\
- \009end\
- \009local sX = tonumber(lvlData.spawnPosX)\
- \009local sY = tonumber(lvlData.spawnPosY)\
- \009term.setCursorPos(sX, sY)\
- \009term.setBackgroundColor(colors.blue)\
- \009term.setTextColor(colors.white)\
- \009term.write(\"S\")\
- end\
- \
- \
- \
- --Code\
- menu2()",
- "7777777777777777777777777\
- 7ccccccccccccccccccccccc7\
- 7ccccccccccccccccccccccc7\
- 7ccccccccccccccccccccccc7\
- 7ccccccccccccccccccccccc7\
- 7ccccccccccccccccccccccc7\
- 7ccccccccccccccccccccccc7\
- 7ccccccccccccccccccccccc7\
- 7777777777777777777777777",
- "{\
- blocksY = {\
- 9,\
- 9,\
- 9,\
- 9,\
- 9,\
- 9,\
- 9,\
- 9,\
- 9,\
- 9,\
- 9,\
- 9,\
- 9,\
- 9,\
- 9,\
- 9,\
- 9,\
- 9,\
- 9,\
- 9,\
- 9,\
- 9,\
- 9,\
- 9,\
- 9,\
- 8,\
- 7,\
- 6,\
- 5,\
- 4,\
- 3,\
- 2,\
- 1,\
- 1,\
- 1,\
- 1,\
- 1,\
- 1,\
- 1,\
- 1,\
- 1,\
- 1,\
- 1,\
- 1,\
- 1,\
- 1,\
- 1,\
- 1,\
- 1,\
- 1,\
- 1,\
- 1,\
- 1,\
- 1,\
- 1,\
- 1,\
- 1,\
- 2,\
- 3,\
- 4,\
- 5,\
- 6,\
- 8,\
- 7,\
- },\
- blocksX = {\
- 1,\
- 2,\
- 3,\
- 4,\
- 5,\
- 6,\
- 7,\
- 8,\
- 9,\
- 10,\
- 11,\
- 12,\
- 13,\
- 14,\
- 15,\
- 16,\
- 17,\
- 18,\
- 19,\
- 20,\
- 21,\
- 22,\
- 24,\
- 25,\
- 23,\
- 25,\
- 25,\
- 25,\
- 25,\
- 25,\
- 25,\
- 25,\
- 25,\
- 24,\
- 23,\
- 22,\
- 21,\
- 20,\
- 19,\
- 18,\
- 17,\
- 16,\
- 15,\
- 14,\
- 13,\
- 12,\
- 11,\
- 10,\
- 9,\
- 8,\
- 7,\
- 1,\
- 2,\
- 3,\
- 4,\
- 5,\
- 6,\
- 1,\
- 1,\
- 1,\
- 1,\
- 1,\
- 1,\
- 1,\
- },\
- doorsX = {},\
- spawnY = 1,\
- spawnX = 1,\
- laddersX = {\
- 9,\
- },\
- doorsY = {},\
- laddersY = {\
- 2,\
- },\
- ladderDestination = {\
- \"house1\",\
- },\
- }",
- "--Editor (yaay make your own levels based on this \"engine\")\
- --Again, written by me c:\
- --(I know, I'm shit at programming but hey why not C:)\
- \
- --Variablen\
- _ver = 0.1\
- _verstr = \"0.1\"\
- pfad = \"\"\
- \
- lvlData = {\
- \009spawnPosX=\"1\",\
- \009spawnPosY=\"1\",\
- \009blocksX = {\
- \
- \009},\
- \009blocksY = {\
- \
- \009}\
- }\
- \
- --Funktionen\
- function clear(bg, fg)\
- \009term.setCursorPos(1,1)\
- \009term.setBackgroundColor(bg)\
- \009term.setTextColor(fg)\
- \009term.clear()\
- end\
- \
- function menu()\
- \009clear(colors.black, colors.white)\
- \009term.setBackgroundColor(colors.lime)\
- \009term.setCursorPos(25, 6)\
- \009term.write(\"NEW\")\
- \009term.setCursorPos(24, 8)\
- \009term.write(\"LOAD\")\
- \009term.setCursorPos(24, 10)\
- \009term.write(\"EXIT\")\
- \009menu = true\
- \009while menu do\
- \009\009local event, button, x, y = os.pullEventRaw(\"mouse_click\")\
- \009\009if button == 1 and x >= 25 and x <= 27 and y == 6 then\
- \009\009\009menu = false\
- \009\009\009menu2()\
- \009\009end\
- \009end\
- end\
- \
- function menu2()\
- \009clear(colors.black, colors.white)\
- \009oldTerm = term.native()\
- \009local graywindow = window.create(oldTerm, 15, 5, 20, 5)\
- \009term.redirect(graywindow)\
- \009term.setBackgroundColor(colors.lightGray)\
- \009term.setCursorPos(1,1)\
- \009term.clear()\
- \009local textBox = window.create(term.current(), 2, 2, 18, 1)\
- \009textBox.setBackgroundColor(colors.gray)\
- \009textBox.setTextColor(colors.lime)\
- \009textBox.clear()\
- \009textBox.write(\"Enter Name/Desti..\")\
- \009term.setBackgroundColor(colors.gray)\
- \009term.setTextColor(colors.white)\
- \009term.setCursorPos(2, 4)\
- \009term.write(\"New\")\
- \009term.setCursorPos(16, 4)\
- \009term.write(\"Load\")\
- \009menu = true\
- \009while menu do\
- \009\009local event, button, x, y = os.pullEvent(\"mouse_click\")\
- \009\009if button == 1 and x >= 16 and x <= 34 and y == 6 then\
- \009\009\009term.redirect(textBox)\
- \009\009\009term.clear()\
- \009\009\009term.setCursorPos(1,1)\
- \009\009\009local eingabe = read()\
- \009\009\009pfad = eingabe\
- \009\009\009term.setCursorPos(1,1)\
- \009\009\009term.clear()\
- \009\009\009term.write(eingabe)\
- \009\009\009term.redirect(graywindow)\
- \009\009elseif button == 1 and x >= 16 and x <= 18 and y == 8 then\
- \009\009\009if fs.exists(pfad..\".lvl\") then\
- \009\009\009\009textBox.setCursorPos(1,1)\
- \009\009\009\009textBox.clear()\
- \009\009\009\009textBox.setTextColor(colors.red)\
- \009\009\009\009textBox.write(\"Already exists.\")\
- \009\009\009\009textBox.setTextColor(colors.lime)\
- \009\009\009elseif pfad == \"\" or pfad == nil then\
- \009\009\009\009textBox.setCursorPos(1,1)\
- \009\009\009\009textBox.clear()\
- \009\009\009\009textBox.setTextColor(colors.red)\
- \009\009\009\009textBox.write(\"Please fill in.\")\
- \009\009\009\009textBox.setTextColor(colors.lime)\
- \009\009\009else\
- \009\009\009\009term.redirect(oldTerm)\
- \009\009\009\009term.setCursorPos(1,1)\
- \009\009\009\009clear(colors.black, colors.white)\
- \009\009\009\009menu = false\
- \009\009\009\009print(\"Please draw your LevelDESIGN.\")\
- \009\009\009\009print(\"This will be that, what you see when playing the level.\")\
- \009\009\009\009sleep(3)\
- \009\009\009\009shell.run(\"paint \"..pfad..\".lvl\")\
- \009\009\009\009\
- \009\009\009\009editor()\
- \009\009\009end\
- \009\009elseif button == 1 and x >= 30 and x <= 34 and y == 8 then\
- \009\009\009if fs.exists(pfad..\".lvl\") and fs.exists(pfad..\".lvlDat\") then\
- \009\009\009\009term.redirect(oldTerm)\
- \009\009\009\009menu = false\
- \009\009\009\009editor(\"true\")\
- \009\009\009elseif fs.exists(pfad..\".lvl\") then\
- \009\009\009\009term.redirect(oldTerm)\
- \009\009\009\009menu = false\
- \009\009\009\009editor(\"false\")\
- \009\009\009else\
- \009\009\009\009textBox.setCursorPos(1,1)\
- \009\009\009\009textBox.clear()\
- \009\009\009\009textBox.setTextColor(colors.red)\
- \009\009\009\009textBox.write(\"Doesn't exist.\")\
- \009\009\009\009textBox.setTextColor(colors.lime)\
- \009\009\009end\
- \009\009end\
- \009end\
- \
- end\
- \
- function loadDat()\
- \009local file = fs.open(pfad..\".lvlDat\",\"r\")\
- \009local inhalt = file.readAll()\
- \009lvlData = textutils.unserialize(inhalt)\
- \009file.close()\
- end\
- \
- function editor(loadData)\
- \009clear(colors.black, colors.white)\
- \009lvl = paintutils.loadImage(pfad..\".lvl\")\
- \009paintutils.drawImage(lvl, 1, 1)\
- \009if loadData == \"true\" then\
- \009\009loadDat()\
- \009\009reloadMap()\
- \009end\
- \009term.setCursorPos(1,19)\
- \009term.setBackgroundColor(colors.lightGray)\
- \009term.clearLine()\
- \009term.setBackgroundColor(colors.lime)\
- \009term.write(\" Block \")\
- \009term.setBackgroundColor(colors.lightGray)\
- \009term.write(\" \")\
- \009term.setBackgroundColor(colors.lime)\
- \009term.write(\" Spawn \")\
- \009term.setBackgroundColor(colors.lightGray)\
- \009term.write(\" \")\
- \009term.setBackgroundColor(colors.lime)\
- \009term.write(\" Remove \")\
- \009editing = true\
- \009while editing do\
- \009\009local event, button, x, y = os.pullEventRaw()\
- \009\009if event == \"mouse_click\" and button == 1 and x >= 1 and x <= 7 and y == 19 then\
- \009\009\009currentBlock = \"block\"\
- \009\009elseif event == \"mouse_click\" and button == 1 and x >= 9 and x <= 15 and y == 19 then\
- \009\009\009currentBlock = \"spawn\"\
- \009\009elseif event == \"mouse_click\" and button == 1 and x >= 17 and x <= 24 and y == 19 then\
- \009\009\009currentBlock = \"remove\"\
- \009\009elseif event == \"mouse_click\" and button == 1 and x >= 1 and x <= 51 and y >= 1 and y <= 18 then\
- \009\009\009if currentBlock == \"block\" then\
- \009\009\009\009term.setCursorPos(x, y)\
- \009\009\009\009term.setBackgroundColor(colors.brown)\
- \009\009\009\009term.setTextColor(colors.white)\
- \009\009\009\009term.write(\"B\")\
- \009\009\009\009local x = tostring(x)\
- \009\009\009\009local y = tostring(y)\
- \009\009\009\009table.insert(lvlData.blocksX, x)\
- \009\009\009\009table.insert(lvlData.blocksY, y)\
- \009\009\009\009reloadMap()\
- \009\009\009elseif currentBlock == \"spawn\" then\
- \009\009\009\009term.setCursorPos(x, y)\
- \009\009\009\009term.setBackgroundColor(colors.blue)\
- \009\009\009\009term.setTextColor(colors.white)\
- \009\009\009\009term.write(\"S\")\
- \009\009\009\009local x = tostring(x)\
- \009\009\009\009local y = tostring(y)\
- \009\009\009\009lvlData.spawnPosX = x\
- \009\009\009\009lvlData.spawnPosY = y\
- \009\009\009\009reloadMap()\
- \009\009\009elseif currentBlock == \"remove\" then\
- \009\009\009\009for _, block in ipairs(lvlData.blocksX) do\
- \009\009\009\009\009local blockY = tonumber(lvlData.blocksY[_])\
- \009\009\009\009\009local block = tonumber(block)\
- \009\009\009\009\009if x == block and y == blockY then\
- \009\009\009\009\009\009lvlData.blocksX[_] = nil\
- \009\009\009\009\009\009lvlData.blocksY[_] = nil\
- \009\009\009\009\009end\
- \009\009\009\009end\
- \009\009\009\009if x == lvlData.spawnPosX and y == lvlData.spawnPosY then\
- \009\009\009\009\009lvlData.spawnPosX = \"1\"\
- \009\009\009\009\009lvlData.spawnPosY = \"1\"\
- \009\009\009\009end\
- \009\009\009\009reloadMap()\
- \009\009\009end\
- \009\009elseif event == \"key\" and button == keys.s then\
- \009\009\009local file = fs.open(pfad..\".lvlDat\",\"w\")\
- \009\009\009local lvlData = textutils.serialize(lvlData)\
- \009\009\009file.write(lvlData)\
- \009\009\009file.close()\
- \009\009\009clear(colors.black, colors.white)\
- \
- \009\009\009editing = false\
- \009\009\009break\
- \009\009end\
- \
- \009end\
- end\
- \
- function reloadMap()\
- \009clear(colors.black, colors.white)\
- \009term.setCursorPos(1,19)\
- \009term.setBackgroundColor(colors.lightGray)\
- \009term.clearLine()\
- \009term.setBackgroundColor(colors.lime)\
- \009term.write(\" Block \")\
- \009term.setBackgroundColor(colors.lightGray)\
- \009term.write(\" \")\
- \009term.setBackgroundColor(colors.lime)\
- \009term.write(\" Spawn \")\
- \009term.setBackgroundColor(colors.lightGray)\
- \009term.write(\" \")\
- \009term.setBackgroundColor(colors.lime)\
- \009term.write(\" Remove \")\
- \009term.setCursorPos(1,1)\
- \009paintutils.drawImage(lvl, 1, 1)\
- \009for _, block in ipairs(lvlData.blocksX) do\
- \009\009local blockY = tonumber(lvlData.blocksY[_])\
- \009\009local block = tonumber(block)\
- \009\009term.setCursorPos(block, blockY)\
- \009\009term.setBackgroundColor(colors.brown)\
- \009\009term.setTextColor(colors.white)\
- \009\009term.write(\"B\")\
- \009end\
- \009local sX = tonumber(lvlData.spawnPosX)\
- \009local sY = tonumber(lvlData.spawnPosY)\
- \009term.setCursorPos(sX, sY)\
- \009term.setBackgroundColor(colors.blue)\
- \009term.setTextColor(colors.white)\
- \009term.write(\"S\")\
- end\
- \
- \
- \
- --Code\
- menu2()",
- }
- folders = {
- "Project",
- "Project/API",
- "Project/game",
- "Project/maps",
- "Project/maps/house1",
- "Project/maps/house2",
- }
- local args = {...}
- if #args < 1 then
- print('Usage: <file> <destination>')
- else
- args[1] = args[1]..'/' for _, folder in ipairs(folders) do
- fs.makeDir(args[1]..folder)
- end
- for _, file in ipairs(files) do
- local file = fs.open(args[1]..file, 'w')
- file.write(fileData[_])
- file.close()
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement