· 4 years ago · Jul 10, 2021, 10:54 AM
1{
2 mainFile = false,
3 compressed = false,
4 data = {
5 [ "keypad-image.skimg" ] = "{\
6 attributes = {\
7 height = 5,\
8 locked = false,\
9 creator = \"SkyCrafter0\",\
10 width = 7,\
11 },\
12 data = {\
13 {\
14 \"\\000\\000\\000\\000\\000\\000\\000\",\
15 \"f88888f\",\
16 \"0888880\",\
17 1,\
18 },\
19 {\
20 \"\\000\\000\\000\\000\\000\\000\\000\",\
21 \"fffffff\",\
22 \"0000000\",\
23 2,\
24 },\
25 {\
26 \"\\000123\\000\\000\\000\",\
27 \"f888fff\",\
28 \"0777e00\",\
29 3,\
30 },\
31 {\
32 \"\\000456\\000\\000\\000\",\
33 \"f888fff\",\
34 \"0777500\",\
35 4,\
36 },\
37 {\
38 \"\\0007890\\000\\000\",\
39 \"f8888ff\",\
40 \"0777700\",\
41 5,\
42 },\
43 },\
44}",
45 [ "libraries/button.lua" ] = "--- A simple button api with the option of drawing an image on the button.\
46-- @module[kind=misc] button\
47\
48local expect = require(\"cc.expect\").expect\
49--- idLength is how long the specific IDs are, if you have lots of buttons, this should go higher.\
50local idLength = 6 -- This is the length of the unique identifiers for buttons.\
51--- strictImage forces the image to be the same height and width as the button\
52local strictImage = true -- This confirms that the image is the same height as the button.\
53local buttons = {}\
54\
55local function genRandID(length)\
56 local str = \"\"\
57 for _=1,length do\
58 local num = math.random(48,109)\
59 if num >= 58 then num = num + 7 end\
60 if num >= 91 then num = num + 6 end\
61 str = str .. string.char(num)\
62 end\
63 return str\
64end\
65\
66--[[- Create a button, and add it to the internal table of buttons.\
67 @tparam number x X coordinate of the button.\
68 @tparam number y Y coordinate of the button.\
69 @tparam number width Width of the button.\
70 @tparam number height Height of the button.\
71 @tparam function function The function to run when the button is clicked.\
72 @tparam[opt] table image Table of blit lines to draw on the button.\
73 @tparam[opt] boolean enabled Whether or not the button is active. Defaults to true.\
74 @treturn string id id of the button\
75]]\
76local function newButton(nX,nY,nW,nH,fFunc,tDraw,enabled) -- tDraw is a table of blit lines. This function will check they're the same length.\
77 expect(1,nX,\"number\")\
78 expect(1,nY,\"number\")\
79 expect(1,nW,\"number\")\
80 expect(1,nH,\"number\")\
81 expect(1,fFunc,\"function\")\
82 expect(1,tDraw,\"table\",\"nil\")\
83 expect(1,enabled,\"boolean\",\"nil\")\
84 enabled = enabled or true -- retain old behaviour\
85\
86 local mX,mY = term.getCursorPos()\
87\
88 if tDraw then -- If a blit table is passed, loop through it and make sure it's a valid (ish) table, and make sure it's the same height & width as the button.\
89 if strictImage then\
90 if #tDraw ~= nH then\
91 error(\"Image must be same height as button\",2)\
92 end\
93 end\
94 for i=1,#tDraw do\
95 if #tDraw[i][1] ~= #tDraw[i][2] or #tDraw[i][1] ~= #tDraw[i][3] then\
96 error(\"tDraw line\" .. tostring(i) .. \"is not equal to other lines\",2)\
97 end\
98 if strictImage then\
99 if #tDraw[i][1] ~= nW then\
100 error(\"Image must be same width as button\",2)\
101 end\
102 end\
103 end\
104 end\
105\
106 local id = genRandID(idLength)\
107\
108 buttons[id] = { -- Store the information about the button in the buttons table.\
109 x = nX,\
110 y = nY,\
111 w = nW,\
112 h = nH,\
113 fFunc = fFunc,\
114 tDraw = tDraw,\
115 enabled = enabled,\
116 }\
117\
118 if tDraw then -- If a blit table is passed, loop through it and draw it.\
119 for i=1,#tDraw do\
120 local frame = tDraw[i]\
121 term.setCursorPos(nX,nY+i)\
122 term.blit(frame[1],frame[2],frame[3])\
123 end\
124 term.setCursorPos(mX,mY)\
125 end\
126\
127 return id\
128end\
129\
130--- Remove a button from being clicked.\
131-- @tparam string id button id to remove.\
132local function deleteButton(id) -- This doesn't remove the image if any!\
133 if buttons[id] then\
134 buttons[id] = nil\
135 end\
136end\
137\
138--- Enable or disable a button.\
139-- @tparam string id Button to enable or disable.\
140-- @tparam boolean enable Whether the button is enabled or not.\
141local function enableButton(id,enable)\
142 if not buttons[id] then error(\"Button \" .. id .. \" does not exist.\",2) end\
143 buttons[id].enabled = enable\
144end\
145\
146--- Takes an event in a table, checks if it's a `mouse_click` or `mouse_drag`, and sees if it's within a button, if so, execute it's function.\
147-- @tparam table event Event table to check for `mouse_click` or `mouse_drag`.\
148-- @tparam[opt] boolean drag Enable button trigger on a `mouse_drag` event. Defaults to false.\
149local function executeButtons(tEvent,bDrag)\
150 bDrag = bDrag or false\
151 if tEvent[1] == \"mouse_click\" or bDrag and tEvent[1] == \"mouse_drag\" then\
152 local x,y = tEvent[3],tEvent[4]\
153 for _,v in pairs(buttons) do\
154 if v.enabled and x >= v.x and x <= v.x + v.w - 1 and y >= v.y and y <= v.y + v.h - 1 then\
155 pcall(v.fFunc)\
156 end\
157 end\
158 end\
159end\
160\
161--- Draw a button again, drawing it's `tDraw`, or nothing if there is no image.\
162-- @tparam string id Button ID to draw image of.\
163local function drawButton(id)\
164 if buttons[id] and buttons[id].tDraw then\
165 local image = buttons[id].tDraw\
166 local w,h = buttons[id].w,buttons[id].h\
167 if strictImage then\
168 if #image ~= h then\
169 error(\"image must be same height as button\",2)\
170 end\
171 end\
172 for i=1,#image do\
173 if #image[i][1] ~= #image[i][2] or #image[i][1] ~= #image[i][3] then\
174 error(\"image line\" .. tostring(i) .. \"is not equal to other lines\",2)\
175 end\
176 if strictImage then\
177 if #image[i][1] ~= w then\
178 error(\"Image must be same width as button\",2)\
179 end\
180 end\
181 end\
182 end\
183end\
184\
185--- Draw every button, this loops through the buttons table.\
186local function drawButtons()\
187 for k in pairs(buttons) do\
188 drawButton(k)\
189 end\
190end\
191\
192--- Edit a button, changing it's function, position, or whatnot.\
193-- @tparam string id ID of the button to change.\
194-- @tparam[opt] number x X coordinate of the button.\
195-- @tparam[opt] number y Y coordinate of the button.\
196-- @tparam[opt] number width Width of the button.\
197-- @tparam[opt] number height Height of the button.\
198-- @tparam[opt] function func Function to execute when the button is clicked.\
199-- @tparam[opt] table image Table of blit lines to draw where the button is.\
200local function edit(id,x,y,w,h,func,image)\
201 if not buttons[id] then\
202 error(\"Button \" .. id .. \" does not exist.\",2)\
203 end\
204 x = x or buttons[id].x\
205 y = y or buttons[id].y\
206 w = w or buttons[id].w\
207 h = h or buttons[id].h\
208 local fFunc = func or buttons[id].fFunc\
209 local tDraw = image or buttons[id].tDraw\
210 local enabled = buttons[id].enabled\
211 buttons[id] = {\
212 x = x,\
213 y = y,\
214 w = w,\
215 h = h,\
216 fFunc = fFunc,\
217 tDraw = tDraw,\
218 enabled = enabled,\
219 }\
220end\
221\
222return {\
223 newButton = newButton,\
224 deleteButton = deleteButton,\
225 enableButton = enableButton,\
226 edit = edit,\
227 executeButtons = executeButtons,\
228 drawButton = drawButton,\
229 drawButtons = drawButtons,\
230}",
231 [ "libraries/bigfont.lua" ] = "-------------------------------------------------------------------------------------\
232-- Wojbies API 5.0 - Bigfont - functions to write bigger font using drawing sybols --\
233-------------------------------------------------------------------------------------\
234-- Copyright (c) 2015-2020 Wojbie (wojbie@wojbie.net)\
235-- Redistribution and use in source and binary forms, with or without modification, are permitted (subject to the limitations in the disclaimer below) provided that the following conditions are met:\
236-- 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\
237-- 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\
238-- 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\
239-- 4. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\
240-- 5. The origin of this software must not be misrepresented; you must not claim that you wrote the original software.\
241-- NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\
242\
243--Switch to true to replace generic currency sign \"\\164\" with krist symbol.\
244local krist = false\
245\
246--### Initializing\
247local b = shell and {} or (_ENV or getfenv())\
248b.versionName = \"Bigfont By Wojbie\"\
249b.versionNum = 5.002 --2021-05-01\
250b.doc = {}\
251\
252local expect, field if require then expect, field = require \"cc.expect\".expect, require \"cc.expect\".field else local ok, did = pcall(dofile,\"rom/modules/main/cc/expect.lua\") if ok then field, expect = did.field, did.expect else field, expect = function() end, function() end end end\
253\
254--### Font database\
255local rawFont = {{\"\\32\\32\\32\\137\\156\\148\\158\\159\\148\\135\\135\\144\\159\\139\\32\\136\\157\\32\\159\\139\\32\\32\\143\\32\\32\\143\\32\\32\\32\\32\\32\\32\\32\\32\\147\\148\\150\\131\\148\\32\\32\\32\\151\\140\\148\\151\\140\\147\", \"\\32\\32\\32\\149\\132\\149\\136\\156\\149\\144\\32\\133\\139\\159\\129\\143\\159\\133\\143\\159\\133\\138\\32\\133\\138\\32\\133\\32\\32\\32\\32\\32\\32\\150\\150\\129\\137\\156\\129\\32\\32\\32\\133\\131\\129\\133\\131\\132\", \"\\32\\32\\32\\130\\131\\32\\130\\131\\32\\32\\129\\32\\32\\32\\32\\130\\131\\32\\130\\131\\32\\32\\32\\32\\143\\143\\143\\32\\32\\32\\32\\32\\32\\130\\129\\32\\130\\135\\32\\32\\32\\32\\131\\32\\32\\131\\32\\131\", \"\\139\\144\\32\\32\\143\\148\\135\\130\\144\\149\\32\\149\\150\\151\\149\\158\\140\\129\\32\\32\\32\\135\\130\\144\\135\\130\\144\\32\\149\\32\\32\\139\\32\\159\\148\\32\\32\\32\\32\\159\\32\\144\\32\\148\\32\\147\\131\\132\", \"\\159\\135\\129\\131\\143\\149\\143\\138\\144\\138\\32\\133\\130\\149\\149\\137\\155\\149\\159\\143\\144\\147\\130\\132\\32\\149\\32\\147\\130\\132\\131\\159\\129\\139\\151\\129\\148\\32\\32\\139\\131\\135\\133\\32\\144\\130\\151\\32\", \"\\32\\32\\32\\32\\32\\32\\130\\135\\32\\130\\32\\129\\32\\129\\129\\131\\131\\32\\130\\131\\129\\140\\141\\132\\32\\129\\32\\32\\129\\32\\32\\32\\32\\32\\32\\32\\131\\131\\129\\32\\32\\32\\32\\32\\32\\32\\32\\32\", \"\\32\\32\\32\\32\\149\\32\\159\\154\\133\\133\\133\\144\\152\\141\\132\\133\\151\\129\\136\\153\\32\\32\\154\\32\\159\\134\\129\\130\\137\\144\\159\\32\\144\\32\\148\\32\\32\\32\\32\\32\\32\\32\\32\\32\\32\\32\\151\\129\", \"\\32\\32\\32\\32\\133\\32\\32\\32\\32\\145\\145\\132\\141\\140\\132\\151\\129\\144\\150\\146\\129\\32\\32\\32\\138\\144\\32\\32\\159\\133\\136\\131\\132\\131\\151\\129\\32\\144\\32\\131\\131\\129\\32\\144\\32\\151\\129\\32\", \"\\32\\32\\32\\32\\129\\32\\32\\32\\32\\130\\130\\32\\32\\129\\32\\129\\32\\129\\130\\129\\129\\32\\32\\32\\32\\130\\129\\130\\129\\32\\32\\32\\32\\32\\32\\32\\32\\133\\32\\32\\32\\32\\32\\129\\32\\129\\32\\32\", \"\\150\\156\\148\\136\\149\\32\\134\\131\\148\\134\\131\\148\\159\\134\\149\\136\\140\\129\\152\\131\\32\\135\\131\\149\\150\\131\\148\\150\\131\\148\\32\\148\\32\\32\\148\\32\\32\\152\\129\\143\\143\\144\\130\\155\\32\\134\\131\\148\", \"\\157\\129\\149\\32\\149\\32\\152\\131\\144\\144\\131\\148\\141\\140\\149\\144\\32\\149\\151\\131\\148\\32\\150\\32\\150\\131\\148\\130\\156\\133\\32\\144\\32\\32\\144\\32\\130\\155\\32\\143\\143\\144\\32\\152\\129\\32\\134\\32\", \"\\130\\131\\32\\131\\131\\129\\131\\131\\129\\130\\131\\32\\32\\32\\129\\130\\131\\32\\130\\131\\32\\32\\129\\32\\130\\131\\32\\130\\129\\32\\32\\129\\32\\32\\133\\32\\32\\32\\129\\32\\32\\32\\130\\32\\32\\32\\129\\32\", \"\\150\\140\\150\\137\\140\\148\\136\\140\\132\\150\\131\\132\\151\\131\\148\\136\\147\\129\\136\\147\\129\\150\\156\\145\\138\\143\\149\\130\\151\\32\\32\\32\\149\\138\\152\\129\\149\\32\\32\\157\\152\\149\\157\\144\\149\\150\\131\\148\", \"\\149\\143\\142\\149\\32\\149\\149\\32\\149\\149\\32\\144\\149\\32\\149\\149\\32\\32\\149\\32\\32\\149\\32\\149\\149\\32\\149\\32\\149\\32\\144\\32\\149\\149\\130\\148\\149\\32\\32\\149\\32\\149\\149\\130\\149\\149\\32\\149\", \"\\130\\131\\129\\129\\32\\129\\131\\131\\32\\130\\131\\32\\131\\131\\32\\131\\131\\129\\129\\32\\32\\130\\131\\32\\129\\32\\129\\130\\131\\32\\130\\131\\32\\129\\32\\129\\131\\131\\129\\129\\32\\129\\129\\32\\129\\130\\131\\32\", \"\\136\\140\\132\\150\\131\\148\\136\\140\\132\\153\\140\\129\\131\\151\\129\\149\\32\\149\\149\\32\\149\\149\\32\\149\\137\\152\\129\\137\\152\\129\\131\\156\\133\\149\\131\\32\\150\\32\\32\\130\\148\\32\\152\\137\\144\\32\\32\\32\", \"\\149\\32\\32\\149\\159\\133\\149\\32\\149\\144\\32\\149\\32\\149\\32\\149\\32\\149\\150\\151\\129\\138\\155\\149\\150\\130\\148\\32\\149\\32\\152\\129\\32\\149\\32\\32\\32\\150\\32\\32\\149\\32\\32\\32\\32\\32\\32\\32\", \"\\129\\32\\32\\130\\129\\129\\129\\32\\129\\130\\131\\32\\32\\129\\32\\130\\131\\32\\32\\129\\32\\129\\32\\129\\129\\32\\129\\32\\129\\32\\131\\131\\129\\130\\131\\32\\32\\32\\129\\130\\131\\32\\32\\32\\32\\140\\140\\132\", \"\\32\\154\\32\\159\\143\\32\\149\\143\\32\\159\\143\\32\\159\\144\\149\\159\\143\\32\\159\\137\\145\\159\\143\\144\\149\\143\\32\\32\\145\\32\\32\\32\\145\\149\\32\\144\\32\\149\\32\\143\\159\\32\\143\\143\\32\\159\\143\\32\", \"\\32\\32\\32\\152\\140\\149\\151\\32\\149\\149\\32\\145\\149\\130\\149\\157\\140\\133\\32\\149\\32\\154\\143\\149\\151\\32\\149\\32\\149\\32\\144\\32\\149\\149\\153\\32\\32\\149\\32\\149\\133\\149\\149\\32\\149\\149\\32\\149\", \"\\32\\32\\32\\130\\131\\129\\131\\131\\32\\130\\131\\32\\130\\131\\129\\130\\131\\129\\32\\129\\32\\140\\140\\129\\129\\32\\129\\32\\129\\32\\137\\140\\129\\130\\32\\129\\32\\130\\32\\129\\32\\129\\129\\32\\129\\130\\131\\32\", \"\\144\\143\\32\\159\\144\\144\\144\\143\\32\\159\\143\\144\\159\\138\\32\\144\\32\\144\\144\\32\\144\\144\\32\\144\\144\\32\\144\\144\\32\\144\\143\\143\\144\\32\\150\\129\\32\\149\\32\\130\\150\\32\\134\\137\\134\\134\\131\\148\", \"\\136\\143\\133\\154\\141\\149\\151\\32\\129\\137\\140\\144\\32\\149\\32\\149\\32\\149\\154\\159\\133\\149\\148\\149\\157\\153\\32\\154\\143\\149\\159\\134\\32\\130\\148\\32\\32\\149\\32\\32\\151\\129\\32\\32\\32\\32\\134\\32\", \"\\133\\32\\32\\32\\32\\133\\129\\32\\32\\131\\131\\32\\32\\130\\32\\130\\131\\129\\32\\129\\32\\130\\131\\129\\129\\32\\129\\140\\140\\129\\131\\131\\129\\32\\130\\129\\32\\129\\32\\130\\129\\32\\32\\32\\32\\32\\129\\32\", \"\\32\\32\\32\\32\\149\\32\\32\\149\\32\\32\\32\\32\\32\\32\\32\\32\\149\\32\\32\\149\\32\\32\\32\\32\\32\\32\\32\\32\\149\\32\\32\\149\\32\\32\\32\\32\\32\\32\\32\\32\\149\\32\\32\\149\\32\\32\\32\\32\", \"\\32\\32\\32\\32\\32\\32\\32\\32\\32\\32\\32\\32\\32\\149\\32\\32\\149\\32\\32\\149\\32\\32\\149\\32\\32\\149\\32\\32\\149\\32\\32\\149\\32\\32\\149\\32\\32\\32\\32\\32\\32\\32\\32\\32\\32\\32\\32\\32\", \"\\32\\32\\32\\32\\32\\32\\32\\32\\32\\32\\32\\32\\32\\32\\32\\32\\32\\32\\32\\32\\32\\32\\32\\32\\32\\32\\32\\32\\32\\32\\32\\32\\32\\32\\32\\32\\32\\32\\32\\32\\32\\32\\32\\32\\32\\32\\32\\32\", \"\\32\\32\\32\\32\\149\\32\\32\\149\\32\\32\\32\\32\\32\\32\\32\\32\\149\\32\\32\\149\\32\\32\\32\\32\\32\\32\\32\\32\\149\\32\\32\\149\\32\\32\\32\\32\\32\\32\\32\\32\\149\\32\\32\\149\\32\\32\\32\\32\", \"\\32\\32\\32\\32\\32\\32\\32\\32\\32\\32\\32\\32\\32\\149\\32\\32\\149\\32\\32\\149\\32\\32\\149\\32\\32\\149\\32\\32\\149\\32\\32\\149\\32\\32\\149\\32\\32\\32\\32\\32\\32\\32\\32\\32\\32\\32\\32\\32\", \"\\32\\149\\32\\32\\149\\32\\32\\149\\32\\32\\149\\32\\32\\149\\32\\32\\149\\32\\32\\149\\32\\32\\149\\32\\32\\149\\32\\32\\149\\32\\32\\149\\32\\32\\149\\32\\32\\149\\32\\32\\149\\32\\32\\149\\32\\32\\149\\32\", \"\\32\\32\\32\\32\\145\\32\\159\\139\\32\\151\\131\\132\\155\\143\\132\\134\\135\\145\\32\\149\\32\\158\\140\\129\\130\\130\\32\\152\\147\\155\\157\\134\\32\\32\\144\\144\\32\\32\\32\\32\\32\\32\\152\\131\\155\\131\\131\\129\", \"\\32\\32\\32\\32\\149\\32\\149\\32\\145\\148\\131\\32\\149\\32\\149\\140\\157\\132\\32\\148\\32\\137\\155\\149\\32\\32\\32\\149\\154\\149\\137\\142\\32\\153\\153\\32\\131\\131\\149\\131\\131\\129\\149\\135\\145\\32\\32\\32\", \"\\32\\32\\32\\32\\129\\32\\130\\135\\32\\131\\131\\129\\134\\131\\132\\32\\129\\32\\32\\129\\32\\131\\131\\32\\32\\32\\32\\130\\131\\129\\32\\32\\32\\32\\129\\129\\32\\32\\32\\32\\32\\32\\130\\131\\129\\32\\32\\32\", \"\\150\\150\\32\\32\\148\\32\\134\\32\\32\\132\\32\\32\\134\\32\\32\\144\\32\\144\\150\\151\\149\\32\\32\\32\\32\\32\\32\\145\\32\\32\\152\\140\\144\\144\\144\\32\\133\\151\\129\\133\\151\\129\\132\\151\\129\\32\\145\\32\", \"\\130\\129\\32\\131\\151\\129\\141\\32\\32\\142\\32\\32\\32\\32\\32\\149\\32\\149\\130\\149\\149\\32\\143\\32\\32\\32\\32\\142\\132\\32\\154\\143\\133\\157\\153\\132\\151\\150\\148\\151\\158\\132\\151\\150\\148\\144\\130\\148\", \"\\32\\32\\32\\140\\140\\132\\32\\32\\32\\32\\32\\32\\32\\32\\32\\151\\131\\32\\32\\129\\129\\32\\32\\32\\32\\134\\32\\32\\32\\32\\32\\32\\32\\129\\129\\32\\129\\32\\129\\129\\130\\129\\129\\32\\129\\130\\131\\32\", \"\\156\\143\\32\\159\\141\\129\\153\\140\\132\\153\\137\\32\\157\\141\\32\\159\\142\\32\\150\\151\\129\\150\\131\\132\\140\\143\\144\\143\\141\\145\\137\\140\\148\\141\\141\\144\\157\\142\\32\\159\\140\\32\\151\\134\\32\\157\\141\\32\", \"\\157\\140\\149\\157\\140\\149\\157\\140\\149\\157\\140\\149\\157\\140\\149\\157\\140\\149\\151\\151\\32\\154\\143\\132\\157\\140\\32\\157\\140\\32\\157\\140\\32\\157\\140\\32\\32\\149\\32\\32\\149\\32\\32\\149\\32\\32\\149\\32\", \"\\129\\32\\129\\129\\32\\129\\129\\32\\129\\129\\32\\129\\129\\32\\129\\129\\32\\129\\129\\131\\129\\32\\134\\32\\131\\131\\129\\131\\131\\129\\131\\131\\129\\131\\131\\129\\130\\131\\32\\130\\131\\32\\130\\131\\32\\130\\131\\32\", \"\\151\\131\\148\\152\\137\\145\\155\\140\\144\\152\\142\\145\\153\\140\\132\\153\\137\\32\\154\\142\\144\\155\\159\\132\\150\\156\\148\\147\\32\\144\\144\\130\\145\\136\\137\\32\\146\\130\\144\\144\\130\\145\\130\\136\\32\\151\\140\\132\", \"\\151\\32\\149\\151\\155\\149\\149\\32\\149\\149\\32\\149\\149\\32\\149\\149\\32\\149\\149\\32\\149\\152\\137\\144\\157\\129\\149\\149\\32\\149\\149\\32\\149\\149\\32\\149\\149\\32\\149\\130\\150\\32\\32\\157\\129\\149\\32\\149\", \"\\131\\131\\32\\129\\32\\129\\130\\131\\32\\130\\131\\32\\130\\131\\32\\130\\131\\32\\130\\131\\32\\32\\32\\32\\130\\131\\32\\130\\131\\32\\130\\131\\32\\130\\131\\32\\130\\131\\32\\32\\129\\32\\130\\131\\32\\133\\131\\32\", \"\\156\\143\\32\\159\\141\\129\\153\\140\\132\\153\\137\\32\\157\\141\\32\\159\\142\\32\\159\\159\\144\\152\\140\\144\\156\\143\\32\\159\\141\\129\\153\\140\\132\\157\\141\\32\\130\\145\\32\\32\\147\\32\\136\\153\\32\\130\\146\\32\", \"\\152\\140\\149\\152\\140\\149\\152\\140\\149\\152\\140\\149\\152\\140\\149\\152\\140\\149\\149\\157\\134\\154\\143\\132\\157\\140\\133\\157\\140\\133\\157\\140\\133\\157\\140\\133\\32\\149\\32\\32\\149\\32\\32\\149\\32\\32\\149\\32\", \"\\130\\131\\129\\130\\131\\129\\130\\131\\129\\130\\131\\129\\130\\131\\129\\130\\131\\129\\130\\130\\131\\32\\134\\32\\130\\131\\129\\130\\131\\129\\130\\131\\129\\130\\131\\129\\32\\129\\32\\32\\129\\32\\32\\129\\32\\32\\129\\32\", \"\\159\\134\\144\\137\\137\\32\\156\\143\\32\\159\\141\\129\\153\\140\\132\\153\\137\\32\\157\\141\\32\\32\\132\\32\\159\\143\\32\\147\\32\\144\\144\\130\\145\\136\\137\\32\\146\\130\\144\\144\\130\\145\\130\\138\\32\\146\\130\\144\", \"\\149\\32\\149\\149\\32\\149\\149\\32\\149\\149\\32\\149\\149\\32\\149\\149\\32\\149\\149\\32\\149\\131\\147\\129\\138\\134\\149\\149\\32\\149\\149\\32\\149\\149\\32\\149\\149\\32\\149\\154\\143\\149\\32\\157\\129\\154\\143\\149\", \"\\130\\131\\32\\129\\32\\129\\130\\131\\32\\130\\131\\32\\130\\131\\32\\130\\131\\32\\130\\131\\32\\32\\32\\32\\130\\131\\32\\130\\131\\129\\130\\131\\129\\130\\131\\129\\130\\131\\129\\140\\140\\129\\130\\131\\32\\140\\140\\129\" }, {[[000110000110110000110010101000000010000000100101]], [[000000110110000000000010101000000010000000100101]], [[000000000000000000000000000000000000000000000000]], [[100010110100000010000110110000010100000100000110]], [[000000110000000010110110000110000000000000110000]], [[000000000000000000000000000000000000000000000000]], [[000000110110000010000000100000100000000000000010]], [[000000000110110100010000000010000000000000000100]], [[000000000000000000000000000000000000000000000000]], [[010000000000100110000000000000000000000110010000]], [[000000000000000000000000000010000000010110000000]], [[000000000000000000000000000000000000000000000000]], [[011110110000000100100010110000000100000000000000]], [[000000000000000000000000000000000000000000000000]], [[000000000000000000000000000000000000000000000000]], [[110000110110000000000000000000010100100010000000]], [[000010000000000000110110000000000100010010000000]], [[000000000000000000000000000000000000000000000000]], [[010110010110100110110110010000000100000110110110]], [[000000000000000000000110000000000110000000000000]], [[000000000000000000000000000000000000000000000000]], [[010100010110110000000000000000110000000010000000]], [[110110000000000000110000110110100000000010000000]], [[000000000000000000000000000000000000000000000000]], [[000100011111000100011111000100011111000100011111]], [[000000000000100100100100011011011011111111111111]], [[000000000000000000000000000000000000000000000000]], [[000100011111000100011111000100011111000100011111]], [[000000000000100100100100011011011011111111111111]], [[100100100100100100100100100100100100100100100100]], [[000000110100110110000010000011110000000000011000]], [[000000000100000000000010000011000110000000001000]], [[000000000000000000000000000000000000000000000000]], [[010000100100000000000000000100000000010010110000]], [[000000000000000000000000000000110110110110110000]], [[000000000000000000000000000000000000000000000000]], [[110110110110110110000000110110110110110110110110]], [[000000000000000000000110000000000000000000000000]], [[000000000000000000000000000000000000000000000000]], [[000000000000110110000110010000000000000000010010]], [[000010000000000000000000000000000000000000000000]], [[000000000000000000000000000000000000000000000000]], [[110110110110110110110000110110110110000000000000]], [[000000000000000000000110000000000000000000000000]], [[000000000000000000000000000000000000000000000000]], [[110110110110110110110000110000000000000000010000]], [[000000000000000000000000100000000000000110000110]], [[000000000000000000000000000000000000000000000000]] }}\
256\
257if krist then\
258 rawFont[1][31] = \"\\32\\32\\32\\32\\145\\32\\159\\139\\32\\151\\131\\132\\133\\135\\145\\134\\135\\145\\32\\149\\32\\158\\140\\129\\130\\130\\32\\152\\147\\155\\157\\134\\32\\32\\144\\144\\32\\32\\32\\32\\32\\32\\152\\131\\155\\131\\131\\129\"\
259 rawFont[1][32] = \"\\32\\32\\32\\32\\149\\32\\149\\32\\145\\148\\131\\32\\145\\146\\132\\140\\157\\132\\32\\148\\32\\137\\155\\149\\32\\32\\32\\149\\154\\149\\137\\142\\32\\153\\153\\32\\131\\131\\149\\131\\131\\129\\149\\135\\145\\32\\32\\32\"\
260 rawFont[1][33] = \"\\32\\32\\32\\32\\129\\32\\130\\135\\32\\131\\131\\129\\130\\128\\129\\32\\129\\32\\32\\129\\32\\131\\131\\32\\32\\32\\32\\130\\131\\129\\32\\32\\32\\32\\129\\129\\32\\32\\32\\32\\32\\32\\130\\131\\129\\32\\32\\32\"\
261 rawFont[2][32] = [[000000000100110000000010000011000110000000001000]]\
262end\
263--### Genarate fonts using 3x3 chars per a character. (1 character is 6x9 pixels)\
264local fonts = {}\
265local firstFont = {}\
266do\
267 local char = 0\
268 local height = #rawFont[1]\
269 local length = #rawFont[1][1]\
270 for i = 1, height, 3 do\
271 for j = 1, length, 3 do\
272 local thisChar = string.char(char)\
273\
274 local temp = {}\
275 temp[1] = rawFont[1][i]:sub(j, j + 2)\
276 temp[2] = rawFont[1][i + 1]:sub(j, j + 2)\
277 temp[3] = rawFont[1][i + 2]:sub(j, j + 2)\
278\
279 local temp2 = {}\
280 temp2[1] = rawFont[2][i]:sub(j, j + 2)\
281 temp2[2] = rawFont[2][i + 1]:sub(j, j + 2)\
282 temp2[3] = rawFont[2][i + 2]:sub(j, j + 2)\
283\
284 firstFont[thisChar] = {temp, temp2}\
285 char = char + 1\
286 end\
287 end\
288 fonts[1] = firstFont\
289end\
290\
291local function generateFontSize(size,yeld)\
292 local inverter = {[\"0\"] = \"1\", [\"1\"] = \"0\"} --:gsub(\"[01]\",inverter)\
293 if size<= #fonts then return true end\
294 for f = #fonts+1, size do\
295 --automagicly make bigger fonts using firstFont and fonts[f-1].\
296 local nextFont = {}\
297 local lastFont = fonts[f - 1]\
298 for char = 0, 255 do\
299 local thisChar = string.char(char)\
300 --sleep(0) print(f,thisChar)\
301\
302 local temp = {}\
303 local temp2 = {}\
304\
305 local templateChar = lastFont[thisChar][1]\
306 local templateBack = lastFont[thisChar][2]\
307 for i = 1, #templateChar do\
308 local line1, line2, line3, back1, back2, back3 = {}, {}, {}, {}, {}, {}\
309 for j = 1, #templateChar[1] do\
310 local currentChar = firstFont[templateChar[i]:sub(j, j)][1]\
311 table.insert(line1, currentChar[1])\
312 table.insert(line2, currentChar[2])\
313 table.insert(line3, currentChar[3])\
314\
315 local currentBack = firstFont[templateChar[i]:sub(j, j)][2]\
316 if templateBack[i]:sub(j, j) == \"1\" then\
317 table.insert(back1, (currentBack[1]:gsub(\"[01]\", inverter)))\
318 table.insert(back2, (currentBack[2]:gsub(\"[01]\", inverter)))\
319 table.insert(back3, (currentBack[3]:gsub(\"[01]\", inverter)))\
320 else\
321 table.insert(back1, currentBack[1])\
322 table.insert(back2, currentBack[2])\
323 table.insert(back3, currentBack[3])\
324 end\
325 end\
326 table.insert(temp, table.concat(line1))\
327 table.insert(temp, table.concat(line2))\
328 table.insert(temp, table.concat(line3))\
329 table.insert(temp2, table.concat(back1))\
330 table.insert(temp2, table.concat(back2))\
331 table.insert(temp2, table.concat(back3))\
332 end\
333\
334 nextFont[thisChar] = {temp, temp2}\
335 if yeld then yeld = \"Font\"..f..\"Yeld\"..char os.queueEvent(yeld) os.pullEvent(yeld) end\
336 end\
337 fonts[f] = nextFont\
338 end\
339 return true\
340end\
341\
342generateFontSize(3,false)\
343\
344--## Use pre-generated fonts instead of old code above.\
345\
346--local fonts = {}\
347\
348local tHex = {[ colors.white ] = \"0\", [ colors.orange ] = \"1\", [ colors.magenta ] = \"2\", [ colors.lightBlue ] = \"3\", [ colors.yellow ] = \"4\", [ colors.lime ] = \"5\", [ colors.pink ] = \"6\", [ colors.gray ] = \"7\", [ colors.lightGray ] = \"8\", [ colors.cyan ] = \"9\", [ colors.purple ] = \"a\", [ colors.blue ] = \"b\", [ colors.brown ] = \"c\", [ colors.green ] = \"d\", [ colors.red ] = \"e\", [ colors.black ] = \"f\"}\
349\
350--# Write data on terminal in specified location. Can scroll.\
351local function stamp(tTerminal, tData, nX, nY)\
352\
353 local oX, oY = tTerminal.getSize()\
354 local cX, cY = #tData[1][1], #tData[1]\
355 nX = nX or math.floor((oX - cX) / 2) + 1\
356 nY = nY or math.floor((oY - cY) / 2) + 1\
357\
358 for i = 1, cY do\
359 if i > 1 and nY + i - 1 > oY then term.scroll(1) nY = nY - 1 end\
360 tTerminal.setCursorPos(nX, nY + i - 1)\
361 tTerminal.blit(tData[1][i], tData[2][i], tData[3][i])\
362 end\
363end\
364\
365--# Write data on terminal in specified location. No scroll.\
366local function press(tTerminal, tData, nX, nY)\
367 local oX, oY = tTerminal.getSize()\
368 local cX, cY = #tData[1][1], #tData[1]\
369 nX = nX or math.floor((oX - cX) / 2) + 1\
370 nY = nY or math.floor((oY - cY) / 2) + 1\
371\
372 for i = 1, cY do\
373 tTerminal.setCursorPos(nX, nY + i - 1)\
374 tTerminal.blit(tData[1][i], tData[2][i], tData[3][i])\
375 end\
376end\
377\
378--# Generate data from strings for data and colors.\
379local function makeText(nSize, sString, nFC, nBC, bBlit)\
380 if not type(sString) == \"string\" then error(\"Not a String\",3) end --this should never happend with expects in place.\
381 local cFC = type(nFC) == \"string\" and nFC:sub(1, 1) or tHex[nFC] or error(\"Wrong Front Color\",3)\
382 local cBC = type(nBC) == \"string\" and nBC:sub(1, 1) or tHex[nBC] or error(\"Wrong Back Color\",3)\
383 local font = fonts[nSize] or error(\"Wrong font size selected\",3)\
384 if sString == \"\" then return {{\"\"}, {\"\"}, {\"\"}} end\
385 \
386 local input = {}\
387 for i in sString:gmatch('.') do table.insert(input, i) end\
388\
389 local tText = {}\
390 local height = #font[input[1]][1]\
391\
392\
393 for nLine = 1, height do\
394 local outLine = {}\
395 for i = 1, #input do\
396 outLine[i] = font[input[i]] and font[input[i]][1][nLine] or \"\"\
397 end\
398 tText[nLine] = table.concat(outLine)\
399 end\
400\
401 local tFront = {}\
402 local tBack = {}\
403 local tFrontSub = {[\"0\"] = cFC, [\"1\"] = cBC}\
404 local tBackSub = {[\"0\"] = cBC, [\"1\"] = cFC}\
405\
406 for nLine = 1, height do\
407 local front = {}\
408 local back = {}\
409 for i = 1, #input do\
410 local template = font[input[i]] and font[input[i]][2][nLine] or \"\"\
411 front[i] = template:gsub(\"[01]\", bBlit and {[\"0\"] = nFC:sub(i, i), [\"1\"] = nBC:sub(i, i)} or tFrontSub)\
412 back[i] = template:gsub(\"[01]\", bBlit and {[\"0\"] = nBC:sub(i, i), [\"1\"] = nFC:sub(i, i)} or tBackSub)\
413 end\
414 tFront[nLine] = table.concat(front)\
415 tBack[nLine] = table.concat(back)\
416 end\
417\
418 return {tText, tFront, tBack}\
419end\
420\
421--# Writing in big font using current terminal settings.\
422b.bigWrite = function(sString)\
423 expect(1, sString, \"string\")\
424 stamp(term, makeText(1, sString, term.getTextColor(), term.getBackgroundColor()), term.getCursorPos())\
425 local x, y = term.getCursorPos()\
426 term.setCursorPos(x, y - 2)\
427end\
428\
429b.bigBlit = function(sString, sFront, sBack)\
430 expect(1, sString, \"string\")\
431 expect(2, sFront, \"string\")\
432 expect(3, sBack, \"string\")\
433 if #sString ~= #sFront then error(\"Invalid length of text color string\",2) end\
434 if #sString ~= #sBack then error(\"Invalid length of background color string\",2) end\
435 stamp(term, makeText(1, sString, sFront, sBack, true), term.getCursorPos())\
436 local x, y = term.getCursorPos()\
437 term.setCursorPos(x, y - 2)\
438end\
439\
440b.bigPrint = function(sString)\
441 expect(1, sString, \"string\")\
442 stamp(term, makeText(1, sString, term.getTextColor(), term.getBackgroundColor()), term.getCursorPos())\
443 print()\
444end\
445\
446--# Writing in huge font using current terminal settings.\
447b.hugeWrite = function(sString)\
448 expect(1, sString, \"string\")\
449 stamp(term, makeText(2, sString, term.getTextColor(), term.getBackgroundColor()), term.getCursorPos())\
450 local x, y = term.getCursorPos()\
451 term.setCursorPos(x, y - 8)\
452end\
453\
454b.hugeBlit = function(sString, sFront, sBack)\
455 expect(1, sString, \"string\")\
456 expect(2, sFront, \"string\")\
457 expect(3, sBack, \"string\")\
458 if #sString ~= #sFront then error(\"Invalid length of text color string\",2) end\
459 if #sString ~= #sBack then error(\"Invalid length of background color string\",2) end\
460 stamp(term, makeText(2, sString, sFront, sBack, true), term.getCursorPos())\
461 local x, y = term.getCursorPos()\
462 term.setCursorPos(x, y - 8)\
463end\
464\
465b.hugePrint = function(sString)\
466 expect(1, sString, \"string\")\
467 stamp(term, makeText(2, sString, term.getTextColor(), term.getBackgroundColor()), term.getCursorPos())\
468 print()\
469end\
470\
471--# Write/blit string on terminal in specified location\
472b.doc.writeOn = [[writeOn(tTerminal, nSize, sString, [nX], [nY]) - Writes sString on tTerminal using current tTerminal colours. nX, nY are coordinates. If any of them are nil then text is centered in that axis using tTerminal size.]]\
473b.writeOn = function(tTerminal, nSize, sString, nX, nY)\
474 expect(1, tTerminal, \"table\")\
475 field(tTerminal, \"getSize\", \"function\")\
476 field(tTerminal, \"scroll\", \"function\")\
477 field(tTerminal, \"setCursorPos\", \"function\")\
478 field(tTerminal, \"blit\", \"function\")\
479 field(tTerminal, \"getTextColor\", \"function\")\
480 field(tTerminal, \"getBackgroundColor\", \"function\")\
481 expect(2, nSize, \"number\")\
482 expect(3, sString, \"string\")\
483 expect(3, nX, \"number\", \"nil\")\
484 expect(3, nY, \"number\", \"nil\")\
485 press(tTerminal, makeText(nSize, sString, tTerminal.getTextColor(), tTerminal.getBackgroundColor()), nX, nY)\
486end\
487\
488b.doc.blitOn = [[writeOn(tTerminal, nSize, sString, sFront, sBack, [nX], [nY]) - Blits sString on tTerminal with sFront and sBack colors . nX, nY are coordinates. If any of them are nil then text is centered in that axis using tTerminal size.]]\
489b.blitOn = function(tTerminal, nSize, sString, sFront, sBack, nX, nY)\
490 expect(1, tTerminal, \"table\")\
491 field(tTerminal, \"getSize\", \"function\")\
492 field(tTerminal, \"scroll\", \"function\")\
493 field(tTerminal, \"setCursorPos\", \"function\")\
494 field(tTerminal, \"blit\", \"function\")\
495 expect(2, nSize, \"number\")\
496 expect(3, sString, \"string\")\
497 expect(4, sFront, \"string\")\
498 expect(5, sBack, \"string\")\
499 if #sString ~= #sFront then error(\"Invalid length of text color string\",2) end\
500 if #sString ~= #sBack then error(\"Invalid length of background color string\",2) end\
501 expect(6, nX, \"number\", \"nil\")\
502 expect(7, nY, \"number\", \"nil\")\
503 press(tTerminal, makeText(nSize, sString, sFront, sBack, true), nX, nY)\
504end\
505\
506--# \
507b.doc.makeBlittleText = [[makeBlittleText(nSize, sString, nFC, nBC) - Generate blittle object in size nSize with text sString in blittle format for printing with that api. nFC and nBC are colors to generate the object with.]]\
508b.makeBlittleText = function(nSize, sString, nFC, nBC)\
509 expect(1, nSize, \"number\")\
510 expect(2, sString, \"string\")\
511 expect(3, nFC, \"number\")\
512 expect(4, nBC, \"number\")\
513 local out = makeText(nSize, sString, nFC, nBC)\
514 out.height = #out[1]\
515 out.width = #out[1][1]\
516 return out\
517end\
518\
519b.doc.generateFontSize = [[generateFontSize(size) - Generates bigger font sizes and enables then on other functions that accept size argument. By default bigfont loads sizes 1-3 as those can be generated without yielding. Using this user can generate sizes 4-6. Warning: This function will internally yield.]]\
520b.generateFontSize = function(size)\
521 expect(1, size, \"number\")\
522 if type(size) ~= \"number\" then error(\"Size needs to be a number\",2) end\
523 if size > 6 then return false end\
524 return generateFontSize(math.floor(size),true)\
525end\
526\
527--### Finalizing\
528return b",
529 [ "startup.lua" ] = "shell.run(\"keypad\")",
530 [ "libraries/sha256.lua" ] = "-- SHA-256, HMAC and PBKDF2 functions in ComputerCraft\
531-- By Anavrins\
532-- MIT License\
533-- Pastebin: https://pastebin.com/6UV4qfNF\
534-- Usage: https://pastebin.com/q2SQ7eRg\
535-- Last updated: March 27 2020\
536\
537local mod32 = 2^32\
538local band = bit32 and bit32.band or bit.band\
539local bnot = bit32 and bit32.bnot or bit.bnot\
540local bxor = bit32 and bit32.bxor or bit.bxor\
541local blshift = bit32 and bit32.lshift or bit.blshift\
542local upack = unpack\
543\
544local function rrotate(n, b)\
545 local s = n/(2^b)\
546 local f = s%1\
547 return (s-f) + f*mod32\
548end\
549local function brshift(int, by)\
550 local s = int / (2^by)\
551 return s - s%1\
552end\
553\
554local H = {\
555 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,\
556 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,\
557}\
558\
559local K = {\
560 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,\
561 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,\
562 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,\
563 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,\
564 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,\
565 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,\
566 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,\
567 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,\
568}\
569\
570local function counter(incr)\
571 local t1, t2 = 0, 0\
572 if 0xFFFFFFFF - t1 < incr then\
573 t2 = t2 + 1\
574 t1 = incr - (0xFFFFFFFF - t1) - 1 \
575 else t1 = t1 + incr\
576 end\
577 return t2, t1\
578end\
579\
580local function BE_toInt(bs, i)\
581 return blshift((bs[i] or 0), 24) + blshift((bs[i+1] or 0), 16) + blshift((bs[i+2] or 0), 8) + (bs[i+3] or 0)\
582end\
583\
584local function preprocess(data)\
585 local len = #data\
586 local proc = {}\
587 data[#data+1] = 0x80\
588 while #data%64~=56 do data[#data+1] = 0 end\
589 local blocks = math.ceil(#data/64)\
590 for i = 1, blocks do\
591 proc[i] = {}\
592 for j = 1, 16 do\
593 proc[i][j] = BE_toInt(data, 1+((i-1)*64)+((j-1)*4))\
594 end\
595 end\
596 proc[blocks][15], proc[blocks][16] = counter(len*8)\
597 return proc\
598end\
599\
600local function digestblock(w, C)\
601 for j = 17, 64 do\
602 local v = w[j-15]\
603 local s0 = bxor(rrotate(w[j-15], 7), rrotate(w[j-15], 18), brshift(w[j-15], 3))\
604 local s1 = bxor(rrotate(w[j-2], 17), rrotate(w[j-2], 19),brshift(w[j-2], 10))\
605 w[j] = (w[j-16] + s0 + w[j-7] + s1)%mod32\
606 end\
607 local a, b, c, d, e, f, g, h = upack(C)\
608 for j = 1, 64 do\
609 local S1 = bxor(rrotate(e, 6), rrotate(e, 11), rrotate(e, 25))\
610 local ch = bxor(band(e, f), band(bnot(e), g))\
611 local temp1 = (h + S1 + ch + K[j] + w[j])%mod32\
612 local S0 = bxor(rrotate(a, 2), rrotate(a, 13), rrotate(a, 22))\
613 local maj = bxor(bxor(band(a, b), band(a, c)), band(b, c))\
614 local temp2 = (S0 + maj)%mod32\
615 h, g, f, e, d, c, b, a = g, f, e, (d+temp1)%mod32, c, b, a, (temp1+temp2)%mod32\
616 end\
617 C[1] = (C[1] + a)%mod32\
618 C[2] = (C[2] + b)%mod32\
619 C[3] = (C[3] + c)%mod32\
620 C[4] = (C[4] + d)%mod32\
621 C[5] = (C[5] + e)%mod32\
622 C[6] = (C[6] + f)%mod32\
623 C[7] = (C[7] + g)%mod32\
624 C[8] = (C[8] + h)%mod32\
625 return C\
626end\
627\
628local mt = {\
629 __tostring = function(a) return string.char(unpack(a)) end,\
630 __index = {\
631 toHex = function(self, s) return (\"%02x\"):rep(#self):format(unpack(self)) end,\
632 isEqual = function(self, t)\
633 if type(t) ~= \"table\" then return false end\
634 if #self ~= #t then return false end\
635 local ret = 0\
636 for i = 1, #self do\
637 ret = bit32.bor(ret, bxor(self[i], t[i]))\
638 end\
639 return ret == 0\
640 end\
641 }\
642}\
643\
644local function toBytes(t, n)\
645 local b = {}\
646 for i = 1, n do\
647 b[(i-1)*4+1] = band(brshift(t[i], 24), 0xFF)\
648 b[(i-1)*4+2] = band(brshift(t[i], 16), 0xFF)\
649 b[(i-1)*4+3] = band(brshift(t[i], 8), 0xFF)\
650 b[(i-1)*4+4] = band(t[i], 0xFF)\
651 end\
652 return setmetatable(b, mt)\
653end\
654\
655local function digest(data)\
656 local data = data or \"\"\
657 data = type(data) == \"table\" and {upack(data)} or {tostring(data):byte(1,-1)}\
658\
659 data = preprocess(data)\
660 local C = {upack(H)}\
661 for i = 1, #data do C = digestblock(data[i], C) end\
662 return toBytes(C, 8)\
663end\
664\
665local function hmac(data, key)\
666 local data = type(data) == \"table\" and {upack(data)} or {tostring(data):byte(1,-1)}\
667 local key = type(key) == \"table\" and {upack(key)} or {tostring(key):byte(1,-1)}\
668\
669 local blocksize = 64\
670\
671 key = #key > blocksize and digest(key) or key\
672\
673 local ipad = {}\
674 local opad = {}\
675 local padded_key = {}\
676\
677 for i = 1, blocksize do\
678 ipad[i] = bxor(0x36, key[i] or 0)\
679 opad[i] = bxor(0x5C, key[i] or 0)\
680 end\
681\
682 for i = 1, #data do\
683 ipad[blocksize+i] = data[i]\
684 end\
685\
686 ipad = digest(ipad)\
687\
688 for i = 1, blocksize do\
689 padded_key[i] = opad[i]\
690 padded_key[blocksize+i] = ipad[i]\
691 end\
692\
693 return digest(padded_key)\
694end\
695\
696local function pbkdf2(pass, salt, iter, dklen)\
697 local salt = type(salt) == \"table\" and salt or {tostring(salt):byte(1,-1)}\
698 local hashlen = 32\
699 local dklen = dklen or 32\
700 local block = 1\
701 local out = {}\
702\
703 while dklen > 0 do\
704 local ikey = {}\
705 local isalt = {upack(salt)}\
706 local clen = dklen > hashlen and hashlen or dklen\
707\
708 isalt[#isalt+1] = band(brshift(block, 24), 0xFF)\
709 isalt[#isalt+1] = band(brshift(block, 16), 0xFF)\
710 isalt[#isalt+1] = band(brshift(block, 8), 0xFF)\
711 isalt[#isalt+1] = band(block, 0xFF)\
712\
713 for j = 1, iter do\
714 isalt = hmac(isalt, pass)\
715 for k = 1, clen do ikey[k] = bxor(isalt[k], ikey[k] or 0) end\
716 if j % 200 == 0 then os.queueEvent(\"PBKDF2\", j) coroutine.yield(\"PBKDF2\") end\
717 end\
718 dklen = dklen - clen\
719 block = block+1\
720 for k = 1, clen do out[#out+1] = ikey[k] end\
721 end\
722\
723 return setmetatable(out, mt)\
724end\
725\
726return {\
727 digest = digest,\
728 hmac = hmac,\
729 pbkdf2 = pbkdf2,\
730}",
731 [ ".keypad-password.txt" ] = "fdb9b6233b450d05b7077e779445724620e69d1e3e8c528ad1cc2b038fceb88f",
732 [ "keypad.lua" ] = "local sUtils = require(\"libraries.sUtils\")\
733local button = require(\"libraries.button\")\
734local sha256 = require(\"libraries.sha256\")\
735local bigfont = require(\"libraries.bigfont\")\
736\
737local image = sUtils.asset.load(\"keypad-image.skimg\")\
738local password = sUtils.fread(\".keypad-password.txt\") -- This b hashed. Set it up with `keypad setup`\
739\
740local tArgs = {...}\
741\
742local numbers = {[\"0\"]=true,[\"1\"]=true,[\"2\"]=true,[\"3\"]=true,[\"4\"]=true,[\"5\"]=true,[\"6\"]=true,[\"7\"]=true,[\"8\"]=true,[\"9\"]=true}\
743local function isDigits(str)\
744 for x in str:gmatch(\".\") do\
745 if not numbers[x] then\
746 return false\
747 end\
748 end\
749 return true\
750end\
751\
752if tArgs[1] == \"setup\" then\
753 term.setTextColour(colours.black)\
754 term.setBackgroundColour(colours.white)\
755 term.clear()\
756 term.setCursorPos(1,1)\
757 term.write(\"Enter the new passcode (Only numeric digits!)\")\
758 term.setCursorPos(1,2)\
759 local newPassword = read()\
760 if not isDigits(newPassword) then\
761 printError(\"Please enter only digits!\")\
762 error(\"Restart setup to try again!\",0)\
763 end\
764 -- Now hash and write the password to file \
765 local hash = sha256.pbkdf2(newPassword,\"monitor-keypad-salt\",25):toHex()\
766 local f = fs.open(\".keypad-password.txt\",\"w\")\
767 f.write(hash)\
768 f.close()\
769 return\
770end\
771\
772local displayOn = {\
773 [\"monitor_442\"] = true,\
774 [\"monitor_441\"] = true\
775}\
776\
777local function open()\
778 rs.setOutput(\"back\",true)\
779 sleep(0.5)\
780 rs.setOutput(\"back\",false)\
781end\
782\
783local function close()\
784 rs.setOutput(\"top\",true)\
785 sleep(0.5)\
786 rs.setOutput(\"top\",false)\
787end\
788\
789for k in pairs(displayOn) do\
790 displayOn[k] = peripheral.wrap(k)\
791end\
792\
793local function blit(t,f,g)\
794 for _,v in pairs(displayOn) do\
795 v.blit(t,f,g)\
796 end\
797end\
798\
799local function setCursorPos(x,y)\
800 for _,v in pairs(displayOn) do\
801 v.setCursorPos(x,y)\
802 end\
803end\
804\
805local function write(txt)\
806 for _,v in pairs(displayOn) do\
807 v.write(txt)\
808 end\
809end\
810\
811local function setTextColour(col)\
812 for _,v in pairs(displayOn) do\
813 v.setTextColour(col)\
814 end\
815end\
816\
817local function setBackgroundColour(col)\
818 for _,v in pairs(displayOn) do\
819 v.setBackgroundColour(col)\
820 end\
821end\
822\
823local function clear()\
824 for _,v in pairs(displayOn) do\
825 v.clear()\
826 end\
827end\
828\
829local function writeOn(size,str,x,y)\
830 for _,v in pairs(displayOn) do\
831 bigfont.writeOn(v,size,str,x,y)\
832 end\
833end\
834\
835local function drawSkimg(img,x,y)\
836 for _,v in pairs(displayOn) do\
837 sUtils.asset.drawSkimg(img,x,y,v)\
838 end\
839end\
840\
841drawSkimg(image)\
842\
843local passCode = {}\
844\
845-- create buttons\
846button.newButton(2,3,1,1,function() table.insert(passCode,1) end)\
847button.newButton(3,3,1,1,function() table.insert(passCode,2) end)\
848button.newButton(4,3,1,1,function() table.insert(passCode,3) end)\
849button.newButton(2,4,1,1,function() table.insert(passCode,4) end)\
850button.newButton(3,4,1,1,function() table.insert(passCode,5) end)\
851button.newButton(4,4,1,1,function() table.insert(passCode,6) end)\
852button.newButton(2,5,1,1,function() table.insert(passCode,7) end)\
853button.newButton(3,5,1,1,function() table.insert(passCode,8) end)\
854button.newButton(4,5,1,1,function() table.insert(passCode,9) end)\
855button.newButton(5,5,1,1,function() table.insert(passCode,0) end)\
856\
857\
858local function cancel()\
859 passCode = {}\
860 setCursorPos(1,1)\
861 blit(\" \",\"0000000\",\"0888880\")\
862end\
863\
864local function accept()\
865 if #passCode == 5 then\
866 local code = table.concat(passCode)\
867 local hash = sha256.pbkdf2(code,\"monitor-keypad-salt\",25):toHex()\
868 if hash == password then\
869 clear()\
870 setTextColour(colours.green)\
871 setBackgroundColour(colours.white)\
872 open()\
873 for i=3,0,-1 do\
874 clear()\
875 writeOn(1,tostring(i))\
876 sleep(1)\
877 end\
878 setTextColour(colours.orange)\
879 for i=14,0,-1 do\
880 clear()\
881 writeOn(1,tostring(i))\
882 sleep(1)\
883 end\
884 clear()\
885 setTextColour(colours.red)\
886 close()\
887 for i=3,0,-1 do\
888 clear()\
889 writeOn(1,tostring(i))\
890 sleep(1)\
891 end\
892 clear()\
893 drawSkimg(image)\
894 else\
895\
896 end\
897 passCode = {}\
898 end\
899end\
900\
901local buttonAccept = button.newButton(5,4,1,1,accept)\
902local buttonCancel = button.newButton(5,3,1,1,cancel)\
903\
904while true do\
905 local e = {os.pullEvent()}\
906 if e[1] == \"monitor_touch\" then\
907 e[1] = \"mouse_click\"\
908 end\
909 button.executeButtons(e)\
910 local currentCode = table.concat(passCode)\
911 if #passCode <= 5 then\
912 setCursorPos(2,1)\
913 setTextColour(colours.black)\
914 setBackgroundColour(colours.lightGrey)\
915 write(currentCode)\
916 else\
917 cancel()\
918 end\
919 sleep(0.1)\
920end",
921 [ "libraries/sUtils.lua" ] = "--- sUtils is a utility api with a large amount of functions for various purposes\
922-- @module[kind=misc] sUtils\
923\
924local expect = require(\"cc.expect\").expect\
925local nft = require(\"cc.image.nft\")\
926\
927--- Loop through a table, and check if it contains the value specified\
928-- @tparam table Table to loop through.\
929-- @tparam any value Value to look for in the table.\
930-- @treturn boolean True if the table contains the value.\
931local function numericallyContains(t, value)\
932 expect(1,t,\"table\")\
933 expect(1,value,\"any\")\
934 for i = 1, #t do\
935 if t[i] == value then\
936 return true\
937 end\
938 end\
939 return false\
940end\
941\
942--- Loop through a table, and check if it contains the value specified\
943-- @tparam table Table to loop through.\
944-- @tparam any value Value to look for in the table.\
945-- @treturn boolean True if the table contains the value.\
946local function keyContains(t, value)\
947 expect(1,t,\"table\")\
948 expect(1,value,\"any\")\
949 for k,v in pairs(t) do\
950 if k == value or v == value then\
951 return true\
952 end\
953 end\
954 return false\
955end\
956\
957--- Grab a file from the internet and save it in the file path.\
958-- @tparam string file Path to the file to save in.\
959-- @tparam string url URL to get the content from.\
960local function getFile(sFilename, sNetAddress, nFails)\
961 expect(1,sFilename,\"string\")\
962 expect(1,sNetAddress,\"string\")\
963 nFails = nFails or 0\
964 if nFails > 5 then\
965 error(\"Failed too many times. Stopping.\", 2)\
966 end\
967 \
968 local h, err = http.get(sNetAddress)\
969 if h then\
970 local fh, err2 = io.open(sFilename, 'w')\
971 if fh then\
972 fh:write(h:readAll()):close()\
973 h.close()\
974 else\
975 h.close()\
976 printError(\"Failed to write file: \" .. err2,2)\
977 getFile(sFilename, sNetAddress, nFails + 1)\
978 end\
979 else\
980 printError(\"Failed to connect: \" .. err,2)\
981 getFile(sFilename, sNetAddress, nFails + 1)\
982 end\
983end\
984\
985--- Split a string by it's separator.\
986-- @tparam string inputstr String to split.\
987-- @tparam string sep Separator to split the string by.\
988-- @treturn table Table containing the split string.\
989local function split(inputstr, sep)\
990 expect(1,inputstr,\"string\")\
991 expect(1,sep,\"string\",\"nil\")\
992 sep = sep or \",\"\
993 local t={}\
994 for str in string.gmatch(inputstr, \"([^\"..sep..\"]+)\") do\
995 table.insert(t, str)\
996 end\
997 return t\
998end\
999\
1000--- Count the number of lines in the file.\
1001-- @tparam string file File to count the lines of.\
1002-- @treturn number lines Amount of lines in the file.\
1003local function countLines(path)\
1004 expect(1,path,\"string\")\
1005 local lines = 0 \
1006 for _ in io.lines(path) do lines = lines + 1 end \
1007 return lines\
1008end\
1009\
1010--- Returns a boolean on if the number is odd or not.\
1011-- @tparam number num Number to check the oddness.\
1012-- @treturn boolean odd True if the number is odd.\
1013local function isOdd(num)\
1014 return num % 2 == 0\
1015end\
1016\
1017--- Recursively get the size of a folder.\
1018-- @tparam string path Path to the folder or file.\
1019-- @tparam[opt=false] boolean ignoreRom Whether or not to discard all entries of `rom`.\
1020-- @treturn number size Size of the folder or file.\
1021local function getSize(path,ignoreRom)\
1022 expect(1,path,\"string\")\
1023 expect(2,ignoreRom,\"boolean\",\"nil\")\
1024 local size = 0\
1025 local files = fs.list(path)\
1026 for _,v in pairs(files) do\
1027 if not ignoreRom or v ~= \"rom\" then\
1028 if fs.isDir(fs.combine(path, v)) then\
1029 size = size + getSize(fs.combine(path, v))\
1030 else\
1031 size = size + fs.getSize(fs.combine(path, v))\
1032 end\
1033 end\
1034 end\
1035 return size\
1036end\
1037\
1038--- Cut or pad a string to length.\
1039-- @tparam string str String to cut or pad.\
1040-- @tparam number len Length to cut or pad to.\
1041-- @tparam[opt] string pad Padding to extend the string if necessary. Defaults to \" \".\
1042-- @treturn string Cut or padded string.\
1043local function cut(str,len,pad)\
1044 pad = pad or \" \"\
1045 return str:sub(1,len) .. pad:rep(len - #str)\
1046end\
1047\
1048--- Splice and insert a character into a string.\
1049-- @tparam string str String to be spliced.\
1050-- @tparam number pos Where to insert the character.\
1051-- @tparam string char Character to insert.\
1052-- @tparam[opt] boolean replace Replace the character, or just insert a new one. Defaults to false.\
1053-- @treturn string The spliced string.\
1054local function splice(str,pos,char,replace)\
1055 local len = str:len()\
1056 local one = str:sub(1,pos-1)\
1057 local two = str:sub(pos,len)\
1058 local final\
1059 if not replace then\
1060 final = one .. char .. two\
1061 return final\
1062 else\
1063 local temp = two:sub(2)\
1064 final = one .. char .. temp\
1065 return final\
1066 end\
1067end\
1068\
1069--- Generate a random number based on math.random(), and the current time.\
1070-- @treturn number A mostly random number.\
1071local function generateRandom()\
1072 --[[\
1073 This function is not truly random. It uses a combination of math.random() and the current time to return a pseudo random number.\
1074 ]]\
1075 local epoch = math.floor(os.epoch(\"utc\") / 1000) + 3600 * math.random(math.random(math.random(1,234),math.random(1,42345)))\
1076 local t = os.date(\"!*t\",epoch)\
1077 return t.hour * t.min * t.sec * (t.hour + t.min + t.sec)\
1078end\
1079\
1080--- Roll a dice with a specified modifier, and check if it passes the DC.\
1081-- @tparam number size Number of sides of the dice.\
1082-- @tparam number modifier Bonuses of the roll.\
1083-- @tparam number dc DC to check the roll against.\
1084-- @treturn boolean If the roll passes the DC.\
1085-- @treturn number The final roll.\
1086local function diceRoll(size,modifier,dc)\
1087 expect(1,size,\"number\")\
1088 expect(1,modifier,\"number\")\
1089 expect(1,dc,\"number\")\
1090 size = size or 100\
1091 modifier = modifier or 0\
1092 dc = dc or 0\
1093\
1094 local roll = math.random(1,size) + modifier\
1095 if roll >= dc then return true,roll end\
1096 return false,roll\
1097end\
1098\
1099--- Get the current time with an offset from UTC.\
1100-- @tparam[opt] number offset Offset from UTC.\
1101-- @treturn table Table containing the time.\
1102local function getTime(offset)\
1103 expect(1,offset,\"number\",\"nil\")\
1104 offset = offset or 0\
1105 local epoch = math.floor(os.epoch(\"utc\") / 1000) + 3600 * offset\
1106 local t = os.date(\"!*t\",epoch)\
1107 return t\
1108end\
1109\
1110--- Get the current time in a table of strings prepended with `0` if they're single digit.\
1111-- @tparam[opt] number offset Offset from UTC.\
1112-- @treturn table Table containing the time.\
1113local function getZeroTime(offset)\
1114 expect(1,offset,\"number\",\"nil\")\
1115 local t = getTime(offset)\
1116 local time = {\
1117 sec = t.sec,\
1118 min = t.min,\
1119 hour = t.hour,\
1120 day = t.day,\
1121 month = t.month,\
1122 year = t.year,\
1123 }\
1124 for k,v in pairs(time) do\
1125 local str = tostring(v)\
1126 if str:len() == 1 then\
1127 str = \"0\" .. str\
1128 end\
1129 time[k] = str\
1130 end\
1131 return time\
1132end\
1133\
1134--- Read the contents of a file.\
1135-- @tparam string file Path to the file.\
1136-- @treturn string Contents of the file.\
1137local function fread(file)\
1138 expect(1,file,\"string\")\
1139 local f = fs.open(file,\"r\")\
1140 local contents = f.readAll()\
1141 f.close()\
1142 return contents\
1143end\
1144\
1145--- Write contents to a file.\
1146-- @tparam string file Path to the file.\
1147-- @tparam string Contents to write to the file.\
1148local function fwrite(file,contents)\
1149 expect(1,file,\"string\")\
1150 expect(2,contents,\"string\")\
1151 local f = fs.open(file,\"w\")\
1152 f.write(contents)\
1153 f.close()\
1154end\
1155\
1156--- Serialize a lua object, and write it to a file.\
1157-- @tparam string path Path to the file.\
1158-- @param object Any serializable lua object.\
1159local function encfwrite(file,object)\
1160 local obj = textutils.serialize(object)\
1161 fwrite(file,obj)\
1162end\
1163\
1164--- encfread reads a file, and unserializes the lua object.\
1165-- @tparam string Path to file.\
1166-- @return Any lua object from the file.\
1167local function encfread(file)\
1168 local contents = fread(file)\
1169 return textutils.unserialize(contents)\
1170end\
1171\
1172--- hread reads from a url\
1173-- @tparam string url URL to read from.\
1174-- @treturn string|nil Contents of the page, if any.\
1175-- @treturn nil|any Failing response, if any.\
1176local function hread(url)\
1177 expect(1,url,\"string\")\
1178 local h,err = http.get(url)\
1179 if not h then\
1180 return nil,err\
1181 end\
1182 local contents = h.readAll()\
1183 h.close()\
1184 return contents,nil\
1185end\
1186\
1187--- Poke a file, creating it if it doesn't exist.\
1188-- @tparam string Path to the file.\
1189local function poke(file)\
1190 fs.open(file,\"a\").close()\
1191end\
1192\
1193--- Webquire is a `require` but for URLs\
1194-- @tparam string url URL to download the module from.\
1195-- @return The loaded module, like what `require` would return.\
1196local function webquire(url)\
1197 local content,err = hread(url)\
1198 if not content then error(\"webquire: \" .. err,2) end\
1199 local lib = load(content,\"=webquire_package\",\"t\",_ENV)() -- load the content, name it as a `=webquire_package`, make it only load text lua, not bytecode, pass `_ENV` to it.\
1200 return lib\
1201end\
1202\
1203--- savequire uses @{sUtils.webquire|webquire} but will also save the file and use that if it's found.\
1204-- @tparam string url URL to download the module from.\
1205-- @return The loaded module, like what `require` would return.\
1206local function savequire(url)\
1207 local splitURL = split(url,\"/\") -- Split url to get the individual pieces, used to grab the filename.\
1208 local name = splitURL[#splitURL]\
1209 local package\
1210 if not fs.exists(fs.combine(\"savequire\",name)) then -- We dont have the package locally, download it from the web\
1211 local content,err = hread(url)\
1212 if not content then error(\"savequire: \" .. err,2) end\
1213 fwrite(fs.combine(\"savequire\",name),content.readAll())\
1214 package = require(fs.combine(\"savequire\",name))\
1215 else\
1216 package = require(fs.combine(\"savequire\",name))\
1217 end\
1218 return package\
1219end\
1220\
1221local agreePhrases = {\
1222 [\"YES\"] = true,\
1223 [\"OK\"] = true,\
1224 [\"Y\"] = true,\
1225 [\"YEAH\"] = true,\
1226 [\"YEP\"] = true,\
1227 [\"TRUE\"] = true,\
1228 [\"YUP\"] = true,\
1229 [\"YA\"] = true,\
1230 [\"OKAY\"] = true,\
1231 [\"YAH\"] = true,\
1232 [\"SURE\"] = true,\
1233 [\"ALRIGHT\"] = true,\
1234 [\"WHATEVER\"] = true,\
1235 [\"WHYNOT\"] = true,\
1236 [\"WHY NOT\"] = true,\
1237 [\"K\"] = true,\
1238 [\"YEA\"] = true,\
1239 [\"YE\"] = true,\
1240 [\"YEE\"] = true,\
1241 [\"AFFIRMATIVE\"] = true,\
1242}\
1243\
1244--- Read user input, compare it to a table of agree phrases.\
1245-- @treturn boolean Whether or not the user agreed to the prompt.\
1246local function confirm(replaceChar,history,completeFn,default)\
1247 local answer = read(replaceChar,history,completeFn,default)\
1248 return not not agreePhrases[answer:upper()]\
1249end\
1250\
1251--- Read user input, return `tonumber()` of it.\
1252-- @treturn number Number the user input.\
1253local function readNumber(...)\
1254 local answer\
1255 repeat \
1256 answer = tonumber(read(...))\
1257 until answer\
1258 return tonumber(answer)\
1259end\
1260\
1261--- \"Canadianify\" a text.\
1262-- @tparam string text Text to candianify.\
1263-- @treturn string Canadian text.\
1264local function canadianify(text)\
1265 return \"sorry \" .. text .. \" eh\"\
1266end\
1267\
1268--- \"Americanify\" a text.\
1269-- @tparam string text Text to americanify.\
1270-- @tparam[opt=1] number case Which type of modification to use. 1 = \"I'm walkin here!\" .. text .. \" Forget about it!\", 2 = \"Oil? \" .. text .. \" The First Amendment.\"\
1271-- @treturn string American text.\
1272local function americanify(text,case)\
1273 case = case or 1\
1274 if case == 1 then\
1275 return \"I'm walkin here! \" .. text .. \" Forget about it!\"\
1276 elseif case == 2 then\
1277 return \"Oil? \" .. text .. \" The First Amendment.\"\
1278 end\
1279end\
1280\
1281--- Check if a value is already in a table, if not, insert it.\
1282-- @tparam table tbl Table to insert to.\
1283-- @param value Value to insert.\
1284-- @treturn table Modified table.\
1285local function insert(tbl,value)\
1286 local present = false\
1287 for _,v in pairs(tbl) do\
1288 if v == value then\
1289 present = true\
1290 end\
1291 end\
1292 if not present then\
1293 table.insert(tbl,value)\
1294 end\
1295 return tbl\
1296end\
1297\
1298--- Remove all values from a table. \
1299-- @tparam table tbl Table to remove from.\
1300-- @param value Value to remove.\
1301-- @treturn table Modified table.\
1302local function remove(tbl,value)\
1303 for k,v in pairs(tbl) do\
1304 if v == value then\
1305 if type(k) == \"number\" then -- This is a numerically indiced table, we need to shift the other elements.\
1306 table.remove(tbl,k)\
1307 else -- key/value, just set to nil.\
1308 tbl[k] = nil\
1309 end\
1310 end\
1311 end\
1312 return tbl\
1313end\
1314\
1315--- Shallow copy a table, not recursive so doesn't copy table elements.\
1316-- @tparam table tbl Table to copy.\
1317-- @treturn table Copied table. \
1318local function shallowCopy(tbl)\
1319 local newTbl = {}\
1320 for k,v in tbl do\
1321 newTbl[k] = v\
1322 end\
1323 return newTbl\
1324end\
1325\
1326--- Deep copy a table, recurses to nested tables.\
1327-- @tparam table tbl Table to copy. \
1328-- @treturn table Copied table. \
1329local function deepCopy(tbl)\
1330 local newTbl = {}\
1331 for k,v in tbl do\
1332 if type(v) == \"table\" then\
1333 newTbl[k] = deepCopy(v)\
1334 else\
1335 newTbl[k] = v\
1336 end\
1337 end\
1338 return newTbl\
1339end\
1340\
1341--- Cache where the files are stored, it's key/value with `cache[path] = contents`.\
1342local cache = {}\
1343\
1344--- Load a file, checks if it's in the cache, if so, return that, if not, return the file and put it in cache.\
1345-- @tparam string path Path to the file.\
1346-- @treturn string Contents of the file\
1347local function cacheLoad(path)\
1348 if cache[path] then\
1349 return cache[path]\
1350 else\
1351 local contents = fread(path)\
1352 cache[path] = contents\
1353 return contents\
1354 end\
1355end\
1356\
1357--- Reload a file in the cache, overwriting it with the new contents.\
1358-- @tparam string path Path to the file to reload.\
1359-- @treturn string The old contents of the file.\
1360local function reload(path)\
1361 local contents = fread(path)\
1362 local old = cache[path]\
1363 cache[path] = contents\
1364 return old\
1365end\
1366\
1367--- Load an image file.\
1368-- @tparam string path Path to the file, supported types are \".skimg\", \".skgrp\", \".blit\", \".nfp\", and \".nft\".\
1369-- @treturn table The image file, to be fed into a drawing routine.\
1370local function load(file)\
1371 expect(1,file,\"string\")\
1372 if not fs.exists(file) then\
1373 error(\"file does not exist\",2)\
1374 end\
1375 local fileName = fs.getName(file)\
1376 local fileType = split(fileName,\".\")[2]\
1377 -- skimg loader\
1378 if fileType == \"skimg\" then\
1379 local fileTbl = encfread(file)\
1380 return fileTbl\
1381 end\
1382 -- skgrp loader (old & outdated)\
1383 if fileType == \"skgrp\" then\
1384 local fileTbl = {}\
1385 for x in io.lines(file) do\
1386 table.insert(fileTbl,x)\
1387 end\
1388 return fileTbl\
1389 end\
1390 -- blit loader, similar to `.skimg`\
1391 if fileType == \"blit\" then\
1392 local fileTbl = encfread(file)\
1393 return fileTbl\
1394 end\
1395 -- nfp loader, for paintutils\
1396 if fileType == \"nfp\" then\
1397 local img = paintutils.loadImage(file)\
1398 return img\
1399 end\
1400 -- nft loader, \"Nitrogen Fingers Text\"\
1401 if fileType == \"nft\" then\
1402 local img = nft.load(file)\
1403 return img\
1404 end\
1405end\
1406\
1407-- THIS FILETYPE IS DEPRECATED, DO NOT USE. (not documented)\
1408--- Draw the given `skgrp` file.\
1409-- @tparam table Table of instructions to draw.\
1410local function drawSkgrp(tbl)\
1411 expect(1,tbl,\"table\")\
1412 for i=1,#tbl do\
1413 local grpTable = split(tbl[i],\",\")\
1414 local operation = grpTable[1]\
1415 if operation == \"P\" then\
1416 paintutils.drawPixel(grpTable[2],grpTable[3],tonumber(grpTable[4]))\
1417 elseif operation == \"B\" then\
1418 paintutils.drawBox(grpTable[2],grpTable[3],grpTable[4],grpTable[5],tonumber(grpTable[6]))\
1419 elseif operation == \"F\" then\
1420 paintutils.drawFilledBox(grpTable[2],grpTable[3],grpTable[4],grpTable[5],tonumber(grpTable[6]))\
1421 elseif operation == \"L\" then\
1422 paintutils.drawLine(grpTable[2],grpTable[3],grpTable[4],grpTable[5],tonumber(grpTable[6]))\
1423 elseif operation == \"TEXT\" then\
1424 paintutils.drawText(grpTable[2],grpTable[3],grpTable[4],grpTable[5],grpTable[6])\
1425 end\
1426 end\
1427end\
1428\
1429--- drawSkimg takes a skimg table, and draws it at the specified location\
1430-- @tparam table skimg The skimg image to draw.\
1431-- @tparam[opt] number x X coordinate, defaults to 1.\
1432-- @tparam[opt] number y Y coordinate, defaults to 1.\
1433-- @tparam[opt] table output Output terminal, defaults to `term.current()`\
1434local function drawSkimg(tbl,x,y,tOutput)\
1435 expect(1,tbl,\"table\")\
1436 expect(2,x,\"number\",\"nil\")\
1437 expect(3,y,\"number\",\"nil\")\
1438 expect(4,tOutput,\"table\",\"nil\") -- tOutput is a term-like object. MUST SUPPORT BLIT!!!\
1439 x = x or 1\
1440 y = y or 1\
1441 tOutput = tOutput or term.current()\
1442 -- make sure it's a valid table with both of the `data` and `attributes` fields.\
1443 if not tbl.attributes or not tbl.data then\
1444 error(\"table is not valid .skimg\",2)\
1445 end\
1446 -- make sure tOutput has blit and setCursorPos\
1447 if not tOutput.setCursorPos or not tOutput.blit then\
1448 error(\"tOutput is incompatible!\",2)\
1449 end\
1450 for i=1,#tbl.data do\
1451 local blitLine = tbl.data[i]\
1452 tOutput.setCursorPos(x,y+i-1)\
1453 tOutput.blit(blitLine[1],blitLine[2],blitLine[3])\
1454 end\
1455end\
1456\
1457--- drawBlit is like drawSkimg, but for a normal blit table.concat\
1458-- @tparam table blit Blit image to draw.\
1459-- @tparam[opt] number x X coordinate of the image, defaults to 1.\
1460-- @tparam[opt] number y X coordinate of the image, defaults to 1.\
1461-- @tparam[opt] table output Output terminal, defaults to `term.current()`.\
1462local function drawBlit(tbl,x,y,tOutput)\
1463 expect(1,tbl,\"table\")\
1464 expect(2,x,\"number\",\"nil\")\
1465 expect(3,y,\"number\",\"nil\")\
1466 expect(4,tOutput,\"table\",\"nil\")\
1467 x = x or 1\
1468 y = y or 1\
1469 tOutput = tOutput or term.current()\
1470 for i=1,#tbl do\
1471 local blitLine = tbl[i]\
1472 tOutput.setCursorPos(x,y+i-1)\
1473 tOutput.blit(blitLine[1],blitLine[2],blitLine[3])\
1474 end\
1475end\
1476\
1477--- Generates a `skimg` image with the provided width, and height.\
1478-- @tparam number width Width of the image.\
1479-- @tparam number height Height of the image.\
1480-- @tparam string creator Creator of the image.\
1481-- @tparam boolean locked Whether or not the file is locked from editing.\
1482local function generateDefaultSkimg(width,height,creator,locked)\
1483 local defaultfg = \"0\"\
1484 local defaultbg = \"d\"\
1485 local defaultchar = \"o\"\
1486 local stringTable = {\
1487 defaultchar:rep(width),\
1488 defaultfg:rep(width),\
1489 defaultbg:rep(width),\
1490 }\
1491 local datatbl = {}\
1492 for i=1,height do\
1493 local tbl = {stringTable[1],stringTable[2],stringTable[3],i}\
1494 table.insert(datatbl,tbl)\
1495 end\
1496\
1497 local tbl = {\
1498 attributes = {\
1499 width = width,\
1500 height = height,\
1501 creator = creator,\
1502 locked = locked,\
1503 },\
1504 data = datatbl,\
1505 }\
1506 return tbl\
1507end\
1508\
1509-- This accepts either a file or a table to get attributes from (not working, not documented)\
1510--- Get the attributes of a `.skimg` file or image table.\
1511-- @tparam string|table image Path to a file, or a `.skimg` table.\
1512-- @treturn table Attributes of the image.\
1513local function getAttributes(fileTable)\
1514 expect(1,fileTable,\"string\",\"table\")\
1515 local tbl\
1516 if fs.exists(fileTable) then\
1517 -- its a file, read the contents and put them into the internal table\
1518 tbl = load(fileTable)\
1519 else\
1520 -- it's not a file, take input and put it into the internal table\
1521 tbl = fileTable\
1522 end\
1523 if tbl.attributes then\
1524 return tbl.attributes\
1525 else\
1526 return nil,\"not found\"\
1527 end\
1528end\
1529\
1530return {\
1531 --- Asset functions.\
1532 asset = {\
1533 load = load,\
1534 drawSkgrp = drawSkgrp,\
1535 drawSkimg = drawSkimg,\
1536 drawBlit = drawBlit,\
1537 --- Skimg asset functions.\
1538 skimg = {\
1539 getAttributes = getAttributes,\
1540 generateDefaultSkimg = generateDefaultSkimg,\
1541 },\
1542 },\
1543 --- Cache functions, stores files in a cache for faster access. (Read only)\
1544 cache = {\
1545 cacheData = cache,\
1546 cacheLoad = cacheLoad,\
1547 reload = reload,\
1548 },\
1549 numericallyContains = numericallyContains,\
1550 keyContains = keyContains,\
1551 getFile = getFile,\
1552 isOdd = isOdd,\
1553 split = split,\
1554 cut = cut,\
1555 splice = splice,\
1556 countLines = countLines,\
1557 getSize = getSize,\
1558 generateRandom = generateRandom,\
1559 diceRoll = diceRoll,\
1560 fread = fread,\
1561 fwrite = fwrite,\
1562 hread = hread,\
1563 getTime = getTime,\
1564 getZeroTime = getZeroTime,\
1565 confirm = confirm,\
1566 readNumber = readNumber,\
1567 poke = poke,\
1568 encfwrite = encfwrite,\
1569 encfread = encfread,\
1570 webquire = webquire,\
1571 savequire = savequire,\
1572 canadianify = canadianify,\
1573 americanify = americanify,\
1574 insert = insert,\
1575 remove = remove,\
1576 shallowCopy = shallowCopy,\
1577 deepCopy = deepCopy,\
1578}",
1579 },
1580}