Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- files = {
- "startup",
- "server/pws.list",
- "server/users.list",
- "server/maps/editor.lua",
- "server/maps/editorlayout.nfp",
- "server/maps/np",
- "server/maps/house1/data.lvl",
- "server/maps/house1/data.lvlDat",
- "server/maps/house1/editor",
- "server/maps/house2/data.lvl",
- "server/maps/house2/data.lvlDat",
- "server/maps/house2/editor",
- "server/maps/house2/lvl",
- }
- fileData = {
- "--test server\
- 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\"\
- }\
- \
- users = {\
- \009\
- }\
- \
- playerData = {\
- \009users = {\
- \
- \009},\
- \009inventory = {\
- \
- \009},\
- \009worlds = {\
- \
- \009},\
- \009posX = {\
- \
- \009},\
- \009posY = {\
- \
- \009}\
- }\
- z = 0\
- \
- rednet.open(\"top\")\
- \
- while true do\
- \009id, msg, msg2 = rednet.receive()\
- \009if msg == msgs[1] then\
- \009\009print(\"Received ping from \"..tostring(id)..\", sending success.\")\
- \009\009rednet.send(id, msgs[2])\
- \009\009print(\"Success sent.\")\
- \009elseif msg == msgs[3] then\
- \009\009print(\"Received Username: \"..msg2..\" from \"..tostring(id)..\", searching user...\")\
- \009\009local file = fs.open(\"/server/users.list\", \"r\")\
- \009\009local found = false\
- \009\009users = file.readAll()\
- \009\009users = textutils.unserialize(users)\
- \009\009file.close()\
- \009\009for _, user in ipairs(users) do\
- \009\009\009if msg2 == user then\
- \009\009\009\009print(\"User found, sending success.\")\
- \009\009\009\009rednet.send(id, msgs[4])\
- \009\009\009\009found = true\
- \009\009\009\009break\
- \009\009\009else\
- \009\009\009\009found = false\
- \009\009\009end\
- \009\009end\
- \009\009if found == false then\
- \009\009\009print(\"User not found, sending register.\")\
- \009\009\009rednet.send(id, msgs[5])\
- \009\009end\
- \009elseif msg == msgs[5] then\
- \009\009usrData = textutils.unserialize(msg2)\
- \009\009pData = {\
- \009\009\009inventory = {\
- \
- \009\009\009},\
- \009\009\009world = \"house1\",\
- \009\009\009x = 2,\
- \009\009\009y = 2\
- \009\009}\
- \009\009print(\"Register (\"..tostring(id)..\"): \"..usrData.name..\".\")\
- \009\009print(\"Writing to files...\")\
- \009\009local file = fs.open(\"/server/users.list\",\"r\")\
- \009\009users = file.readAll()\
- \009\009users = textutils.unserialize(users)\
- \009\009file.close()\
- \009\009local file = fs.open(\"/server/users.list\",\"w\")\
- \009\009table.insert(users, usrData.name)\
- \009\009file.write(textutils.serialize(users))\
- \009\009file.close()\
- \009\009local file = fs.open(\"/server/pws.list\",\"r\")\
- \009\009pws = file.readAll()\
- \009\009pws = textutils.unserialize(pws)\
- \009\009file.close()\
- \009\009local file = fs.open(\"/server/pws.list\",\"w\")\
- \009\009table.insert(pws, usrData.encpw)\
- \009\009file.write(textutils.serialize(pws))\
- \009\009file.close()\
- \009\009fs.makeDir(\"/server/saves/\"..usrData.name..\"\")\
- \009\009local file = fs.open(\"/server/saves/\"..usrData.name..\"/data\",\"w\")\
- \009\009file.write(textutils.serialize(pData))\
- \009\009file.close()\
- \009\009print(\"Complete, sending success.\")\
- \009\009rednet.send(id, msgs[2])\
- \009elseif msg == msgs[4] then\
- \009\009usrData = textutils.unserialize(msg2)\
- \009\009print(\"Login (\"..tostring(id)..\"): \"..usrData.name..\".\")\
- \009\009print(\"Checking password....\")\
- \009\009local file = fs.open(\"/server/users.list\",\"r\")\
- \009\009users = file.readAll()\
- \009\009users = textutils.unserialize(users)\
- \009\009file.close()\
- \009\009local file = fs.open(\"/server/pws.list\",\"r\")\
- \009\009pws = file.readAll()\
- \009\009pws = textutils.unserialize(pws)\
- \009\009file.close()\
- \009\009local usrnmbr = 0\
- \009\009for _, usr in ipairs(users) do\
- \009\009\009if usr == usrData.name then\
- \009\009\009\009usrnmbr = _\
- \009\009\009\009break\
- \009\009\009end\
- \009\009end\
- \009\009if usrData.encpw == pws[usrnmbr] then\
- \009\009\009print(\"Password correct, sending success.\")\
- \009\009\009rednet.send(id, msgs[2])\
- \009\009else\
- \009\009\009print(\"Password incorrect, sending failure.\")\
- \009\009\009rednet.send(id, msgs[6])\
- \009\009end\
- \009elseif msg == msgs[7] then\
- \009\009usrData = textutils.unserialize(msg2)\
- \009\009print(tostring(id)..\" requested deletion of \"..usrData.name)\
- \009\009print(\"Checking password...\")\
- \009\009local file = fs.open(\"/server/users.list\",\"r\")\
- \009\009users = file.readAll()\
- \009\009users = textutils.unserialize(users)\
- \009\009file.close()\
- \009\009local file = fs.open(\"/server/pws.list\",\"r\")\
- \009\009pws = file.readAll()\
- \009\009pws = textutils.unserialize(pws)\
- \009\009file.close()\
- \009\009local usrnmbr = 0\
- \009\009for _, usr in ipairs(users) do\
- \009\009\009if usr == usrData.name then\
- \009\009\009\009usrnmbr = _\
- \009\009\009\009break\
- \009\009\009end\
- \009\009end\
- \009\009if usrData.encpw == pws[usrnmbr] then\
- \009\009\009shell.run(\"rm /server/saves/\"..usrData.name)\
- \009\009\009table.remove(users, usrnmbr)\
- \009\009\009table.remove(pws, usrnmbr)\
- \009\009\009local file = fs.open(\"/server/users.list\",\"w\")\
- \009\009\009file.write(textutils.serialize(users))\
- \009\009\009file.close()\
- \009\009\009local file = fs.open(\"/server/pws.list\",\"w\")\
- \009\009\009file.write(textutils.serialize(pws))\
- \009\009\009file.close()\
- \009\009\009print(\"Password correct and removed account, sending success.\")\
- \009\009\009rednet.send(id, msgs[2])\
- \009\009else\
- \009\009\009print(\"Password invalid, sending failure.\")\
- \009\009\009rednet.send(id, msgs[6])\
- \009\009end\
- \009elseif msg == msgs[8] then\
- \
- \009\009c = textutils.unserialize(msg2)\
- \009\009print(tostring(id)..\" requested changing password of \"..c.oldData.name..\".\")\
- \009\009print(\"Checking password...\")\
- \009\009local file = fs.open(\"/server/users.list\",\"r\")\
- \009\009users = file.readAll()\
- \009\009users = textutils.unserialize(users)\
- \009\009file.close()\
- \009\009local file = fs.open(\"/server/pws.list\",\"r\")\
- \009\009pws = file.readAll()\
- \009\009pws = textutils.unserialize(pws)\
- \009\009file.close()\
- \009\009local usrnmbr = 0\
- \009\009for _, usr in ipairs(users) do\
- \009\009\009if usr == c.newData.name and usr == c.oldData.name then\
- \009\009\009\009usrnmbr = _\
- \009\009\009\009break\
- \009\009\009end\
- \009\009end\
- \009\009if c.oldData.encpw == pws[usrnmbr] then\
- \
- \009\009\009pws[usrnmbr] = c.newData.encpw\
- \009\009\009local file = fs.open(\"/server/pws.list\",\"w\")\
- \009\009\009file.write(textutils.serialize(pws))\
- \009\009\009file.close()\
- \009\009\009print(\"Password correct and changed. Sending success.\")\
- \009\009\009rednet.send(id, msgs[2])\
- \009\009else\
- \009\009\009rednet.send(id, msgs[6])\
- \009\009end\
- \009elseif msg == msgs[10] then\
- \009\009print(tostring(id)..\" requested \"..msg2..\" spawn...\")\
- \009\009local file = fs.open(\"/server/saves/\"..msg2..\"/data\",\"r\")\
- \009\009local pData = file.readAll()\
- \009\009pData = textutils.unserialize(pData)\
- \009\009file.close()\
- \009\009if playerData.users[msg2] ~= nil then\
- \009\009\009--[[table.remove(playerData.users, _)\
- \009\009\009table.remove(playerData.inventory, _)\
- \009\009\009table.remove(playerData.worlds, _)\
- \009\009\009table.remove[playerData.posX, _)\
- \009\009\009table.remove(playerData.posY, _)]]\
- \009\009\009playerData.users[msg2] = nil\
- \009\009\009playerData.inventory[msg2] = nil\
- \009\009\009playerData.worlds[msg2] = nil\
- \009\009\009playerData.posX[msg2] = nil\
- \009\009\009playerData.posY[msg2] = nil\
- \009\009end\
- \009\009--[[table.insert(playerData.users, msg2)\
- \009\009table.insert(playerData.inventory, pData.inventory)\
- \009\009table.insert(playerData.worlds, pData.world)\
- \009\009table.insert(playerData.posX, tostring(pData.x))\
- \009\009table.insert(playerData.posY, tostring(pData.y))]]\
- \009\009playerData.users[msg2] = msg2\
- \009\009playerData.inventory[msg2] = pData.inventory\
- \009\009playerData.worlds[msg2] = pData.world\
- \009\009playerData.posX[msg2] = pData.x\
- \009\009playerData.posY[msg2] = pData.y\
- \009\009print(\"Player inserted into world, sending success and players.\")\
- \009\009rednet.send(id, msgs[2], textutils.serialize(playerData))\
- \009elseif msg == msgs[11] then\
- \009\009mapData = {\
- \009\009\009layout = nil,\
- \009\009\009data = {\
- \
- \009\009\009}\
- \009\009}\
- \009\009print(tostring(id)..\" requested map \"..msg2..\".\")\
- \009\009local file = fs.open(\"/server/maps/\"..msg2..\"/lvl\",\"r\")\
- \009\009mapData.layout = file.readAll()\
- \009\009file.close()\
- \009\009local file = fs.open(\"/server/maps/\"..msg2..\"/data.lvlDat\",\"r\")\
- \009\009local inhalt = file.readAll()\
- \009\009mapData.data = textutils.unserialize(inhalt)\
- \009\009file.close()\
- \009\009print(\"Sending map\")\
- \009\009rednet.send(id, msgs[2], textutils.serialize(mapData))\
- \009elseif msg == msgs[9] then\
- \009\009--[[z = z+1\
- \009\009print(\"Requested data \"..tostring(z))\
- \009\009for _, usr in ipairs(playerData.users) do\
- \009\009\009print(usr)\
- \009\009\009print(tostring(playerData.posX[_]))\
- \009\009\009print(tostring(playerData.posY[_]))\
- \009\009end]]\
- \009\009rednet.send(id, msgs[2], textutils.serialize(playerData))\
- \009elseif msg == msgs[12] then\
- \009\009local changed = textutils.unserialize(msg2)\
- \009\009print(\"Move \"..changed.changer.name)\
- \009\009\009--print(tostring(playerData.posX[changed.changer.name]))\
- \009\009\009--print(tostring(playerData.posY[changed.changer.name]))\
- \009\009\009\009playerData.posX[changed.changer.name] = changed.playerData.posX[changed.changer.name]\
- \009\009\009\009playerData.posY[changed.changer.name] = changed.playerData.posY[changed.changer.name]\
- \009\009\009\009playerData.inventory[changed.changer.name] = changed.playerData.inventory[changed.changer.name]\
- \009\009\009\009playerData.worlds[changed.changer.name] = changed.playerData.worlds[changed.changer.name]\
- \009\009\009\009--print(usr)\
- \009\009\009\009local a = tostring(playerData.posX[changed.changer.name])\
- \009\009\009\009local b = tostring(playerData.posY[changed.changer.name])\
- \009\009\009\009local c = tostring(playerData.worlds[changed.changer.name])\
- \009\009print(tostring(id)..\" moved ->\"..a..\" \"..b..\" \"..c)\
- \009\009u = changed.changer.name\
- \009\009local file = fs.open(\"/server/saves/\"..u..\"/data\",\"r\")\
- \009\009local inhalt = file.readAll()\
- \009\009inhalt = textutils.unserialize(inhalt)\
- \009\009file.close()\
- \009\009\
- \009\009inhalt.world = playerData.worlds[changed.changer.name]\
- \009\009inhalt.inventory = playerData.inventory[changed.changer.name]\
- \009\009inhalt.x = playerData.posX[changed.changer.name]\
- \009\009inhalt.y = playerData.posY[changed.changer.name]\
- \009\009local file = fs.open(\"/server/saves/\"..u..\"/data\",\"w\")\
- \009\009file.write(textutils.serialize(inhalt))\
- \009\009file.close()\
- \009elseif msg == msgs[13] then\
- \009\009local file = fs.open(\"/server/chat\", \"r\")\
- \009\009local inhalt = file.readAll()\
- \009\009file.close()\
- \009\009rednet.send(id, msgs[13], inhalt)\
- \009elseif msg == msgs[14] then\
- \009\009print(\"Getting message\")\
- \009\009rednet.broadcast(msg2, msgs[13])\
- \009end\
- end",
- "{\
- }",
- "{\
- }",
- "--[[\
- 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()",
- "7777777777777777777777777\
- 7ccccccccccccccccccccccc7\
- 7ccccccccccccccccccccccc7\
- 7ccccccccccccccccccccccc7\
- 7ccccccccccccccccccccccc7\
- 7ccccccccccccccccccccccc7\
- 7ccccccccccccccccccccccc7\
- 7ccccccccccccccccccccccc7\
- 7777777777777777777777777",
- }
- folders = {
- "server",
- "server/maps",
- "server/saves",
- "server/maps/house1",
- "server/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