-- +---------------------+-------------+---------------------+ -- | | | | -- | | PrintShop | | -- | | | | -- +---------------------+-------------+---------------------+ local version = "Version 1.0.0" -- Offers printed books to MineCraft players in exchange for XP levels. -- http://www.computercraft.info/forums2/index.php?/topic/25037-cprint-print-books-with-command-computers/ --------------------------------------------- ------------Variable Declarations------------ --------------------------------------------- if not fs.exists(shell.resolve("printshop.cfg")) then shell.run("pastebin get CWWeJk9g printshop.cfg") end if not cprint then if not (fs.exists("cprint") or fs.exists(shell.resolve("cprint"))) then shell.run("pastebin get QP8yFSPW cprint") os.loadAPI(shell.resolve("cprint")) else os.loadAPI(fs.exists("cprint") and "cprint" or shell.resolve("cprint")) end end local cost, cooldown, myEvent, xSize, ySize, printList do local arg = {...} cost, cooldown = tonumber(arg[1]) or 5, tonumber(arg[2]) or 30 end local cursor = {{">> "," <<"},{"> > "," < <"},{" >> "," << "},{"> > "," < <"}} --------------------------------------------- ------------ Functions ------------ --------------------------------------------- local function clear(textCol, backCol) if textCol then term.setTextColour(textCol) end if backCol then term.setBackgroundColour(backCol) end for i = 4, ySize - 3 do term.setCursorPos(1, i) term.clearLine() end end -- Returns whether a click was performed at a given location. -- If one parameter is passed, it checks to see if y is [1]. -- If two parameters are passed, it checks to see if x is [1] and y is [2]. -- If three parameters are passed, it checks to see if x is between [1]/[2] (non-inclusive) and y is [3]. -- If four paramaters are passed, it checks to see if x is between [1]/[2] and y is between [3]/[4] (non-inclusive). local function clickedAt(...) if myEvent[1] ~= "mouse_click" then return false end if #arg == 1 then return (arg[1] == myEvent[4]) elseif #arg == 2 then return (myEvent[3] == arg[1] and myEvent[4] == arg[2]) elseif #arg == 3 then return (myEvent[3] > arg[1] and myEvent[3] < arg[2] and myEvent[4] == arg[3]) else return (myEvent[3] > arg[1] and myEvent[3] < arg[2] and myEvent[4] > arg[3] and myEvent[4] < arg[4]) end end -- Returns whether one of a given set of keys was pressed. local function pressedKey(...) if myEvent[1] ~= "key" then return false end for i=1,#arg do if arg[i] == myEvent[2] then return true end end return false end local function writeAt(text, x, y, tCol, bCol) if not (x and y) then local curX, curY = term.getCursorPos() x, y = x or curX, y or curY end term.setCursorPos(x, y) if tCol then term.setTextColour(tCol) end if bCol then term.setBackgroundColour(bCol) end term.write(text) end local function downloadPaste(pasteID) if type(pasteID) ~= "string" then error("package.downloadPaste: Expected: (string) paste ID", 2) end local webHandle = http.get("http://pastebin.com/raw.php?i=" .. textutils.urlEncode(pasteID)) if webHandle then local incoming = webHandle.readAll() webHandle.close() return incoming else error("Connection to pastebin failed. http API config in ComputerCraft.cfg is enabled, but may be set to block pastebin - or pastebin servers may be busy.") end end local function fileBrowser() local bump = math.floor((xSize - 49) / 2) + 1 while true do local position, lastPosition, animationTimer, curCount, gapTimer, lastProgress = 1, 0, os.startTimer(0), 1 if #shell.resolve(".") > 0 then printList[1] = ".." end while true do myEvent = {os.pullEvent()} -- Track animations (bouncing cursor + scrolling marquee). if myEvent[1] == "timer" and myEvent[2] == animationTimer then curCount = curCount == 4 and 1 or (curCount + 1) animationTimer = os.startTimer(0.5) myEvent[1] = "cabbage" -- Move down the list. elseif pressedKey(keys.down, keys.s) or (myEvent[1] == "mouse_scroll" and myEvent[2] == 1) then position = position == #printList and 1 or (position + 1) -- Move up the list. elseif pressedKey(keys.up, keys.w) or (myEvent[1] == "mouse_scroll" and myEvent[2] == -1) then position = position == 1 and #printList or (position - 1) -- Select something. elseif pressedKey(keys.enter, keys.space) or clickedAt(math.floor(ySize / 2) + 1) then return printList[position] -- User clicked somewhere on the file list; move that entry to the currently-selected position. elseif clickedAt(0, xSize + 1, 3, ySize - 2) then position = position + myEvent[4] - math.floor(ySize / 2) - 1 position = position > #printList and #printList or position position = position < 1 and 1 or position end -- Update other screen stuff. if myEvent[1] ~= "timer" then -- File list. term.setBackgroundColour(colours.black) for y = position == lastPosition and (math.floor(ySize / 2) + 1) or 4, position == lastPosition and (math.floor(ySize / 2) + 1) or (ySize - 3) do local thisLine = y + position - math.floor(ySize / 2) - 1 if printList[thisLine] then local thisString = printList[thisLine][1] if thisLine == position then term.setCursorPos(math.floor((xSize - #thisString - 8) / 2) + 1, y) term.clearLine() term.setTextColour(colours.brown) term.write(cursor[curCount][1]) term.setTextColour(colours.purple) term.write(thisString) term.setTextColour(colours.brown) term.write(cursor[curCount][2]) else term.setCursorPos(math.floor((xSize - #thisString) / 2) + 1, y) term.clearLine() if y == 4 or y == ySize - 3 then term.setTextColour(blackText) elseif y == 5 or y == ySize - 4 then term.setTextColour(colours.grey) elseif y == 6 or y == ySize - 5 then term.setTextColour(colours.lightGrey) else term.setTextColour(colours.white) end term.write(thisString) end else term.setCursorPos(1, y) term.clearLine() end end lastPosition = position end end end end --------------------------------------------- ------------ Init ------------ --------------------------------------------- if term.current().setTextScale then local setTextScale = term.current().setTextScale setTextScale(0.5) local scale = 5 repeat setTextScale(scale) scale = scale - 0.5 local xSize, ySize = term.getSize() until (xSize >= 50 and ySize >= 19) or scale == 0 end xSize, ySize = term.getSize() if xSize < 50 or ySize < 19 or not term.isColour() then error("Sorry, a 50x19 colour display is required at minimum.") end do local input = fs.open("printshop.cfg", "r") printList = textutils.unserialise(input.readAll()) input.close() end term.setTextColour(colours.black) term.setBackgroundColour(colours.green) for j = 0, 1 do for i = 1, 3 do term.setCursorPos(1, i + (j * (ySize - 3))) term.clearLine() end end term.setCursorPos(5, 2) term.write("PrintShop", 5, 2) paintutils.drawPixel(1, 1, colours.blue) paintutils.drawPixel(2, 1, colours.green) paintutils.drawPixel(3, 1, colours.yellow) paintutils.drawPixel(1, 2, colours.grey) paintutils.drawPixel(2, 2, colours.white) paintutils.drawPixel(3, 2, colours.lightBlue) paintutils.drawPixel(1, 3, colours.orange) paintutils.drawPixel(3, 3, colours.red) paintutils.drawPixel(2, 3, colours.lime) --------------------------------------------- ------------ Main Program Loop ------------ --------------------------------------------- while true do local thisBook, copies = fileBrowser(), 1 clear(colours.black, colours.lightGrey) writeAt(thisBook[1], math.floor((51 - #thisBook[1]) / 2) + 1, 6) writeAt("How many copies?", 18, 9, colours.grey) writeAt("XP Level Cost: " .. tostring(cost * copies), 18, 13) writeAt(" < ", 18, 11, colours.lightGrey, colours.grey) writeAt(" > ", 26, 11) writeAt(" Ok ", 31, 11) writeAt(" ", 22, 11) writeAt(" Cancel ", 22, 15) local thisString = tostring(copies) writeAt(thisString, 22 + math.floor((4 - #thisString) / 2), 11, colours.lime) repeat myEvent = {os.pullEvent("mouse_click")} if clickedAt(17, 21, 11) and copies > 1 then copies = copies - 1 elseif clickedAt(25, 29, 11) then copies = copies + 1 end writeAt(" ", 22, 11, colours.lime, colours.grey) thisString = tostring(copies) writeAt(thisString, 22 + math.floor((4 - #thisString) / 2), 11) writeAt(tostring(cost * copies) .. " ", 33, 13, colours.grey, colours.lightGrey) until clickedAt(30, 35, 11) or clickedAt(21, 30, 15) if clickedAt(30, 35, 11) then if commands.testfor("@p[lm=" .. tostring(cost * copies) .. "]") then commands.xp("-" .. tostring(cost * copies) .."L", "@p") local book = cprint.newPrintableBook(thisBook[1]) local oldTerm = term.redirect(book) print(downloadPaste(thisBook[2])) term.redirect(oldTerm) book.printBook("@p", copies) writeAt("Book(s) printed! Cooling down...", 10, 15) sleep(cooldown) else writeAt("You don't have enough XP levels!", 10, 15, colours.red) sleep(5) end end end