· 7 years ago · Jan 27, 2019, 02:52 AM
1local tArg = {...}
2local outputPath, file = fs.combine(shell.dir(), tArg[1] or "")
3fs.delete(shell.getRunningProgram()) -- save space
4local safeColorList = {[colors.white] = true,[colors.lightGray] = true,[colors.gray] = true,[colors.black] = true}
5local stc = function(color) if (term.isColor() or safeColorList[color]) then term.setTextColor(color) end end
6local archive = textutils.unserialize("{\
7 mainFile = false,\
8 compressed = false,\
9 data = {\
10 [ \"help/pocket.txt\" ] = \"pocket is an API available on pocket computers, which allows modifying its upgrades.\\\
11Functions in the pocket API:\\\
12pocket.equipBack()\\\
13pocket.unequipBack()\\\
14\\\
15When equipping upgrades, it will search your inventory for a suitable upgrade, starting in the selected slot. If one cannot be found then it will check your offhand.\",\
16 [ \"help/chat.txt\" ] = \"Surf the rednet superhighway with \\\"chat\\\", the networked chat program for CraftOS! Host chatrooms and invite your friends! Requires a Wired or Wireless Modem on each computer. When running chat, type \\\"/help\\\" to see a list of available commands.\\\
17\\\
18ex:\\\
19\\\"chat host forgecraft\\\" will create a chatroom with the name \\\"forgecraft\\\"\\\
20\\\"chat join forgecraft direwolf20\\\" will connect to the chatroom with the name \\\"forgecraft\\\", using the nickname \\\"direwolf20\\\"\",\
21 [ \"apis/keys.lua\" ] = \"\\\
22-- Minecraft key code bindings\\\
23-- See http://www.minecraftwiki.net/wiki/Key_codes for more info\\\
24\\\
25local tKeys = {\\\
26 nil, \\\"one\\\", \\\"two\\\", \\\"three\\\", \\\"four\\\", -- 1\\\
27 \\\"five\\\", \\\"six\\\", \\\"seven\\\", \\\"eight\\\", \\\"nine\\\", -- 6\\\
28 \\\"zero\\\", \\\"minus\\\", \\\"equals\\\", \\\"backspace\\\",\\\"tab\\\", -- 11\\\
29 \\\"q\\\", \\\"w\\\", \\\"e\\\", \\\"r\\\", \\\"t\\\", -- 16\\\
30 \\\"y\\\", \\\"u\\\", \\\"i\\\", \\\"o\\\", \\\"p\\\", -- 21\\\
31 \\\"leftBracket\\\",\\\"rightBracket\\\",\\\"enter\\\",\\\"leftCtrl\\\",\\\"a\\\", -- 26\\\
32 \\\"s\\\", \\\"d\\\", \\\"f\\\", \\\"g\\\", \\\"h\\\", -- 31\\\
33 \\\"j\\\", \\\"k\\\", \\\"l\\\", \\\"semiColon\\\",\\\"apostrophe\\\", -- 36\\\
34 \\\"grave\\\", \\\"leftShift\\\",\\\"backslash\\\",\\\"z\\\", \\\"x\\\", -- 41\\\
35 \\\"c\\\", \\\"v\\\", \\\"b\\\", \\\"n\\\", \\\"m\\\", -- 46\\\
36 \\\"comma\\\", \\\"period\\\", \\\"slash\\\", \\\"rightShift\\\",\\\"multiply\\\", -- 51\\\
37 \\\"leftAlt\\\", \\\"space\\\", \\\"capsLock\\\", \\\"f1\\\", \\\"f2\\\", -- 56\\\
38 \\\"f3\\\", \\\"f4\\\", \\\"f5\\\", \\\"f6\\\", \\\"f7\\\", -- 61\\\
39 \\\"f8\\\", \\\"f9\\\", \\\"f10\\\", \\\"numLock\\\", \\\"scrollLock\\\", -- 66\\\
40 \\\"numPad7\\\", \\\"numPad8\\\", \\\"numPad9\\\", \\\"numPadSubtract\\\",\\\"numPad4\\\", -- 71\\\
41 \\\"numPad5\\\", \\\"numPad6\\\", \\\"numPadAdd\\\",\\\"numPad1\\\", \\\"numPad2\\\", -- 76\\\
42 \\\"numPad3\\\", \\\"numPad0\\\", \\\"numPadDecimal\\\",nil, nil, -- 81\\\
43 nil, \\\"f11\\\", \\\"f12\\\", nil, nil, -- 86\\\
44 nil, nil, nil, nil, nil, -- 91\\\
45 nil, nil, nil, nil, \\\"f13\\\", -- 96\\\
46 \\\"f14\\\", \\\"f15\\\", nil, nil, nil, -- 101\\\
47 nil, nil, nil, nil, nil, -- 106\\\
48 nil, \\\"kana\\\", nil, nil, nil, -- 111\\\
49 nil, nil, nil, nil, nil, -- 116\\\
50 \\\"convert\\\", nil, \\\"noconvert\\\",nil, \\\"yen\\\", -- 121\\\
51 nil, nil, nil, nil, nil, -- 126\\\
52 nil, nil, nil, nil, nil, -- 131\\\
53 nil, nil, nil, nil, nil, -- 136\\\
54 \\\"numPadEquals\\\",nil, nil, \\\"circumflex\\\",\\\"at\\\", -- 141\\\
55 \\\"colon\\\", \\\"underscore\\\",\\\"kanji\\\", \\\"stop\\\", \\\"ax\\\", -- 146\\\
56 nil, nil, nil, nil, nil, -- 151\\\
57 \\\"numPadEnter\\\",\\\"rightCtrl\\\",nil, nil, nil, -- 156\\\
58 nil, nil, nil, nil, nil, -- 161\\\
59 nil, nil, nil, nil, nil, -- 166\\\
60 nil, nil, nil, nil, nil, -- 171\\\
61 nil, nil, nil, \\\"numPadComma\\\",nil, -- 176\\\
62 \\\"numPadDivide\\\",nil, nil, \\\"rightAlt\\\", nil, -- 181\\\
63 nil, nil, nil, nil, nil, -- 186\\\
64 nil, nil, nil, nil, nil, -- 191\\\
65 nil, \\\"pause\\\", nil, \\\"home\\\", \\\"up\\\", -- 196\\\
66 \\\"pageUp\\\", nil, \\\"left\\\", nil, \\\"right\\\", -- 201\\\
67 nil, \\\"end\\\", \\\"down\\\", \\\"pageDown\\\", \\\"insert\\\", -- 206\\\
68 \\\"delete\\\" -- 211\\\
69}\\\
70\\\
71local keys = _ENV\\\
72for nKey, sKey in pairs( tKeys ) do\\\
73 keys[sKey] = nKey\\\
74end\\\
75keys[\\\"return\\\"] = keys.enter\\\
76--backwards compatibility to earlier, typo prone, versions\\\
77keys.scollLock = keys.scrollLock\\\
78keys.cimcumflex = keys.circumflex\\\
79\\\
80function getName( _nKey )\\\
81 if type( _nKey ) ~= \\\"number\\\" then\\\
82 error( \\\"bad argument #1 (expected number, got \\\" .. type( _nKey ) .. \\\")\\\", 2 )\\\
83 end\\\
84 return tKeys[ _nKey ]\\\
85end\",\
86 [ \"programs/fun/advanced/levels/3.dat\" ] = \"2\\\
87 77777777\\\
88777888188777\\\
897b78777787b7\\\
9078787 78787\\\
9178787 78787\\\
9278887 78887\\\
93777877778777\\\
94 78838887\\\
95 77777777\",\
96 [ \"programs/fun/advanced/levels/7.dat\" ] = \"3\\\
97728777778b7\\\
9878888888887\\\
9978777877787\\\
100787 787 787\\\
101787 7877788\\\
102787 7888889\\\
10388777877777\\\
104e888887\\\
1057777887\",\
106 [ \"help/textutils.txt\" ] = \"Functions in the Text Utilities API:\\\
107textutils.slowPrint( text )\\\
108textutils.tabulate( table, table2, ... )\\\
109textutils.pagedTabulate( table, table2, ... )\\\
110textutils.formatTime( time, bTwentyFourHour )\\\
111textutils.serialize( table )\\\
112textutils.unserialize( string )\\\
113textutils.serializeJSON( table, [useNBTStyle] )\\\
114textutils.urlEncode( string )\\\
115textutils.complete( string, table )\",\
116 [ \"help/shell.txt\" ] = \"shell is the toplevel program which interprets commands and runs program.\\\
117Type \\\"help shellapi\\\" for information about the shell lua api.\",\
118 [ \"programs/clear.lua\" ] = \"term.clear()\\\
119term.setCursorPos( 1, 1 )\",\
120 [ \"programs/fun/advanced/levels/1.dat\" ] = \"1\\\
121 777\\\
122 7b7\\\
123 787\\\
1247777778777\\\
1257188888887\\\
1267777777777\",\
127 [ \"help/math.txt\" ] = \"math is a standard Lua5.1 API.\\\
128Refer to http://www.lua.org/manual/5.1/ for more information.\",\
129 [ \"help/hello.txt\" ] = \"hello prints the text \\\"Hello World!\\\" to the screen.\",\
130 [ \"help/drives.txt\" ] = \"The Disk Drive is a peripheral device available for CraftOS. Type \\\"help peripheral\\\" to learn about using the Peripheral API to connect with peripherals. When a Disk Drive is connected, peripheral.getType() will return \\\"drive\\\".\\\
131\\\
132Methods exposed by the Disk Drive:\\\
133isDiskPresent()\\\
134getDiskLabel()\\\
135setDiskLabel( label )\\\
136hasData()\\\
137getMountPath()\\\
138hasAudio()\\\
139getAudioTitle()\\\
140playAudio()\\\
141stopAudio()\\\
142ejectDisk()\\\
143getDiskID()\\\
144\\\
145Events fired by the Disk Drive:\\\
146\\\"disk\\\" when a disk or other item is inserted into the drive. Argument is the name of the drive.\\\
147\\\"disk_eject\\\" when a disk is removed from a drive. Argument is the name of the drive.\\\
148Type \\\"help events\\\" to learn about the event system.\",\
149 [ \"help/table.txt\" ] = \"table is a standard Lua5.1 API.\\\
150Refer to http://www.lua.org/manual/5.1/ for more information.\",\
151 [ \"help/worm.txt\" ] = \"You've played it in the arcades, now experience the high-octane thrills of the hit game \\\"WORM!\\\" on your home computer! Only on CraftOS!\",\
152 [ \"help/move.txt\" ] = \"mv moves a file or directory from one location to another.\\\
153\\\
154ex:\\\
155\\\"mv foo bar\\\" renames the file \\\"foo\\\" to \\\"bar\\\".\\\
156\\\"mv foo bar/foo\\\" moves the file \\\"foo\\\" to a folder called \\\"bar\\\".\\\
157\\\"mv disk/* disk2\\\" moves the contents of one disk to another\",\
158 [ \"help/speakers.txt\" ] = \"The Speaker is a peripheral device available for CraftOS. Type \\\"help peripheral\\\" to learn about using the Peripheral API to connect with peripherals. When a Speaker is connected, peripheral.getType() will return \\\"speaker\\\".\\\
159\\\
160Methods exposed by the Speaker:\\\
161playSound( sResourceName, nVolume, nPitch )\\\
162playNote( sInstrumentName, nVolume, nPitch )\\\
163\\\
164Resource name is the same as used by the /playsound command, such as \\\"minecraft:entity.cow.ambient\\\".\\\
165Instruments are as follows: \\\"harp\\\", \\\"bass\\\", \\\"snare\\\", \\\"hat\\\", and \\\"basedrum\\\" with the addition of \\\"flute\\\", \\\"bell\\\", \\\"chime\\\", and \\\"guitar\\\" in Minecraft versions 1.12 and above.\\\
166Ticks is the amount of times a noteblock has been tuned (right clicked).\",\
167 [ \"apis/vector.lua\" ] = \"\\\
168local vector = {\\\
169 add = function( self, o )\\\
170 return vector.new(\\\
171 self.x + o.x,\\\
172 self.y + o.y,\\\
173 self.z + o.z\\\
174 )\\\
175 end,\\\
176 sub = function( self, o )\\\
177 return vector.new(\\\
178 self.x - o.x,\\\
179 self.y - o.y,\\\
180 self.z - o.z\\\
181 )\\\
182 end,\\\
183 mul = function( self, m )\\\
184 return vector.new(\\\
185 self.x * m,\\\
186 self.y * m,\\\
187 self.z * m\\\
188 )\\\
189 end,\\\
190 div = function( self, m )\\\
191 return vector.new(\\\
192 self.x / m,\\\
193 self.y / m,\\\
194 self.z / m\\\
195 )\\\
196 end,\\\
197 unm = function( self )\\\
198 return vector.new(\\\
199 -self.x,\\\
200 -self.y,\\\
201 -self.z\\\
202 )\\\
203 end,\\\
204 dot = function( self, o )\\\
205 return self.x*o.x + self.y*o.y + self.z*o.z\\\
206 end,\\\
207 cross = function( self, o )\\\
208 return vector.new(\\\
209 self.y*o.z - self.z*o.y,\\\
210 self.z*o.x - self.x*o.z,\\\
211 self.x*o.y - self.y*o.x\\\
212 )\\\
213 end,\\\
214 length = function( self )\\\
215 return math.sqrt( self.x*self.x + self.y*self.y + self.z*self.z )\\\
216 end,\\\
217 normalize = function( self )\\\
218 return self:mul( 1 / self:length() )\\\
219 end,\\\
220 round = function( self, nTolerance )\\\
221 nTolerance = nTolerance or 1.0\\\
222 return vector.new(\\\
223 math.floor( (self.x + (nTolerance * 0.5)) / nTolerance ) * nTolerance,\\\
224 math.floor( (self.y + (nTolerance * 0.5)) / nTolerance ) * nTolerance,\\\
225 math.floor( (self.z + (nTolerance * 0.5)) / nTolerance ) * nTolerance\\\
226 )\\\
227 end,\\\
228 tostring = function( self )\\\
229 return self.x..\\\",\\\"..self.y..\\\",\\\"..self.z\\\
230 end,\\\
231}\\\
232\\\
233local vmetatable = {\\\
234 __index = vector,\\\
235 __add = vector.add,\\\
236 __sub = vector.sub,\\\
237 __mul = vector.mul,\\\
238 __div = vector.div,\\\
239 __unm = vector.unm,\\\
240 __tostring = vector.tostring,\\\
241}\\\
242\\\
243function new( x, y, z )\\\
244 local v = {\\\
245 x = tonumber(x) or 0,\\\
246 y = tonumber(y) or 0,\\\
247 z = tonumber(z) or 0\\\
248 }\\\
249 setmetatable( v, vmetatable )\\\
250 return v\\\
251end\",\
252 [ \"help/type.txt\" ] = \"type determines the type of a file or directory. Prints \\\"file\\\", \\\"directory\\\" or \\\"does not exist\\\".\",\
253 [ \"help/tunnel.txt\" ] = \"tunnel is a program for Mining Turtles. Tunnel will mine a 3x2 tunnel of the depth specified.\\\
254\\\
255ex:\\\
256\\\"tunnel 20\\\" will tunnel a tunnel 20 blocks long.\",\
257 [ \"help/redstone.txt\" ] = \"The redstone program can be used to get, set or pulse redstone inputs and outputs from the computer.\\\
258\\\
259ex:\\\
260\\\"redstone probe\\\" will list all the redstone inputs to the computer\\\
261\\\"redstone set left true\\\" turns on the left redstone output.\\\
262\\\"redstone set right blue false\\\" turns off the blue wire in the bundled cable on the right redstone output.\\\
263\\\"redstone pulse front 10 1\\\" emits 10 one second redstone pulses on the front redstone output.\\\
264\\\
265Type \\\"help redstoneapi\\\" or \\\"help rs\\\" for information on the redstone Lua API.\",\
266 [ \"programs/turtle/craft.lua\" ] = \"\\\
267if not turtle.craft then\\\
268 print( \\\"Requires a Crafty Turtle\\\" )\\\
269 return\\\
270end\\\
271\\\
272local tArgs = { ... }\\\
273local nLimit = nil\\\
274if #tArgs < 1 then\\\
275 print( \\\"Usage: craft [number]\\\" )\\\
276 return\\\
277else\\\
278 nLimit = tonumber( tArgs[1] )\\\
279end\\\
280\\\
281local nCrafted = 0\\\
282local nOldCount = turtle.getItemCount( turtle.getSelectedSlot() )\\\
283if turtle.craft( nLimit ) then\\\
284 local nNewCount = turtle.getItemCount( turtle.getSelectedSlot() )\\\
285 if nOldCount <= nLimit then\\\
286 nCrafted = nNewCount\\\
287 else\\\
288 nCrafted = nOldCount - nNewCount\\\
289 end\\\
290end\\\
291\\\
292if nCrafted > 1 then\\\
293 print( nCrafted..\\\" items crafted\\\" )\\\
294elseif nCrafted == 1 then\\\
295 print( \\\"1 item crafted\\\" )\\\
296else\\\
297 print( \\\"No items crafted\\\" )\\\
298end\",\
299 [ \"programs/move.lua\" ] = \"\\\
300local tArgs = { ... }\\\
301if #tArgs < 2 then\\\
302 print( \\\"Usage: mv <source> <destination>\\\" )\\\
303 return\\\
304end\\\
305\\\
306local sSource = shell.resolve( tArgs[1] )\\\
307local sDest = shell.resolve( tArgs[2] )\\\
308local tFiles = fs.find( sSource )\\\
309if #tFiles > 0 then\\\
310 for n,sFile in ipairs( tFiles ) do\\\
311 if fs.isDir( sDest ) then\\\
312 fs.move( sFile, fs.combine( sDest, fs.getName(sFile) ) )\\\
313 elseif #tFiles == 1 then\\\
314 fs.move( sFile, sDest )\\\
315 else\\\
316 printError( \\\"Cannot overwrite file multiple times\\\" )\\\
317 return\\\
318 end\\\
319 end\\\
320else\\\
321 printError( \\\"No matching files\\\" )\\\
322end\",\
323 [ \"programs/rename.lua\" ] = \"local tArgs = { ... }\\\
324if #tArgs < 2 then\\\
325 print( \\\"Usage: rename <source> <destination>\\\" )\\\
326 return\\\
327end\\\
328\\\
329local sSource = shell.resolve( tArgs[1] )\\\
330local sDest = shell.resolve( tArgs[2] )\\\
331\\\
332if fs.exists( sDest ) then\\\
333 printError( \\\"Destination exists\\\" )\\\
334end\\\
335\\\
336fs.move( sSource, sDest )\",\
337 [ \"programs/fun/advanced/redirection.lua\" ] = \"--CCRedirection by : RamiLego4Game and Dan200--\\\
338--Based on Redirection by Dan200: http://www.redirectiongame.com--\\\
339--Clearing Screen--\\\
340\\\
341--Vars--\\\
342local TermW,TermH = term.getSize()\\\
343\\\
344local sLevelTitle\\\
345local tScreen\\\
346local oScreen\\\
347local SizeW,SizeH\\\
348local aExits\\\
349local fExit\\\
350local nSpeed\\\
351local Speed\\\
352local fSpeed\\\
353local fSpeedS\\\
354local bPaused\\\
355local Tick\\\
356local Blocks\\\
357local XOrgin,YOrgin\\\
358local fLevel\\\
359\\\
360local function reset()\\\
361 sLevelTitle = \\\"\\\"\\\
362 tScreen = {}\\\
363 oScreen = {}\\\
364 SizeW,SizeH = TermW,TermH\\\
365 aExits = 0\\\
366 fExit = \\\"nop\\\"\\\
367 nSpeed = 0.6\\\
368 Speed = nSpeed\\\
369 fSpeed = 0.2\\\
370 fSpeedS = false\\\
371 bPaused = false\\\
372 Tick = os.startTimer(Speed)\\\
373 Blocks = 0\\\
374 XOrgin,YOrgin = 1,1\\\
375\\\
376 term.setBackgroundColor(colors.black)\\\
377 term.setTextColor(colors.white)\\\
378 term.clear()\\\
379end\\\
380\\\
381local InterFace = {}\\\
382InterFace.cExit = colors.red\\\
383InterFace.cSpeedD = colors.white\\\
384InterFace.cSpeedA = colors.red\\\
385InterFace.cTitle = colors.red\\\
386\\\
387local cG = colors.lightGray\\\
388local cW = colors.gray\\\
389local cS = colors.black\\\
390local cR1 = colors.blue\\\
391local cR2 = colors.red\\\
392local cR3 = colors.green\\\
393local cR4 = colors.yellow\\\
394\\\
395local tArgs = { ... }\\\
396\\\
397--Functions--\\\
398local function printCentred( yc, stg )\\\
399 local xc = math.floor((TermW - string.len(stg)) / 2) + 1\\\
400 term.setCursorPos(xc,yc)\\\
401 term.write( stg )\\\
402end\\\
403\\\
404local function centerOrgin()\\\
405 XOrgin = math.floor((TermW/2)-(SizeW/2))\\\
406 YOrgin = math.floor((TermH/2)-(SizeH/2))\\\
407end\\\
408\\\
409local function reMap()\\\
410 tScreen = nil\\\
411 tScreen = {}\\\
412 for x=1,SizeW do\\\
413 tScreen[x] = {}\\\
414 for y=1,SizeH do\\\
415 tScreen[x][y] = { space = true, wall = false, ground = false, robot = \\\"zz\\\", start = \\\"zz\\\", exit = \\\"zz\\\" }\\\
416 end\\\
417 end\\\
418end\\\
419\\\
420local function tablecopy(t)\\\
421 local t2 = {}\\\
422 for k,v in pairs(t) do\\\
423 t2[k] = v\\\
424 end\\\
425 return t2\\\
426end\\\
427\\\
428local function buMap()\\\
429 oScreen = nil\\\
430 oScreen = {}\\\
431 for x=1,SizeW do\\\
432 oScreen[x] = {}\\\
433 for y=1,SizeH do\\\
434 oScreen[x][y] = tablecopy(tScreen[x][y])\\\
435 end\\\
436 end\\\
437end\\\
438\\\
439local function addRobot(x,y,side,color)\\\
440 local obj = tScreen[x][y]\\\
441 local data = side..color\\\
442 if obj.wall == nil and obj.robot == nil then\\\
443 tScreen[x][y].robot = data\\\
444 else\\\
445 obj.wall = nil\\\
446 obj.robot = \\\"zz\\\"\\\
447 tScreen[x][y].robot = data\\\
448 end\\\
449end\\\
450\\\
451local function addStart(x,y,side,color)\\\
452 local obj = tScreen[x][y]\\\
453 local data = side..color\\\
454 if obj.wall == nil and obj.space == nil then\\\
455 tScreen[x][y].start = data\\\
456 else\\\
457 obj.wall = nil\\\
458 obj.space = nil\\\
459 tScreen[x][y].start = data\\\
460 end\\\
461 aExits = aExits+1\\\
462end\\\
463\\\
464local function addGround(x,y)\\\
465 local obj = tScreen[x][y]\\\
466 if obj.space == nil and obj.exit == nil and obj.wall == nil and obj.robot == nil and obj.start == nil then\\\
467 tScreen[x][y].ground = true\\\
468 else\\\
469 obj.space = nil\\\
470 obj.exit = \\\"zz\\\"\\\
471 obj.wall = nil\\\
472 obj.robot = \\\"zz\\\"\\\
473 obj.start = \\\"zz\\\"\\\
474 tScreen[x][y].ground = true\\\
475 end\\\
476end\\\
477\\\
478local function addExit(x,y,cl)\\\
479 local obj = tScreen[x][y]\\\
480 if obj.space == nil and obj.ground == nil and obj.wall == nil and obj.robot == nil and obj.start == nil then\\\
481 tScreen[x][y].exit = cl\\\
482 else\\\
483 obj.space = nil\\\
484 obj.ground = nil\\\
485 obj.wall = nil\\\
486 obj.robot = \\\"zz\\\"\\\
487 obj.start = \\\"zz\\\"\\\
488 tScreen[x][y].exit = cl\\\
489 end\\\
490end\\\
491\\\
492local function addWall(x,y)\\\
493 local obj = tScreen[x][y]\\\
494 if obj == nil then\\\
495 return error(\\\"Here X\\\"..x..\\\" Y\\\"..y)\\\
496 end\\\
497 if obj.space == nil and obj.exit == nil and obj.ground == nil and obj.robot == nil and obj.start == nil then\\\
498 tScreen[x][y].wall = true\\\
499 else\\\
500 obj.space = nil\\\
501 obj.exit = nil\\\
502 obj.ground = nil\\\
503 obj.robot = nil\\\
504 obj.start = nil\\\
505 tScreen[x][y].wall = true\\\
506 end\\\
507end\\\
508\\\
509local function loadLevel(nNum)\\\
510 sLevelTitle = \\\"Level \\\"..nNum\\\
511 if nNum == nil then return error(\\\"nNum == nil\\\") end\\\
512 local sDir = fs.getDir( shell.getRunningProgram() )\\\
513 local sLevelD = sDir .. \\\"/levels/\\\" .. tostring(nNum)..\\\".dat\\\"\\\
514 if not ( fs.exists(sLevelD) or fs.isDir(sLevelD) ) then return error(\\\"Level Not Exists : \\\"..sLevelD) end\\\
515 fLevel = fs.open(sLevelD,\\\"r\\\")\\\
516 local Line = 0\\\
517 local wl = true\\\
518 Blocks = tonumber(string.sub(fLevel.readLine(),1,1))\\\
519 local xSize = string.len(fLevel.readLine())+2\\\
520 local Lines = 3\\\
521 while wl do\\\
522 local wLine = fLevel.readLine()\\\
523 if wLine == nil then\\\
524 fLevel.close()\\\
525 wl = false\\\
526 else\\\
527 xSize = math.max(string.len(wLine)+2,xSize)\\\
528 Lines = Lines + 1\\\
529 end\\\
530 end\\\
531 SizeW,SizeH = xSize,Lines\\\
532 reMap()\\\
533 fLevel = fs.open(sLevelD,\\\"r\\\")\\\
534 fLevel.readLine()\\\
535 for Line=2,Lines-1 do\\\
536 local sLine = fLevel.readLine()\\\
537 local chars = string.len(sLine)\\\
538 for char = 1, chars do\\\
539 local el = string.sub(sLine,char,char)\\\
540 if el == \\\"8\\\" then\\\
541 addGround(char+1,Line)\\\
542 elseif el == \\\"0\\\" then\\\
543 addStart(char+1,Line,\\\"a\\\",\\\"a\\\")\\\
544 elseif el == \\\"1\\\" then\\\
545 addStart(char+1,Line,\\\"b\\\",\\\"a\\\")\\\
546 elseif el == \\\"2\\\" then\\\
547 addStart(char+1,Line,\\\"c\\\",\\\"a\\\")\\\
548 elseif el == \\\"3\\\" then\\\
549 addStart(char+1,Line,\\\"d\\\",\\\"a\\\")\\\
550 elseif el == \\\"4\\\" then\\\
551 addStart(char+1,Line,\\\"a\\\",\\\"b\\\")\\\
552 elseif el == \\\"5\\\" then\\\
553 addStart(char+1,Line,\\\"b\\\",\\\"b\\\")\\\
554 elseif el == \\\"6\\\" then\\\
555 addStart(char+1,Line,\\\"c\\\",\\\"b\\\")\\\
556 elseif el == \\\"9\\\" then\\\
557 addStart(char+1,Line,\\\"d\\\",\\\"b\\\")\\\
558 elseif el == \\\"b\\\" then\\\
559 addExit(char+1,Line,\\\"a\\\")\\\
560 elseif el == \\\"e\\\" then\\\
561 addExit(char+1,Line,\\\"b\\\")\\\
562 elseif el == \\\"7\\\" then\\\
563 addWall(char+1,Line)\\\
564 end\\\
565 end\\\
566 end\\\
567 fLevel.close()\\\
568end\\\
569\\\
570local function drawStars()\\\
571 --CCR Background By : RamiLego--\\\
572 local cStar,cStarG,crStar,crStarB = colors.lightGray,colors.gray,\\\".\\\",\\\"*\\\"\\\
573 local DStar,BStar,nStar,gStar = 14,10,16,3\\\
574 local TermW,TermH = term.getSize()\\\
575\\\
576 term.clear()\\\
577 term.setCursorPos(1,1)\\\
578 for x=1,TermW do\\\
579 for y=1,TermH do\\\
580 local StarT = math.random(1,30)\\\
581 if StarT == DStar then\\\
582 term.setCursorPos(x,y)\\\
583 term.setTextColor(cStar)\\\
584 write(crStar)\\\
585 elseif StarT == BStar then\\\
586 term.setCursorPos(x,y)\\\
587 term.setTextColor(cStar)\\\
588 write(crStarB)\\\
589 elseif StarT == nStar then\\\
590 term.setCursorPos(x,y)\\\
591 term.setTextColor(cStarG)\\\
592 write(crStar)\\\
593 elseif StarT == gStar then\\\
594 term.setCursorPos(x,y)\\\
595 term.setTextColor(cStarG)\\\
596 write(crStarB)\\\
597 end\\\
598 end\\\
599 end\\\
600end\\\
601\\\
602local function drawMap()\\\
603 for x=1,SizeW do\\\
604 for y=1,SizeH do\\\
605\\\
606 local obj = tScreen[x][y]\\\
607 if obj.ground == true then\\\
608 paintutils.drawPixel(XOrgin+x,YOrgin+y+1,cG)\\\
609 end\\\
610 if obj.wall == true then\\\
611 paintutils.drawPixel(XOrgin+x,YOrgin+y+1,cW)\\\
612 end\\\
613\\\
614 local ex = tostring(tScreen[x][y].exit)\\\
615 if not(ex == \\\"zz\\\" or ex == \\\"nil\\\") then\\\
616 if ex == \\\"a\\\" then\\\
617 ex = cR1\\\
618 elseif ex == \\\"b\\\" then\\\
619 ex = cR2\\\
620 elseif ex == \\\"c\\\" then\\\
621 ex = cR3\\\
622 elseif ex == \\\"d\\\" then\\\
623 ex = cR4\\\
624 else\\\
625 return error(\\\"Exit Color Out\\\")\\\
626 end\\\
627 term.setBackgroundColor(cG)\\\
628 term.setTextColor(ex)\\\
629 term.setCursorPos(XOrgin+x,YOrgin+y+1)\\\
630 print(\\\"X\\\")\\\
631 end\\\
632\\\
633 local st = tostring(tScreen[x][y].start)\\\
634 if not(st == \\\"zz\\\" or st == \\\"nil\\\") then\\\
635 local Cr = string.sub(st,2,2)\\\
636 if Cr == \\\"a\\\" then\\\
637 Cr = cR1\\\
638 elseif Cr == \\\"b\\\" then\\\
639 Cr = cR2\\\
640 elseif Cr == \\\"c\\\" then\\\
641 Cr = cR3\\\
642 elseif Cr == \\\"d\\\" then\\\
643 Cr = cR4\\\
644 else\\\
645 return error(\\\"Start Color Out\\\")\\\
646 end\\\
647\\\
648 term.setTextColor(Cr)\\\
649 term.setBackgroundColor(cG)\\\
650 term.setCursorPos(XOrgin+x,YOrgin+y+1)\\\
651\\\
652 local sSide = string.sub(st,1,1)\\\
653 if sSide == \\\"a\\\" then\\\
654 print(\\\"^\\\")\\\
655 elseif sSide == \\\"b\\\" then\\\
656 print(\\\">\\\")\\\
657 elseif sSide == \\\"c\\\" then\\\
658 print(\\\"v\\\")\\\
659 elseif sSide == \\\"d\\\" then\\\
660 print(\\\"<\\\")\\\
661 else\\\
662 print(\\\"@\\\")\\\
663 end\\\
664 end\\\
665\\\
666 if obj.space == true then\\\
667 paintutils.drawPixel(XOrgin+x,YOrgin+y+1,cS)\\\
668 end\\\
669\\\
670 local rb = tostring(tScreen[x][y].robot)\\\
671 if not(rb == \\\"zz\\\" or rb == \\\"nil\\\") then\\\
672 local Cr = string.sub(rb,2,2)\\\
673 if Cr == \\\"a\\\" then\\\
674 Cr = cR1\\\
675 elseif Cr == \\\"b\\\" then\\\
676 Cr = cR2\\\
677 elseif Cr == \\\"c\\\" then\\\
678 Cr = cR3\\\
679 elseif Cr == \\\"d\\\" then\\\
680 Cr = cR4\\\
681 else\\\
682 Cr = colors.white\\\
683 end\\\
684 term.setBackgroundColor(Cr)\\\
685 term.setTextColor(colors.white)\\\
686 term.setCursorPos(XOrgin+x,YOrgin+y+1)\\\
687 local sSide = string.sub(rb,1,1)\\\
688 if sSide == \\\"a\\\" then\\\
689 print(\\\"^\\\")\\\
690 elseif sSide == \\\"b\\\" then\\\
691 print(\\\">\\\")\\\
692 elseif sSide == \\\"c\\\" then\\\
693 print(\\\"v\\\")\\\
694 elseif sSide == \\\"d\\\" then\\\
695 print(\\\"<\\\")\\\
696 else\\\
697 print(\\\"@\\\")\\\
698 end\\\
699 end\\\
700 end\\\
701 end\\\
702end\\\
703\\\
704local function isBrick(x,y)\\\
705 local brb = tostring(tScreen[x][y].robot)\\\
706 local bobj = oScreen[x][y]\\\
707 if (brb == \\\"zz\\\" or brb == \\\"nil\\\") and not bobj.wall == true then\\\
708 return false\\\
709 else\\\
710 return true\\\
711 end\\\
712end\\\
713\\\
714local function gRender(sContext)\\\
715 if sContext == \\\"start\\\" then\\\
716 for x=1,SizeW do\\\
717 for y=1,SizeH do\\\
718 local st = tostring(tScreen[x][y].start)\\\
719 if not(st == \\\"zz\\\" or st == \\\"nil\\\") then\\\
720 local Cr = string.sub(st,2,2)\\\
721 local sSide = string.sub(st,1,1)\\\
722 addRobot(x,y,sSide,Cr)\\\
723 end\\\
724 end\\\
725 end\\\
726 elseif sContext == \\\"tick\\\" then\\\
727 buMap()\\\
728 for x=1,SizeW do\\\
729 for y=1,SizeH do\\\
730 local rb = tostring(oScreen[x][y].robot)\\\
731 if not(rb == \\\"zz\\\" or rb == \\\"nil\\\") then\\\
732 local Cr = string.sub(rb,2,2)\\\
733 local sSide = string.sub(rb,1,1)\\\
734 local sobj = oScreen[x][y]\\\
735 if sobj.space == true then\\\
736 tScreen[x][y].robot = \\\"zz\\\"\\\
737 if not sSide == \\\"g\\\" then\\\
738 addRobot(x,y,\\\"g\\\",Cr)\\\
739 end\\\
740 elseif sobj.exit == Cr then\\\
741 if sSide == \\\"a\\\" or sSide == \\\"b\\\" or sSide == \\\"c\\\" or sSide == \\\"d\\\" then\\\
742 tScreen[x][y].robot = \\\"zz\\\"\\\
743 addRobot(x,y,\\\"g\\\",Cr)\\\
744 aExits = aExits-1\\\
745 end\\\
746 elseif sSide == \\\"a\\\" then\\\
747 local obj = isBrick(x,y-1)\\\
748 tScreen[x][y].robot = \\\"zz\\\"\\\
749 if not obj == true then\\\
750 addRobot(x,y-1,sSide,Cr)\\\
751 else\\\
752 local obj2 = isBrick(x-1,y)\\\
753 local obj3 = isBrick(x+1,y)\\\
754 if not obj2 == true and not obj3 == true then\\\
755 if Cr == \\\"a\\\" then\\\
756 addRobot(x,y,\\\"d\\\",Cr)\\\
757 elseif Cr == \\\"b\\\" then\\\
758 addRobot(x,y,\\\"b\\\",Cr)\\\
759 end\\\
760 elseif obj == true and obj2 == true and obj3 == true then\\\
761 addRobot(x,y,\\\"c\\\",Cr)\\\
762 else\\\
763 if obj3 == true then\\\
764 addRobot(x,y,\\\"d\\\",Cr)\\\
765 elseif obj2 == true then\\\
766 addRobot(x,y,\\\"b\\\",Cr)\\\
767 end\\\
768 end\\\
769 end\\\
770 elseif sSide == \\\"b\\\" then\\\
771 local obj = isBrick(x+1,y)\\\
772 tScreen[x][y].robot = \\\"zz\\\"\\\
773 if not obj == true then\\\
774 addRobot(x+1,y,sSide,Cr)\\\
775 else\\\
776 local obj2 = isBrick(x,y-1)\\\
777 local obj3 = isBrick(x,y+1)\\\
778 if not obj2 == true and not obj3 == true then\\\
779 if Cr == \\\"a\\\" then\\\
780 addRobot(x,y,\\\"a\\\",Cr)\\\
781 elseif Cr == \\\"b\\\" then\\\
782 addRobot(x,y,\\\"c\\\",Cr)\\\
783 end\\\
784 elseif obj == true and obj2 == true and obj3 == true then\\\
785 addRobot(x,y,\\\"d\\\",Cr)\\\
786 else\\\
787 if obj3 == true then\\\
788 addRobot(x,y,\\\"a\\\",Cr)\\\
789 elseif obj2 == true then\\\
790 addRobot(x,y,\\\"c\\\",Cr)\\\
791 end\\\
792 end\\\
793 end\\\
794 elseif sSide == \\\"c\\\" then\\\
795 local obj = isBrick(x,y+1)\\\
796 tScreen[x][y].robot = \\\"zz\\\"\\\
797 if not obj == true then\\\
798 addRobot(x,y+1,sSide,Cr)\\\
799 else\\\
800 local obj2 = isBrick(x-1,y)\\\
801 local obj3 = isBrick(x+1,y)\\\
802 if not obj2 == true and not obj3 == true then\\\
803 if Cr == \\\"a\\\" then\\\
804 addRobot(x,y,\\\"b\\\",Cr)\\\
805 elseif Cr == \\\"b\\\" then\\\
806 addRobot(x,y,\\\"d\\\",Cr)\\\
807 end\\\
808 elseif obj == true and obj2 == true and obj3 == true then\\\
809 addRobot(x,y,\\\"a\\\",Cr)\\\
810 else\\\
811 if obj3 == true then\\\
812 addRobot(x,y,\\\"d\\\",Cr)\\\
813 elseif obj2 == true then\\\
814 addRobot(x,y,\\\"b\\\",Cr)\\\
815 end\\\
816 end\\\
817 end\\\
818 elseif sSide == \\\"d\\\" then\\\
819 local obj = isBrick(x-1,y)\\\
820 tScreen[x][y].robot = \\\"zz\\\"\\\
821 if not obj == true then\\\
822 addRobot(x-1,y,sSide,Cr)\\\
823 else\\\
824 local obj2 = isBrick(x,y-1)\\\
825 local obj3 = isBrick(x,y+1)\\\
826 if not obj2 == true and not obj3 == true then\\\
827 if Cr == \\\"a\\\" then\\\
828 addRobot(x,y,\\\"c\\\",Cr)\\\
829 elseif Cr == \\\"b\\\" then\\\
830 addRobot(x,y,\\\"a\\\",Cr)\\\
831 end\\\
832 elseif obj == true and obj2 == true and obj3 == true then\\\
833 addRobot(x,y,\\\"b\\\",Cr)\\\
834 else\\\
835 if obj3 == true then\\\
836 addRobot(x,y,\\\"a\\\",Cr)\\\
837 elseif obj2 == true then\\\
838 addRobot(x,y,\\\"c\\\",Cr)\\\
839 end\\\
840 end\\\
841 end\\\
842 else\\\
843 addRobot(x,y,sSide,\\\"g\\\")\\\
844 end\\\
845 end\\\
846 end\\\
847 end\\\
848 end\\\
849end\\\
850\\\
851function InterFace.drawBar()\\\
852 term.setBackgroundColor( colors.black )\\\
853 term.setTextColor( InterFace.cTitle )\\\
854 printCentred( 1, \\\" \\\"..sLevelTitle..\\\" \\\" )\\\
855\\\
856 term.setCursorPos(1,1)\\\
857 term.setBackgroundColor( cW )\\\
858 write( \\\" \\\" )\\\
859 term.setBackgroundColor( colors.black )\\\
860 write( \\\" x \\\"..tostring(Blocks)..\\\" \\\" )\\\
861\\\
862 term.setCursorPos( TermW-8,TermH )\\\
863 term.setBackgroundColor( colors.black )\\\
864 term.setTextColour(InterFace.cSpeedD)\\\
865 write(\\\" <<\\\" )\\\
866 if bPaused then\\\
867 term.setTextColour(InterFace.cSpeedA)\\\
868 else\\\
869 term.setTextColour(InterFace.cSpeedD)\\\
870 end\\\
871 write(\\\" ||\\\")\\\
872 if fSpeedS then\\\
873 term.setTextColour(InterFace.cSpeedA)\\\
874 else\\\
875 term.setTextColour(InterFace.cSpeedD)\\\
876 end\\\
877 write(\\\" >>\\\")\\\
878\\\
879 term.setCursorPos( TermW-1, 1 )\\\
880 term.setBackgroundColor( colors.black )\\\
881 term.setTextColour( InterFace.cExit )\\\
882 write(\\\" X\\\")\\\
883 term.setBackgroundColor(colors.black)\\\
884end\\\
885\\\
886function InterFace.render()\\\
887 local id,p1,p2,p3 = os.pullEvent()\\\
888 if id == \\\"mouse_click\\\" then\\\
889 if p3 == 1 and p2 == TermW then\\\
890 return \\\"end\\\"\\\
891 elseif p3 == TermH and p2 >= TermW-7 and p2 <= TermW-6 then\\\
892 return \\\"retry\\\"\\\
893 elseif p3 == TermH and p2 >= TermW-4 and p2 <= TermW-3 then\\\
894 bPaused = not bPaused\\\
895 fSpeedS = false\\\
896 Speed = (bPaused and 0) or nSpeed\\\
897 if Speed > 0 then\\\
898 Tick = os.startTimer(Speed)\\\
899 else\\\
900 Tick = nil\\\
901 end\\\
902 InterFace.drawBar()\\\
903 elseif p3 == TermH and p2 >= TermW-1 then\\\
904 bPaused = false\\\
905 fSpeedS = not fSpeedS\\\
906 Speed = (fSpeedS and fSpeed) or nSpeed\\\
907 Tick = os.startTimer(Speed)\\\
908 InterFace.drawBar()\\\
909 elseif p3-1 < YOrgin+SizeH+1 and p3-1 > YOrgin and\\\
910 p2 < XOrgin+SizeW+1 and p2 > XOrgin then\\\
911 local eobj = tScreen[p2-XOrgin][p3-YOrgin-1]\\\
912 local erobj = tostring(tScreen[p2-XOrgin][p3-YOrgin-1].robot)\\\
913 if (erobj == \\\"zz\\\" or erobj == \\\"nil\\\") and not eobj.wall == true and not eobj.space == true and Blocks > 0 then\\\
914 addWall(p2-XOrgin,p3-YOrgin-1)\\\
915 Blocks = Blocks-1\\\
916 InterFace.drawBar()\\\
917 drawMap()\\\
918 end\\\
919 end\\\
920 elseif id == \\\"timer\\\" and p1 == Tick then\\\
921 gRender(\\\"tick\\\")\\\
922 drawMap()\\\
923 if Speed > 0 then\\\
924 Tick = os.startTimer(Speed)\\\
925 else\\\
926 Tick = nil\\\
927 end\\\
928 end\\\
929end\\\
930\\\
931local function startG(LevelN)\\\
932 drawStars()\\\
933 loadLevel(LevelN)\\\
934 centerOrgin()\\\
935 local create = true\\\
936 drawMap()\\\
937 InterFace.drawBar()\\\
938 gRender(\\\"start\\\")\\\
939 drawMap()\\\
940\\\
941 local NExit = true\\\
942 if aExits == 0 then\\\
943 NExit = false\\\
944 end\\\
945\\\
946 while true do\\\
947 local isExit = InterFace.render()\\\
948 if isExit == \\\"end\\\" then\\\
949 return nil\\\
950 elseif isExit == \\\"retry\\\" then\\\
951 return LevelN\\\
952 elseif fExit == \\\"yes\\\" then\\\
953 if fs.exists( fs.getDir( shell.getRunningProgram() ) .. \\\"/levels/\\\" .. tostring(LevelN + 1) .. \\\".dat\\\" ) then\\\
954 return LevelN + 1\\\
955 else\\\
956 return nil\\\
957 end\\\
958 end\\\
959 if aExits == 0 and NExit == true then\\\
960 fExit = \\\"yes\\\"\\\
961 end\\\
962 end\\\
963end\\\
964\\\
965local ok, err = true, nil\\\
966\\\
967--Menu--\\\
968local sStartLevel = tArgs[1]\\\
969if ok and not sStartLevel then\\\
970 ok, err = pcall( function()\\\
971 term.setTextColor(colors.white)\\\
972 term.setBackgroundColor( colors.black )\\\
973 term.clear()\\\
974 drawStars()\\\
975 term.setTextColor( colors.red )\\\
976 printCentred( TermH/2 - 1, \\\" REDIRECTION \\\" )\\\
977 printCentred( TermH/2 - 0, \\\" ComputerCraft Edition \\\" )\\\
978 term.setTextColor( colors.yellow )\\\
979 printCentred( TermH/2 + 2, \\\" Click to Begin \\\" )\\\
980 os.pullEvent( \\\"mouse_click\\\" )\\\
981 end )\\\
982end\\\
983\\\
984--Game--\\\
985if ok then\\\
986 ok,err = pcall( function()\\\
987 local nLevel\\\
988 if sStartLevel then\\\
989 nLevel = tonumber( sStartLevel )\\\
990 else\\\
991 nLevel = 1\\\
992 end\\\
993 while nLevel do\\\
994 reset()\\\
995 nLevel = startG(nLevel)\\\
996 end\\\
997 end )\\\
998end\\\
999\\\
1000--Upsell screen--\\\
1001if ok then\\\
1002 ok, err = pcall( function()\\\
1003 term.setTextColor(colors.white)\\\
1004 term.setBackgroundColor( colors.black )\\\
1005 term.clear()\\\
1006 drawStars()\\\
1007 term.setTextColor( colors.red )\\\
1008 if TermW >= 40 then\\\
1009 printCentred( TermH/2 - 1, \\\" Thank you for playing Redirection \\\" )\\\
1010 printCentred( TermH/2 - 0, \\\" ComputerCraft Edition \\\" )\\\
1011 printCentred( TermH/2 + 2, \\\" Check out the full game: \\\" )\\\
1012 term.setTextColor( colors.yellow )\\\
1013 printCentred( TermH/2 + 3, \\\" http://www.redirectiongame.com \\\" )\\\
1014 else\\\
1015 printCentred( TermH/2 - 2, \\\" Thank you for \\\" )\\\
1016 printCentred( TermH/2 - 1, \\\" playing Redirection \\\" )\\\
1017 printCentred( TermH/2 - 0, \\\" ComputerCraft Edition \\\" )\\\
1018 printCentred( TermH/2 + 2, \\\" Check out the full game: \\\" )\\\
1019 term.setTextColor( colors.yellow )\\\
1020 printCentred( TermH/2 + 3, \\\" www.redirectiongame.com \\\" )\\\
1021 end\\\
1022 parallel.waitForAll(\\\
1023 function() sleep(2) end,\\\
1024 function() os.pullEvent( \\\"mouse_click\\\" ) end\\\
1025 )\\\
1026 end )\\\
1027end\\\
1028\\\
1029--Clear and exit--\\\
1030term.setCursorPos(1,1)\\\
1031term.setTextColor(colors.white)\\\
1032term.setBackgroundColor(colors.black)\\\
1033term.clear()\\\
1034if not ok then\\\
1035 if err == \\\"Terminated\\\" then\\\
1036 print( \\\"Check out the full version of Redirection:\\\" )\\\
1037 print( \\\"http://www.redirectiongame.com\\\" )\\\
1038 else\\\
1039 printError( err )\\\
1040 end\\\
1041end\",\
1042 [ \"help/credits-emu.txt\" ] = \"CCEmuX would not be possible without the help of several open source projects:\\\
1043\\\
1044## Commons CLI\\\
1045Apache Commons CLI\\\
1046Copyright 2001-2017 The Apache Software Foundation\\\
1047\\\
1048This product includes software developed at\\\
1049The Apache Software Foundation (http://www.apache.org/).\\\
1050\\\
1051Licensed to the Apache Software Foundation (ASF) under one or more\\\
1052contributor license agreements. See the NOTICE file distributed with\\\
1053this work for additional information regarding copyright ownership.\\\
1054The ASF licenses this file to You under the Apache License, Version 2.0\\\
1055(the \\\"License\\\"); you may not use this file except in compliance with\\\
1056the License. You may obtain a copy of the License at\\\
1057\\\
1058 http://www.apache.org/licenses/LICENSE-2.0\\\
1059\\\
1060Unless required by applicable law or agreed to in writing, software\\\
1061distributed under the License is distributed on an \\\"AS IS\\\" BASIS,\\\
1062WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\\\
1063See the License for the specific language governing permissions and\\\
1064limitations under the License.\\\
1065\\\
1066## Commons Lang\\\
1067Apache Commons Lang\\\
1068Copyright 2001-2017 The Apache Software Foundation\\\
1069\\\
1070This product includes software developed at\\\
1071The Apache Software Foundation (http://www.apache.org/).\\\
1072\\\
1073This product includes software from the Spring Framework,\\\
1074under the Apache License 2.0 (see: StringUtils.containsWhitespace())\\\
1075\\\
1076Licensed to the Apache Software Foundation (ASF) under one or more\\\
1077contributor license agreements. See the NOTICE file distributed with\\\
1078this work for additional information regarding copyright ownership.\\\
1079The ASF licenses this file to You under the Apache License, Version 2.0\\\
1080(the \\\"License\\\"); you may not use this file except in compliance with\\\
1081the License. You may obtain a copy of the License at\\\
1082\\\
1083 http://www.apache.org/licenses/LICENSE-2.0\\\
1084\\\
1085Unless required by applicable law or agreed to in writing, software\\\
1086distributed under the License is distributed on an \\\"AS IS\\\" BASIS,\\\
1087WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\\\
1088See the License for the specific language governing permissions and\\\
1089limitations under the License.\\\
1090\\\
1091## Guava\\\
1092Copyright (C) 2008 The Guava Authors\\\
1093\\\
1094Licensed under the Apache License, Version 2.0 (the \\\"License\\\");\\\
1095you may not use this file except in compliance with the License.\\\
1096You may obtain a copy of the License at\\\
1097\\\
1098http://www.apache.org/licenses/LICENSE-2.0\\\
1099\\\
1100Unless required by applicable law or agreed to in writing, software\\\
1101distributed under the License is distributed on an \\\"AS IS\\\" BASIS,\\\
1102WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\\\
1103See the License for the specific language governing permissions and\\\
1104limitations under the License.\\\
1105\\\
1106## Log4J\\\
1107Apache Log4j API\\\
1108Copyright 1999-2017 The Apache Software Foundation\\\
1109\\\
1110This product includes software developed at\\\
1111The Apache Software Foundation (http://www.apache.org/).\\\
1112\\\
1113Licensed to the Apache Software Foundation (ASF) under one or more\\\
1114contributor license agreements. See the NOTICE file distributed with\\\
1115this work for additional information regarding copyright ownership.\\\
1116The ASF licenses this file to You under the Apache license, Version 2.0\\\
1117(the \\\"License\\\"); you may not use this file except in compliance with\\\
1118the License. You may obtain a copy of the License at\\\
1119\\\
1120 http://www.apache.org/licenses/LICENSE-2.0\\\
1121\\\
1122Unless required by applicable law or agreed to in writing, software\\\
1123distributed under the License is distributed on an \\\"AS IS\\\" BASIS,\\\
1124WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\\\
1125See the license for the specific language governing permissions and\\\
1126limitations under the license.\\\
1127\\\
1128## Netty\\\
1129Copyright 2012 The Netty Project\\\
1130\\\
1131The Netty Project licenses this file to you under the Apache License,\\\
1132version 2.0 (the \\\"License\\\"); you may not use this file except in compliance\\\
1133with the License. You may obtain a copy of the License at:\\\
1134\\\
1135 http://www.apache.org/licenses/LICENSE-2.0\\\
1136\\\
1137Unless required by applicable law or agreed to in writing, software\\\
1138distributed under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT\\\
1139WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the\\\
1140License for the specific language governing permissions and limitations\\\
1141under the License.\",\
1142 [ \"help/commandsapi.txt\" ] = \"Functions in the commands API:\\\
1143commands.exec( command )\\\
1144commands.execAsync( command )\\\
1145commands.list()\\\
1146commands.getBlockPosition()\\\
1147commands.getBlockInfo( x, y, z )\\\
1148commands.getBlockInfos( minx, miny, minz, maxx, maxy, maxz )\\\
1149\\\
1150The commands API can also be used to invoke commands directly, like so:\\\
1151commands.say( \\\"Hello World\\\" )\\\
1152commands.give( \\\"dan200\\\", \\\"minecraft:diamond\\\", 64 )\\\
1153This works with any command. Use \\\"commands.async\\\" instead of \\\"commands\\\" to execute asynchronously.\\\
1154\\\
1155The commands API is only available on Command Computers.\\\
1156Visit http://minecraft.gamepedia.com/Commands for documentation on all commands.\",\
1157 [ \"help/io.txt\" ] = \"io is a standard Lua5.1 API, reimplemented for CraftOS. Not all the features are availiable.\\\
1158Refer to http://www.lua.org/manual/5.1/ for more information.\",\
1159 [ \"help/dj.txt\" ] = \"dj plays Music Discs from disk drives attached to the computer.\\\
1160\\\
1161ex:\\\
1162\\\"dj\\\" or \\\"dj play\\\" plays a random disc.\\\
1163\\\"dj play left\\\" plays the disc in the drive on the left of the computer.\\\
1164\\\"dj stop\\\" stops the current disc.\",\
1165 [ \"help/equip.txt\" ] = \"equip is a program for Turtles and Pocket Computer. equip will equip an item from the Turtle's inventory for use as a tool of peripheral. On a Pocket Computer you don't need to write a side.\\\
1166\\\
1167ex:\\\
1168\\\"equip 5 left\\\" will equip the item from slot 5 of the turtle onto the left side of the turtle\\\
1169\\\"equip\\\" on a Pocket Computer will equip the first item from your inventory.\",\
1170 [ \"programs/advanced/multishell.lua\" ] = \"\\\
1171-- Setup process switching\\\
1172local parentTerm = term.current()\\\
1173local w,h = parentTerm.getSize()\\\
1174\\\
1175local tProcesses = {}\\\
1176local nCurrentProcess = nil\\\
1177local nRunningProcess = nil\\\
1178local bShowMenu = false\\\
1179local bWindowsResized = false\\\
1180\\\
1181local function selectProcess( n )\\\
1182 if nCurrentProcess ~= n then\\\
1183 if nCurrentProcess then\\\
1184 local tOldProcess = tProcesses[ nCurrentProcess ]\\\
1185 tOldProcess.window.setVisible( false )\\\
1186 end\\\
1187 nCurrentProcess = n\\\
1188 if nCurrentProcess then\\\
1189 local tNewProcess = tProcesses[ nCurrentProcess ]\\\
1190 tNewProcess.window.setVisible( true )\\\
1191 tNewProcess.bInteracted = true\\\
1192 end\\\
1193 end\\\
1194end\\\
1195\\\
1196local function setProcessTitle( n, sTitle )\\\
1197 tProcesses[ n ].sTitle = sTitle\\\
1198end\\\
1199\\\
1200local function resumeProcess( nProcess, sEvent, ... )\\\
1201 local tProcess = tProcesses[ nProcess ]\\\
1202 local sFilter = tProcess.sFilter\\\
1203 if sFilter == nil or sFilter == sEvent or sEvent == \\\"terminate\\\" then\\\
1204 local nPreviousProcess = nRunningProcess\\\
1205 nRunningProcess = nProcess\\\
1206 term.redirect( tProcess.terminal )\\\
1207 local ok, result = coroutine.resume( tProcess.co, sEvent, ... )\\\
1208 tProcess.terminal = term.current()\\\
1209 if ok then\\\
1210 tProcess.sFilter = result\\\
1211 else\\\
1212 printError( result )\\\
1213 end\\\
1214 nRunningProcess = nPreviousProcess\\\
1215 end\\\
1216end\\\
1217\\\
1218local function launchProcess( tProgramEnv, sProgramPath, ... )\\\
1219 local tProgramArgs = table.pack( ... )\\\
1220 local nProcess = #tProcesses + 1\\\
1221 local tProcess = {}\\\
1222 tProcess.sTitle = fs.getName( sProgramPath )\\\
1223 if bShowMenu then\\\
1224 tProcess.window = window.create( parentTerm, 1, 2, w, h-1, false )\\\
1225 else\\\
1226 tProcess.window = window.create( parentTerm, 1, 1, w, h, false )\\\
1227 end\\\
1228 tProcess.co = coroutine.create( function()\\\
1229 os.run( tProgramEnv, sProgramPath, table.unpack( tProgramArgs, 1, tProgramArgs.n ) )\\\
1230 if not tProcess.bInteracted then\\\
1231 term.setCursorBlink( false )\\\
1232 print( \\\"Press any key to continue\\\" )\\\
1233 os.pullEvent( \\\"char\\\" )\\\
1234 end\\\
1235 end )\\\
1236 tProcess.sFilter = nil\\\
1237 tProcess.terminal = tProcess.window\\\
1238 tProcess.bInteracted = false\\\
1239 tProcesses[ nProcess ] = tProcess\\\
1240 resumeProcess( nProcess )\\\
1241 return nProcess\\\
1242end\\\
1243\\\
1244local function cullProcess( nProcess )\\\
1245 local tProcess = tProcesses[ nProcess ]\\\
1246 if coroutine.status( tProcess.co ) == \\\"dead\\\" then\\\
1247 if nCurrentProcess == nProcess then\\\
1248 selectProcess( nil )\\\
1249 end\\\
1250 table.remove( tProcesses, nProcess )\\\
1251 if nCurrentProcess == nil then\\\
1252 if nProcess > 1 then\\\
1253 selectProcess( nProcess - 1 )\\\
1254 elseif #tProcesses > 0 then\\\
1255 selectProcess( 1 )\\\
1256 end\\\
1257 end\\\
1258 return true\\\
1259 end\\\
1260 return false\\\
1261end\\\
1262\\\
1263local function cullProcesses()\\\
1264 local culled = false\\\
1265 for n=#tProcesses,1,-1 do\\\
1266 culled = culled or cullProcess( n )\\\
1267 end\\\
1268 return culled\\\
1269end\\\
1270\\\
1271-- Setup the main menu\\\
1272local menuMainTextColor, menuMainBgColor, menuOtherTextColor, menuOtherBgColor\\\
1273if parentTerm.isColor() then\\\
1274 menuMainTextColor, menuMainBgColor = colors.yellow, colors.black\\\
1275 menuOtherTextColor, menuOtherBgColor = colors.black, colors.gray\\\
1276else\\\
1277 menuMainTextColor, menuMainBgColor = colors.white, colors.black\\\
1278 menuOtherTextColor, menuOtherBgColor = colors.black, colors.gray\\\
1279end\\\
1280\\\
1281local function redrawMenu()\\\
1282 if bShowMenu then\\\
1283 -- Draw menu\\\
1284 parentTerm.setCursorPos( 1, 1 )\\\
1285 parentTerm.setBackgroundColor( menuOtherBgColor )\\\
1286 parentTerm.clearLine()\\\
1287 for n=1,#tProcesses do\\\
1288 if n == nCurrentProcess then\\\
1289 parentTerm.setTextColor( menuMainTextColor )\\\
1290 parentTerm.setBackgroundColor( menuMainBgColor )\\\
1291 else\\\
1292 parentTerm.setTextColor( menuOtherTextColor )\\\
1293 parentTerm.setBackgroundColor( menuOtherBgColor )\\\
1294 end\\\
1295 parentTerm.write( \\\" \\\" .. tProcesses[n].sTitle .. \\\" \\\" )\\\
1296 end\\\
1297\\\
1298 -- Put the cursor back where it should be\\\
1299 local tProcess = tProcesses[ nCurrentProcess ]\\\
1300 if tProcess then\\\
1301 tProcess.window.restoreCursor()\\\
1302 end\\\
1303 end\\\
1304end\\\
1305\\\
1306local function resizeWindows()\\\
1307 local windowY, windowHeight\\\
1308 if bShowMenu then\\\
1309 windowY = 2\\\
1310 windowHeight = h-1\\\
1311 else\\\
1312 windowY = 1\\\
1313 windowHeight = h\\\
1314 end\\\
1315 for n=1,#tProcesses do\\\
1316 local tProcess = tProcesses[n]\\\
1317 local window = tProcess.window\\\
1318 local x,y = tProcess.window.getCursorPos()\\\
1319 if y > windowHeight then\\\
1320 tProcess.window.scroll( y - windowHeight )\\\
1321 tProcess.window.setCursorPos( x, windowHeight )\\\
1322 end\\\
1323 tProcess.window.reposition( 1, windowY, w, windowHeight )\\\
1324 end\\\
1325 bWindowsResized = true\\\
1326end\\\
1327\\\
1328local function setMenuVisible( bVis )\\\
1329 if bShowMenu ~= bVis then\\\
1330 bShowMenu = bVis\\\
1331 resizeWindows()\\\
1332 redrawMenu()\\\
1333 end\\\
1334end\\\
1335\\\
1336local multishell = {}\\\
1337\\\
1338function multishell.getFocus()\\\
1339 return nCurrentProcess\\\
1340end\\\
1341\\\
1342function multishell.setFocus( n )\\\
1343 if type( n ) ~= \\\"number\\\" then\\\
1344 error( \\\"bad argument #1 (expected number, got \\\" .. type( n ) .. \\\")\\\", 2 )\\\
1345 end\\\
1346 if n >= 1 and n <= #tProcesses then\\\
1347 selectProcess( n )\\\
1348 redrawMenu()\\\
1349 return true\\\
1350 end\\\
1351 return false\\\
1352end\\\
1353\\\
1354function multishell.getTitle( n )\\\
1355 if type( n ) ~= \\\"number\\\" then\\\
1356 error( \\\"bad argument #1 (expected number, got \\\" .. type( n ) .. \\\")\\\", 2 )\\\
1357 end\\\
1358 if n >= 1 and n <= #tProcesses then\\\
1359 return tProcesses[n].sTitle\\\
1360 end\\\
1361 return nil\\\
1362end\\\
1363\\\
1364function multishell.setTitle( n, sTitle )\\\
1365 if type( n ) ~= \\\"number\\\" then\\\
1366 error( \\\"bad argument #1 (expected number, got \\\" .. type( n ) .. \\\")\\\", 2 )\\\
1367 end\\\
1368 if type( sTitle ) ~= \\\"string\\\" then\\\
1369 error( \\\"bad argument #2 (expected string, got \\\" .. type( sTitle ) .. \\\")\\\", 2 )\\\
1370 end\\\
1371 if n >= 1 and n <= #tProcesses then\\\
1372 setProcessTitle( n, sTitle )\\\
1373 redrawMenu()\\\
1374 end\\\
1375end\\\
1376\\\
1377function multishell.getCurrent()\\\
1378 return nRunningProcess\\\
1379end\\\
1380\\\
1381function multishell.launch( tProgramEnv, sProgramPath, ... )\\\
1382 if type( tProgramEnv ) ~= \\\"table\\\" then\\\
1383 error( \\\"bad argument #1 (expected table, got \\\" .. type( tProgramEnv ) .. \\\")\\\", 2 )\\\
1384 end\\\
1385 if type( sProgramPath ) ~= \\\"string\\\" then\\\
1386 error( \\\"bad argument #2 (expected string, got \\\" .. type( sProgramPath ) .. \\\")\\\", 2 )\\\
1387 end\\\
1388 local previousTerm = term.current()\\\
1389 setMenuVisible( (#tProcesses + 1) >= 2 )\\\
1390 local nResult = launchProcess( tProgramEnv, sProgramPath, ... )\\\
1391 redrawMenu()\\\
1392 term.redirect( previousTerm )\\\
1393 return nResult\\\
1394end\\\
1395\\\
1396function multishell.getCount()\\\
1397 return #tProcesses\\\
1398end\\\
1399\\\
1400-- Begin\\\
1401parentTerm.clear()\\\
1402setMenuVisible( false )\\\
1403selectProcess( launchProcess( {\\\
1404 [\\\"shell\\\"] = shell,\\\
1405 [\\\"multishell\\\"] = multishell,\\\
1406}, \\\"/rom/programs/shell.lua\\\" ) )\\\
1407redrawMenu()\\\
1408\\\
1409-- Run processes\\\
1410while #tProcesses > 0 do\\\
1411 -- Get the event\\\
1412 local tEventData = table.pack( os.pullEventRaw() )\\\
1413 local sEvent = tEventData[1]\\\
1414 if sEvent == \\\"term_resize\\\" then\\\
1415 -- Resize event\\\
1416 w,h = parentTerm.getSize()\\\
1417 resizeWindows()\\\
1418 redrawMenu()\\\
1419\\\
1420 elseif sEvent == \\\"char\\\" or sEvent == \\\"key\\\" or sEvent == \\\"key_up\\\" or sEvent == \\\"paste\\\" or sEvent == \\\"terminate\\\" then\\\
1421 -- Keyboard event\\\
1422 -- Passthrough to current process\\\
1423 resumeProcess( nCurrentProcess, table.unpack( tEventData, 1, tEventData.n ) )\\\
1424 if cullProcess( nCurrentProcess ) then\\\
1425 setMenuVisible( #tProcesses >= 2 )\\\
1426 redrawMenu()\\\
1427 end\\\
1428\\\
1429 elseif sEvent == \\\"mouse_click\\\" then\\\
1430 -- Click event\\\
1431 local button, x, y = tEventData[2], tEventData[3], tEventData[4]\\\
1432 if bShowMenu and y == 1 then\\\
1433 -- Switch process\\\
1434 local tabStart = 1\\\
1435 for n=1,#tProcesses do\\\
1436 local tabEnd = tabStart + string.len( tProcesses[n].sTitle ) + 1\\\
1437 if x >= tabStart and x <= tabEnd then\\\
1438 selectProcess( n )\\\
1439 redrawMenu()\\\
1440 break\\\
1441 end\\\
1442 tabStart = tabEnd + 1\\\
1443 end\\\
1444 else\\\
1445 -- Passthrough to current process\\\
1446 resumeProcess( nCurrentProcess, sEvent, button, x, (bShowMenu and y-1) or y )\\\
1447 if cullProcess( nCurrentProcess ) then\\\
1448 setMenuVisible( #tProcesses >= 2 )\\\
1449 redrawMenu()\\\
1450 end\\\
1451 end\\\
1452\\\
1453 elseif sEvent == \\\"mouse_drag\\\" or sEvent == \\\"mouse_up\\\" or sEvent == \\\"mouse_scroll\\\" then\\\
1454 -- Other mouse event\\\
1455 local p1, x, y = tEventData[2], tEventData[3], tEventData[4]\\\
1456 if not (bShowMenu and y == 1) then\\\
1457 -- Passthrough to current process\\\
1458 resumeProcess( nCurrentProcess, sEvent, p1, x, (bShowMenu and y-1) or y )\\\
1459 if cullProcess( nCurrentProcess ) then\\\
1460 setMenuVisible( #tProcesses >= 2 )\\\
1461 redrawMenu()\\\
1462 end\\\
1463 end\\\
1464\\\
1465 else\\\
1466 -- Other event\\\
1467 -- Passthrough to all processes\\\
1468 local nLimit = #tProcesses -- Storing this ensures any new things spawned don't get the event\\\
1469 for n=1,nLimit do\\\
1470 resumeProcess( n, table.unpack( tEventData, 1, tEventData.n ) )\\\
1471 end\\\
1472 if cullProcesses() then\\\
1473 setMenuVisible( #tProcesses >= 2 )\\\
1474 redrawMenu()\\\
1475 end\\\
1476 end\\\
1477\\\
1478 if bWindowsResized then\\\
1479 -- Pass term_resize to all processes\\\
1480 local nLimit = #tProcesses -- Storing this ensures any new things spawned don't get the event\\\
1481 for n=1,nLimit do\\\
1482 resumeProcess( n, \\\"term_resize\\\" )\\\
1483 end\\\
1484 bWindowsResized = false\\\
1485 if cullProcesses() then\\\
1486 setMenuVisible( #tProcesses >= 2 )\\\
1487 redrawMenu()\\\
1488 end\\\
1489 end\\\
1490end\\\
1491\\\
1492-- Shutdown\\\
1493term.redirect( parentTerm )\",\
1494 [ \"programs/fun/adventure.lua\" ] = \"\\\
1495local tBiomes = {\\\
1496 \\\"in a forest\\\",\\\
1497 \\\"in a pine forest\\\",\\\
1498 \\\"knee deep in a swamp\\\",\\\
1499 \\\"in a mountain range\\\",\\\
1500 \\\"in a desert\\\",\\\
1501 \\\"in a grassy plain\\\",\\\
1502 \\\"in frozen tundra\\\",\\\
1503}\\\
1504\\\
1505local function hasTrees( _nBiome )\\\
1506 return _nBiome <= 3\\\
1507end\\\
1508\\\
1509local function hasStone( _nBiome )\\\
1510 return _nBiome == 4\\\
1511end\\\
1512\\\
1513local function hasRivers( _nBiome )\\\
1514 return _nBiome ~= 3 and _nBiome ~= 5\\\
1515end\\\
1516\\\
1517local items = {\\\
1518 [\\\"no tea\\\"] = {\\\
1519 droppable = false,\\\
1520 desc = \\\"Pull yourself together man.\\\",\\\
1521 },\\\
1522 [\\\"a pig\\\"] = {\\\
1523 heavy = true,\\\
1524 creature = true,\\\
1525 drops = { \\\"some pork\\\" },\\\
1526 aliases = { \\\"pig\\\" },\\\
1527 desc = \\\"The pig has a square nose.\\\",\\\
1528 },\\\
1529 [\\\"a cow\\\"] = {\\\
1530 heavy = true,\\\
1531 creature = true,\\\
1532 aliases = { \\\"cow\\\" },\\\
1533 desc = \\\"The cow stares at you blankly.\\\",\\\
1534 },\\\
1535 [\\\"a sheep\\\"] = {\\\
1536 heavy = true,\\\
1537 creature = true,\\\
1538 hitDrops = { \\\"some wool\\\" },\\\
1539 aliases = { \\\"sheep\\\" },\\\
1540 desc = \\\"The sheep is fluffy.\\\",\\\
1541 },\\\
1542 [\\\"a chicken\\\"] = {\\\
1543 heavy = true,\\\
1544 creature = true,\\\
1545 drops = { \\\"some chicken\\\" },\\\
1546 aliases = { \\\"chicken\\\" },\\\
1547 desc = \\\"The chicken looks delicious.\\\",\\\
1548 },\\\
1549 [\\\"a creeper\\\"] = {\\\
1550 heavy = true,\\\
1551 creature = true,\\\
1552 monster = true,\\\
1553 aliases = { \\\"creeper\\\" },\\\
1554 desc = \\\"The creeper needs a hug.\\\",\\\
1555 },\\\
1556 [\\\"a skeleton\\\"] = {\\\
1557 heavy = true,\\\
1558 creature = true,\\\
1559 monster = true,\\\
1560 aliases = { \\\"skeleton\\\" },\\\
1561 nocturnal = true,\\\
1562 desc = \\\"The head bone's connected to the neck bone, the neck bone's connected to the chest bone, the chest bone's connected to the arm bone, the arm bone's connected to the bow, and the bow is pointed at you.\\\",\\\
1563 },\\\
1564 [\\\"a zombie\\\"] = {\\\
1565 heavy = true,\\\
1566 creature = true,\\\
1567 monster = true,\\\
1568 aliases = { \\\"zombie\\\" },\\\
1569 nocturnal = true,\\\
1570 desc = \\\"All he wants to do is eat your brains.\\\",\\\
1571 },\\\
1572 [\\\"a spider\\\"] = {\\\
1573 heavy = true,\\\
1574 creature = true,\\\
1575 monster = true,\\\
1576 aliases = { \\\"spider\\\" },\\\
1577 desc = \\\"Dozens of eyes stare back at you.\\\",\\\
1578 },\\\
1579 [\\\"a cave entrance\\\"] = {\\\
1580 heavy = true,\\\
1581 aliases = { \\\"cave entance\\\", \\\"cave\\\", \\\"entrance\\\" },\\\
1582 desc = \\\"The entrance to the cave is dark, but it looks like you can climb down.\\\",\\\
1583 },\\\
1584 [\\\"an exit to the surface\\\"] = {\\\
1585 heavy = true,\\\
1586 aliases = { \\\"exit to the surface\\\", \\\"exit\\\", \\\"opening\\\" },\\\
1587 desc = \\\"You can just see the sky through the opening.\\\",\\\
1588 },\\\
1589 [\\\"a river\\\"] = {\\\
1590 heavy = true,\\\
1591 aliases = { \\\"river\\\" },\\\
1592 desc = \\\"The river flows majestically towards the horizon. It doesn't do anything else.\\\",\\\
1593 },\\\
1594 [\\\"some wood\\\"] = {\\\
1595 aliases = { \\\"wood\\\" },\\\
1596 material = true,\\\
1597 desc = \\\"You could easilly craft this wood into planks.\\\",\\\
1598 },\\\
1599 [\\\"some planks\\\"] = {\\\
1600 aliases = { \\\"planks\\\", \\\"wooden planks\\\", \\\"wood planks\\\" },\\\
1601 desc = \\\"You could easilly craft these planks into sticks.\\\",\\\
1602 },\\\
1603 [\\\"some sticks\\\"] = {\\\
1604 aliases = { \\\"sticks\\\", \\\"wooden sticks\\\", \\\"wood sticks\\\" },\\\
1605 desc = \\\"A perfect handle for torches or a pickaxe.\\\",\\\
1606 },\\\
1607 [\\\"a crafting table\\\"] = {\\\
1608 aliases = { \\\"crafting table\\\", \\\"craft table\\\", \\\"work bench\\\", \\\"workbench\\\", \\\"crafting bench\\\", \\\"table\\\", },\\\
1609 desc = \\\"It's a crafting table. I shouldn't tell you this, but these don't actually do anything in this game, you can craft tools whenever you like.\\\",\\\
1610 },\\\
1611 [\\\"a furnace\\\"] = {\\\
1612 aliases = { \\\"furnace\\\" },\\\
1613 desc = \\\"It's a furnace. Between you and me, these don't actually do anything in this game.\\\",\\\
1614 },\\\
1615 [\\\"a wooden pickaxe\\\"] = {\\\
1616 aliases = { \\\"pickaxe\\\", \\\"pick\\\", \\\"wooden pick\\\", \\\"wooden pickaxe\\\", \\\"wood pick\\\", \\\"wood pickaxe\\\" },\\\
1617 tool = true,\\\
1618 toolLevel = 1,\\\
1619 toolType = \\\"pick\\\",\\\
1620 desc = \\\"The pickaxe looks good for breaking stone and coal.\\\",\\\
1621 },\\\
1622 [\\\"a stone pickaxe\\\"] = {\\\
1623 aliases = { \\\"pickaxe\\\", \\\"pick\\\", \\\"stone pick\\\", \\\"stone pickaxe\\\" },\\\
1624 tool = true,\\\
1625 toolLevel = 2,\\\
1626 toolType = \\\"pick\\\",\\\
1627 desc = \\\"The pickaxe looks good for breaking iron.\\\",\\\
1628 },\\\
1629 [\\\"an iron pickaxe\\\"] = {\\\
1630 aliases = { \\\"pickaxe\\\", \\\"pick\\\", \\\"iron pick\\\", \\\"iron pickaxe\\\" },\\\
1631 tool = true,\\\
1632 toolLevel = 3,\\\
1633 toolType = \\\"pick\\\",\\\
1634 desc = \\\"The pickaxe looks strong enough to break diamond.\\\",\\\
1635 },\\\
1636 [\\\"a diamond pickaxe\\\"] = {\\\
1637 aliases = { \\\"pickaxe\\\", \\\"pick\\\", \\\"diamond pick\\\", \\\"diamond pickaxe\\\" },\\\
1638 tool = true,\\\
1639 toolLevel = 4,\\\
1640 toolType = \\\"pick\\\",\\\
1641 desc = \\\"Best. Pickaxe. Ever.\\\",\\\
1642 },\\\
1643 [\\\"a wooden sword\\\"] = {\\\
1644 aliases = { \\\"sword\\\", \\\"wooden sword\\\", \\\"wood sword\\\" },\\\
1645 tool = true,\\\
1646 toolLevel = 1,\\\
1647 toolType = \\\"sword\\\",\\\
1648 desc = \\\"Flimsy, but better than nothing.\\\",\\\
1649 },\\\
1650 [\\\"a stone sword\\\"] = {\\\
1651 aliases = { \\\"sword\\\", \\\"stone sword\\\" },\\\
1652 tool = true,\\\
1653 toolLevel = 2,\\\
1654 toolType = \\\"sword\\\",\\\
1655 desc = \\\"A pretty good sword.\\\",\\\
1656 },\\\
1657 [\\\"an iron sword\\\"] = {\\\
1658 aliases = { \\\"sword\\\", \\\"iron sword\\\" },\\\
1659 tool = true,\\\
1660 toolLevel = 3,\\\
1661 toolType = \\\"sword\\\",\\\
1662 desc = \\\"This sword can slay any enemy.\\\",\\\
1663 },\\\
1664 [\\\"a diamond sword\\\"] = {\\\
1665 aliases = { \\\"sword\\\", \\\"diamond sword\\\" },\\\
1666 tool = true,\\\
1667 toolLevel = 4,\\\
1668 toolType = \\\"sword\\\",\\\
1669 desc = \\\"Best. Sword. Ever.\\\",\\\
1670 },\\\
1671 [\\\"a wooden shovel\\\"] = {\\\
1672 aliases = { \\\"shovel\\\", \\\"wooden shovel\\\", \\\"wood shovel\\\" },\\\
1673 tool = true,\\\
1674 toolLevel = 1,\\\
1675 toolType = \\\"shovel\\\",\\\
1676 desc = \\\"Good for digging holes.\\\",\\\
1677 },\\\
1678 [\\\"a stone shovel\\\"] = {\\\
1679 aliases = { \\\"shovel\\\", \\\"stone shovel\\\" },\\\
1680 tool = true,\\\
1681 toolLevel = 2,\\\
1682 toolType = \\\"shovel\\\",\\\
1683 desc = \\\"Good for digging holes.\\\",\\\
1684 },\\\
1685 [\\\"an iron shovel\\\"] = {\\\
1686 aliases = { \\\"shovel\\\", \\\"iron shovel\\\" },\\\
1687 tool = true,\\\
1688 toolLevel = 3,\\\
1689 toolType = \\\"shovel\\\",\\\
1690 desc = \\\"Good for digging holes.\\\",\\\
1691 },\\\
1692 [\\\"a diamond shovel\\\"] = {\\\
1693 aliases = { \\\"shovel\\\", \\\"diamond shovel\\\" },\\\
1694 tool = true,\\\
1695 toolLevel = 4,\\\
1696 toolType = \\\"shovel\\\",\\\
1697 desc = \\\"Good for digging holes.\\\",\\\
1698 },\\\
1699 [\\\"some coal\\\"] = {\\\
1700 aliases = { \\\"coal\\\" },\\\
1701 ore = true,\\\
1702 toolLevel = 1,\\\
1703 toolType = \\\"pick\\\",\\\
1704 desc = \\\"That coal looks useful for building torches, if only you had a pickaxe to mine it.\\\",\\\
1705 },\\\
1706 [\\\"some dirt\\\"] = {\\\
1707 aliases = { \\\"dirt\\\" },\\\
1708 material = true,\\\
1709 desc = \\\"Why not build a mud hut?\\\",\\\
1710 },\\\
1711 [\\\"some stone\\\"] = {\\\
1712 aliases = { \\\"stone\\\", \\\"cobblestone\\\" },\\\
1713 material = true,\\\
1714 ore = true,\\\
1715 infinite = true,\\\
1716 toolLevel = 1,\\\
1717 toolType = \\\"pick\\\",\\\
1718 desc = \\\"Stone is useful for building things, and making stone pickaxes.\\\",\\\
1719 },\\\
1720 [\\\"some iron\\\"] = {\\\
1721 aliases = { \\\"iron\\\" },\\\
1722 material = true,\\\
1723 ore = true,\\\
1724 toolLevel = 2,\\\
1725 toolType = \\\"pick\\\",\\\
1726 desc = \\\"That iron looks mighty strong, you'll need a stone pickaxe to mine it.\\\",\\\
1727 },\\\
1728 [\\\"some diamond\\\"] = {\\\
1729 aliases = { \\\"diamond\\\", \\\"diamonds\\\" },\\\
1730 material = true,\\\
1731 ore = true,\\\
1732 toolLevel = 3,\\\
1733 toolType = \\\"pick\\\",\\\
1734 desc = \\\"Sparkly, rare, and impossible to mine without an iron pickaxe.\\\",\\\
1735 },\\\
1736 [\\\"some torches\\\"] = {\\\
1737 aliases = { \\\"torches\\\", \\\"torch\\\" },\\\
1738 desc = \\\"These won't run out for a while.\\\",\\\
1739 },\\\
1740 [\\\"a torch\\\"] = {\\\
1741 aliases = { \\\"torch\\\" },\\\
1742 desc = \\\"Fire, fire, burn so bright, won't you light my cave tonight?\\\",\\\
1743 },\\\
1744 [\\\"some wool\\\"] = {\\\
1745 aliases = { \\\"wool\\\" },\\\
1746 material = true,\\\
1747 desc = \\\"Soft and good for building.\\\",\\\
1748 },\\\
1749 [\\\"some pork\\\"] = {\\\
1750 aliases = { \\\"pork\\\", \\\"porkchops\\\" },\\\
1751 food = true,\\\
1752 desc = \\\"Delicious and nutricious.\\\",\\\
1753 },\\\
1754 [\\\"some chicken\\\"] = {\\\
1755 aliases = { \\\"chicken\\\" },\\\
1756 food = true,\\\
1757 desc = \\\"Finger licking good.\\\",\\\
1758 },\\\
1759}\\\
1760\\\
1761local tAnimals = {\\\
1762 \\\"a pig\\\", \\\"a cow\\\", \\\"a sheep\\\", \\\"a chicken\\\",\\\
1763}\\\
1764\\\
1765local tMonsters = {\\\
1766 \\\"a creeper\\\", \\\"a skeleton\\\", \\\"a zombie\\\", \\\"a spider\\\"\\\
1767}\\\
1768\\\
1769local tRecipes = {\\\
1770 [\\\"some planks\\\"] = { \\\"some wood\\\" },\\\
1771 [\\\"some sticks\\\"] = { \\\"some planks\\\" },\\\
1772 [\\\"a crafting table\\\"] = { \\\"some planks\\\" },\\\
1773 [\\\"a furnace\\\"] = { \\\"some stone\\\" },\\\
1774 [\\\"some torches\\\"] = { \\\"some sticks\\\", \\\"some coal\\\" },\\\
1775\\\
1776 [\\\"a wooden pickaxe\\\"] = { \\\"some planks\\\", \\\"some sticks\\\" },\\\
1777 [\\\"a stone pickaxe\\\"] = { \\\"some stone\\\", \\\"some sticks\\\" },\\\
1778 [\\\"an iron pickaxe\\\"] = { \\\"some iron\\\", \\\"some sticks\\\" },\\\
1779 [\\\"a diamond pickaxe\\\"] = { \\\"some diamond\\\", \\\"some sticks\\\" },\\\
1780\\\
1781 [\\\"a wooden sword\\\"] = { \\\"some planks\\\", \\\"some sticks\\\" },\\\
1782 [\\\"a stone sword\\\"] = { \\\"some stone\\\", \\\"some sticks\\\" },\\\
1783 [\\\"an iron sword\\\"] = { \\\"some iron\\\", \\\"some sticks\\\" },\\\
1784 [\\\"a diamond sword\\\"] = { \\\"some diamond\\\", \\\"some sticks\\\" },\\\
1785\\\
1786 [\\\"a wooden shovel\\\"] = { \\\"some planks\\\", \\\"some sticks\\\" },\\\
1787 [\\\"a stone shovel\\\"] = { \\\"some stone\\\", \\\"some sticks\\\" },\\\
1788 [\\\"an iron shovel\\\"] = { \\\"some iron\\\", \\\"some sticks\\\" },\\\
1789 [\\\"a diamond shovel\\\"] = { \\\"some diamond\\\", \\\"some sticks\\\" },\\\
1790}\\\
1791\\\
1792local tGoWest = {\\\
1793 \\\"(life is peaceful there)\\\",\\\
1794 \\\"(lots of open air)\\\",\\\
1795 \\\"(to begin life anew)\\\",\\\
1796 \\\"(this is what we'll do)\\\",\\\
1797 \\\"(sun in winter time)\\\",\\\
1798 \\\"(we will do just fine)\\\",\\\
1799 \\\"(where the skies are blue)\\\",\\\
1800 \\\"(this and more we'll do)\\\",\\\
1801}\\\
1802local nGoWest = 0\\\
1803\\\
1804local bRunning = true\\\
1805local tMap = { { {}, }, }\\\
1806local x,y,z = 0,0,0\\\
1807local inventory = {\\\
1808 [\\\"no tea\\\"] = items[\\\"no tea\\\"],\\\
1809}\\\
1810\\\
1811local nTurn = 0\\\
1812local nTimeInRoom = 0\\\
1813local bInjured = false\\\
1814\\\
1815local tDayCycle = {\\\
1816 \\\"It is daytime.\\\",\\\
1817 \\\"It is daytime.\\\",\\\
1818 \\\"It is daytime.\\\",\\\
1819 \\\"It is daytime.\\\",\\\
1820 \\\"It is daytime.\\\",\\\
1821 \\\"It is daytime.\\\",\\\
1822 \\\"It is daytime.\\\",\\\
1823 \\\"It is daytime.\\\",\\\
1824 \\\"The sun is setting.\\\",\\\
1825 \\\"It is night.\\\",\\\
1826 \\\"It is night.\\\",\\\
1827 \\\"It is night.\\\",\\\
1828 \\\"It is night.\\\",\\\
1829 \\\"It is night.\\\",\\\
1830 \\\"The sun is rising.\\\",\\\
1831}\\\
1832\\\
1833local function getTimeOfDay()\\\
1834 return math.fmod( math.floor(nTurn/3), #tDayCycle ) + 1\\\
1835end\\\
1836\\\
1837local function isSunny()\\\
1838 return (getTimeOfDay() < 10)\\\
1839end\\\
1840\\\
1841local function getRoom( x, y, z, dontCreate )\\\
1842 tMap[x] = tMap[x] or {}\\\
1843 tMap[x][y] = tMap[x][y] or {}\\\
1844 if not tMap[x][y][z] and dontCreate ~= true then\\\
1845 local room = {\\\
1846 items = {},\\\
1847 exits = {},\\\
1848 nMonsters = 0,\\\
1849 }\\\
1850 tMap[x][y][z] = room\\\
1851\\\
1852 if y == 0 then\\\
1853 -- Room is above ground\\\
1854\\\
1855 -- Pick biome\\\
1856 room.nBiome = math.random( 1, #tBiomes )\\\
1857 room.trees = hasTrees( room.nBiome )\\\
1858\\\
1859 -- Add animals\\\
1860 if math.random(1,3) == 1 then\\\
1861 for n = 1,math.random(1,2) do\\\
1862 local sAnimal = tAnimals[ math.random( 1, #tAnimals ) ]\\\
1863 room.items[ sAnimal ] = items[ sAnimal ]\\\
1864 end\\\
1865 end\\\
1866\\\
1867 -- Add surface ore\\\
1868 if math.random(1,5) == 1 or hasStone( room.nBiome ) then\\\
1869 room.items[ \\\"some stone\\\" ] = items[ \\\"some stone\\\" ]\\\
1870 end\\\
1871 if math.random(1,8) == 1 then\\\
1872 room.items[ \\\"some coal\\\" ] = items[ \\\"some coal\\\" ]\\\
1873 end\\\
1874 if math.random(1,8) == 1 and hasRivers( room.nBiome ) then\\\
1875 room.items[ \\\"a river\\\" ] = items[ \\\"a river\\\" ]\\\
1876 end\\\
1877\\\
1878 -- Add exits\\\
1879 room.exits = {\\\
1880 [\\\"north\\\"] = true,\\\
1881 [\\\"south\\\"] = true,\\\
1882 [\\\"east\\\"] = true,\\\
1883 [\\\"west\\\"] = true,\\\
1884 }\\\
1885 if math.random(1,8) == 1 then\\\
1886 room.exits[\\\"down\\\"] = true\\\
1887 room.items[\\\"a cave entrance\\\"] = items[\\\"a cave entrance\\\"]\\\
1888 end\\\
1889\\\
1890 else\\\
1891 -- Room is underground\\\
1892 -- Add exits\\\
1893 local function tryExit( sDir, sOpp, x, y, z )\\\
1894 local adj = getRoom( x, y, z, true )\\\
1895 if adj then\\\
1896 if adj.exits[sOpp] then\\\
1897 room.exits[sDir] = true\\\
1898 end\\\
1899 else\\\
1900 if math.random(1,3) == 1 then\\\
1901 room.exits[sDir] = true\\\
1902 end\\\
1903 end\\\
1904 end\\\
1905\\\
1906 if y == -1 then\\\
1907 local above = getRoom( x, y + 1, z )\\\
1908 if above.exits[\\\"down\\\"] then\\\
1909 room.exits[\\\"up\\\"] = true\\\
1910 room.items[\\\"an exit to the surface\\\"] = items[\\\"an exit to the surface\\\"]\\\
1911 end\\\
1912 else\\\
1913 tryExit( \\\"up\\\", \\\"down\\\", x, y + 1, z )\\\
1914 end\\\
1915\\\
1916 if y > -3 then\\\
1917 tryExit( \\\"down\\\", \\\"up\\\", x, y - 1, z )\\\
1918 end\\\
1919\\\
1920 tryExit( \\\"east\\\", \\\"west\\\", x - 1, y, z )\\\
1921 tryExit( \\\"west\\\", \\\"east\\\", x + 1, y, z )\\\
1922 tryExit( \\\"north\\\", \\\"south\\\", x, y, z + 1 )\\\
1923 tryExit( \\\"south\\\", \\\"north\\\", x, y, z - 1 )\\\
1924\\\
1925 -- Add ores\\\
1926 room.items[ \\\"some stone\\\" ] = items[ \\\"some stone\\\" ]\\\
1927 if math.random(1,3) == 1 then\\\
1928 room.items[ \\\"some coal\\\" ] = items[ \\\"some coal\\\" ]\\\
1929 end\\\
1930 if math.random(1,8) == 1 then\\\
1931 room.items[ \\\"some iron\\\" ] = items[ \\\"some iron\\\" ]\\\
1932 end\\\
1933 if y == -3 and math.random(1,15) == 1 then\\\
1934 room.items[ \\\"some diamond\\\" ] = items[ \\\"some diamond\\\" ]\\\
1935 end\\\
1936\\\
1937 -- Turn out the lights\\\
1938 room.dark = true\\\
1939 end\\\
1940 end\\\
1941 return tMap[x][y][z]\\\
1942end\\\
1943\\\
1944local function itemize( t )\\\
1945 local item = next( t )\\\
1946 if item == nil then\\\
1947 return \\\"nothing\\\"\\\
1948 end\\\
1949\\\
1950 local text = \\\"\\\"\\\
1951 while item do\\\
1952 text = text .. item\\\
1953\\\
1954 local nextItem = next( t, item )\\\
1955 if nextItem ~= nil then\\\
1956 local nextNextItem = next( t, nextItem )\\\
1957 if nextNextItem == nil then\\\
1958 text = text .. \\\" and \\\"\\\
1959 else\\\
1960 text = text .. \\\", \\\"\\\
1961 end\\\
1962 end\\\
1963 item = nextItem\\\
1964 end\\\
1965 return text\\\
1966end\\\
1967\\\
1968local function findItem( _tList, _sQuery )\\\
1969 for sItem, tItem in pairs( _tList ) do\\\
1970 if sItem == _sQuery then\\\
1971 return sItem\\\
1972 end\\\
1973 if tItem.aliases ~= nil then\\\
1974 for n, sAlias in pairs( tItem.aliases ) do\\\
1975 if sAlias == _sQuery then\\\
1976 return sItem\\\
1977 end\\\
1978 end\\\
1979 end\\\
1980 end\\\
1981 return nil\\\
1982end\\\
1983\\\
1984local tMatches = {\\\
1985 [\\\"wait\\\"] = {\\\
1986 \\\"wait\\\",\\\
1987 },\\\
1988 [\\\"look\\\"] = {\\\
1989 \\\"look at the ([%a ]+)\\\",\\\
1990 \\\"look at ([%a ]+)\\\",\\\
1991 \\\"look\\\",\\\
1992 \\\"inspect ([%a ]+)\\\",\\\
1993 \\\"inspect the ([%a ]+)\\\",\\\
1994 \\\"inspect\\\",\\\
1995 },\\\
1996 [\\\"inventory\\\"] = {\\\
1997 \\\"check self\\\",\\\
1998 \\\"check inventory\\\",\\\
1999 \\\"inventory\\\",\\\
2000 \\\"i\\\",\\\
2001 },\\\
2002 [\\\"go\\\"] = {\\\
2003 \\\"go (%a+)\\\",\\\
2004 \\\"travel (%a+)\\\",\\\
2005 \\\"walk (%a+)\\\",\\\
2006 \\\"run (%a+)\\\",\\\
2007 \\\"go\\\",\\\
2008 },\\\
2009 [\\\"dig\\\"] = {\\\
2010 \\\"dig (%a+) using ([%a ]+)\\\",\\\
2011 \\\"dig (%a+) with ([%a ]+)\\\",\\\
2012 \\\"dig (%a+)\\\",\\\
2013 \\\"dig\\\",\\\
2014 },\\\
2015 [\\\"take\\\"] = {\\\
2016 \\\"pick up the ([%a ]+)\\\",\\\
2017 \\\"pick up ([%a ]+)\\\",\\\
2018 \\\"pickup ([%a ]+)\\\",\\\
2019 \\\"take the ([%a ]+)\\\",\\\
2020 \\\"take ([%a ]+)\\\",\\\
2021 \\\"take\\\",\\\
2022 },\\\
2023 [\\\"drop\\\"] = {\\\
2024 \\\"put down the ([%a ]+)\\\",\\\
2025 \\\"put down ([%a ]+)\\\",\\\
2026 \\\"drop the ([%a ]+)\\\",\\\
2027 \\\"drop ([%a ]+)\\\",\\\
2028 \\\"drop\\\",\\\
2029 },\\\
2030 [\\\"place\\\"] = {\\\
2031 \\\"place the ([%a ]+)\\\",\\\
2032 \\\"place ([%a ]+)\\\",\\\
2033 \\\"place\\\",\\\
2034 },\\\
2035 [\\\"cbreak\\\"] = {\\\
2036 \\\"punch the ([%a ]+)\\\",\\\
2037 \\\"punch ([%a ]+)\\\",\\\
2038 \\\"punch\\\",\\\
2039 \\\"break the ([%a ]+) with the ([%a ]+)\\\",\\\
2040 \\\"break ([%a ]+) with ([%a ]+) \\\",\\\
2041 \\\"break the ([%a ]+)\\\",\\\
2042 \\\"break ([%a ]+)\\\",\\\
2043 \\\"break\\\",\\\
2044 },\\\
2045 [\\\"mine\\\"] = {\\\
2046 \\\"mine the ([%a ]+) with the ([%a ]+)\\\",\\\
2047 \\\"mine ([%a ]+) with ([%a ]+)\\\",\\\
2048 \\\"mine ([%a ]+)\\\",\\\
2049 \\\"mine\\\",\\\
2050 },\\\
2051 [\\\"attack\\\"] = {\\\
2052 \\\"attack the ([%a ]+) with the ([%a ]+)\\\",\\\
2053 \\\"attack ([%a ]+) with ([%a ]+)\\\",\\\
2054 \\\"attack ([%a ]+)\\\",\\\
2055 \\\"attack\\\",\\\
2056 \\\"kill the ([%a ]+) with the ([%a ]+)\\\",\\\
2057 \\\"kill ([%a ]+) with ([%a ]+)\\\",\\\
2058 \\\"kill ([%a ]+)\\\",\\\
2059 \\\"kill\\\",\\\
2060 \\\"hit the ([%a ]+) with the ([%a ]+)\\\",\\\
2061 \\\"hit ([%a ]+) with ([%a ]+)\\\",\\\
2062 \\\"hit ([%a ]+)\\\",\\\
2063 \\\"hit\\\",\\\
2064 },\\\
2065 [\\\"craft\\\"] = {\\\
2066 \\\"craft a ([%a ]+)\\\",\\\
2067 \\\"craft some ([%a ]+)\\\",\\\
2068 \\\"craft ([%a ]+)\\\",\\\
2069 \\\"craft\\\",\\\
2070 \\\"make a ([%a ]+)\\\",\\\
2071 \\\"make some ([%a ]+)\\\",\\\
2072 \\\"make ([%a ]+)\\\",\\\
2073 \\\"make\\\",\\\
2074 },\\\
2075 [\\\"build\\\"] = {\\\
2076 \\\"build ([%a ]+) out of ([%a ]+)\\\",\\\
2077 \\\"build ([%a ]+) from ([%a ]+)\\\",\\\
2078 \\\"build ([%a ]+)\\\",\\\
2079 \\\"build\\\",\\\
2080 },\\\
2081 [\\\"eat\\\"] = {\\\
2082 \\\"eat a ([%a ]+)\\\",\\\
2083 \\\"eat the ([%a ]+)\\\",\\\
2084 \\\"eat ([%a ]+)\\\",\\\
2085 \\\"eat\\\",\\\
2086 },\\\
2087 [\\\"help\\\"] = {\\\
2088 \\\"help me\\\",\\\
2089 \\\"help\\\",\\\
2090 },\\\
2091 [\\\"exit\\\"] = {\\\
2092 \\\"exit\\\",\\\
2093 \\\"quit\\\",\\\
2094 \\\"goodbye\\\",\\\
2095 \\\"good bye\\\",\\\
2096 \\\"bye\\\",\\\
2097 \\\"farewell\\\",\\\
2098 },\\\
2099}\\\
2100\\\
2101local commands = {}\\\
2102local function doCommand( text )\\\
2103 if text == \\\"\\\" then\\\
2104 commands[ \\\"noinput\\\" ]()\\\
2105 return\\\
2106 end\\\
2107\\\
2108 for sCommand, t in pairs( tMatches ) do\\\
2109 for n, sMatch in pairs( t ) do\\\
2110 local tCaptures = { string.match( text, \\\"^\\\" .. sMatch .. \\\"$\\\" ) }\\\
2111 if #tCaptures ~= 0 then\\\
2112 local fnCommand = commands[ sCommand ]\\\
2113 if #tCaptures == 1 and tCaptures[1] == sMatch then\\\
2114 fnCommand()\\\
2115 else\\\
2116 fnCommand( table.unpack( tCaptures ) )\\\
2117 end\\\
2118 return\\\
2119 end\\\
2120 end\\\
2121 end\\\
2122 commands[ \\\"badinput\\\" ]()\\\
2123end\\\
2124\\\
2125function commands.wait()\\\
2126 print( \\\"Time passes...\\\" )\\\
2127end\\\
2128\\\
2129function commands.look( _sTarget )\\\
2130 local room = getRoom( x,y,z )\\\
2131 if room.dark then\\\
2132 print( \\\"It is pitch dark.\\\" )\\\
2133 return\\\
2134 end\\\
2135\\\
2136 if _sTarget == nil then\\\
2137 -- Look at the world\\\
2138 if y == 0 then\\\
2139 io.write( \\\"You are standing \\\" .. tBiomes[room.nBiome] .. \\\". \\\" )\\\
2140 print( tDayCycle[ getTimeOfDay() ] )\\\
2141 else\\\
2142 io.write( \\\"You are underground. \\\" )\\\
2143 if next( room.exits ) ~= nil then\\\
2144 print( \\\"You can travel \\\"..itemize( room.exits )..\\\".\\\" )\\\
2145 else\\\
2146 print()\\\
2147 end\\\
2148 end\\\
2149 if next( room.items ) ~= nil then\\\
2150 print( \\\"There is \\\" .. itemize( room.items ) .. \\\" here.\\\" )\\\
2151 end\\\
2152 if room.trees then\\\
2153 print( \\\"There are trees here.\\\" )\\\
2154 end\\\
2155\\\
2156 else\\\
2157 -- Look at stuff\\\
2158 if room.trees and (_sTarget == \\\"tree\\\" or _sTarget == \\\"trees\\\") then\\\
2159 print( \\\"The trees look easy to break.\\\" )\\\
2160 elseif _sTarget == \\\"self\\\" or _sTarget == \\\"myself\\\" then\\\
2161 print( \\\"Very handsome.\\\" )\\\
2162 else\\\
2163 local tItem = nil\\\
2164 local sItem = findItem( room.items, _sTarget )\\\
2165 if sItem then\\\
2166 tItem = room.items[sItem]\\\
2167 else\\\
2168 sItem = findItem( inventory, _sTarget )\\\
2169 if sItem then\\\
2170 tItem = inventory[sItem]\\\
2171 end\\\
2172 end\\\
2173\\\
2174 if tItem then\\\
2175 print( tItem.desc or (\\\"You see nothing special about \\\"..sItem..\\\".\\\") )\\\
2176 else\\\
2177 print( \\\"You don't see any \\\".._sTarget..\\\" here.\\\" )\\\
2178 end\\\
2179 end\\\
2180 end\\\
2181end\\\
2182\\\
2183function commands.go( _sDir )\\\
2184 local room = getRoom( x,y,z )\\\
2185 if _sDir == nil then\\\
2186 print( \\\"Go where?\\\" )\\\
2187 return\\\
2188 end\\\
2189\\\
2190 if nGoWest ~= nil then\\\
2191 if _sDir == \\\"west\\\" then\\\
2192 nGoWest = nGoWest + 1\\\
2193 if nGoWest > #tGoWest then\\\
2194 nGoWest = 1\\\
2195 end\\\
2196 print( tGoWest[ nGoWest ] )\\\
2197 else\\\
2198 if nGoWest > 0 or nTurn > 6 then\\\
2199 nGoWest = nil\\\
2200 end\\\
2201 end\\\
2202 end\\\
2203\\\
2204 if room.exits[_sDir] == nil then\\\
2205 print( \\\"You can't go that way.\\\" )\\\
2206 return\\\
2207 end\\\
2208\\\
2209 if _sDir == \\\"north\\\" then\\\
2210 z = z + 1\\\
2211 elseif _sDir == \\\"south\\\" then\\\
2212 z = z - 1\\\
2213 elseif _sDir == \\\"east\\\" then\\\
2214 x = x - 1\\\
2215 elseif _sDir == \\\"west\\\" then\\\
2216 x = x + 1\\\
2217 elseif _sDir == \\\"up\\\" then\\\
2218 y = y + 1\\\
2219 elseif _sDir == \\\"down\\\" then\\\
2220 y = y - 1\\\
2221 else\\\
2222 print( \\\"I don't understand that direction.\\\" )\\\
2223 return\\\
2224 end\\\
2225\\\
2226 nTimeInRoom = 0\\\
2227 doCommand( \\\"look\\\" )\\\
2228end\\\
2229\\\
2230function commands.dig( _sDir, _sTool )\\\
2231 local room = getRoom( x,y,z )\\\
2232 if _sDir == nil then\\\
2233 print( \\\"Dig where?\\\" )\\\
2234 return\\\
2235 end\\\
2236\\\
2237 local sTool = nil\\\
2238 local tTool = nil\\\
2239 if _sTool ~= nil then\\\
2240 sTool = findItem( inventory, _sTool )\\\
2241 if not sTool then\\\
2242 print( \\\"You're not carrying a \\\".._sTool..\\\".\\\" )\\\
2243 return\\\
2244 end\\\
2245 tTool = inventory[ sTool ]\\\
2246 end\\\
2247\\\
2248 local bActuallyDigging = (room.exits[ _sDir ] ~= true)\\\
2249 if bActuallyDigging then\\\
2250 if sTool == nil or tTool.toolType ~= \\\"pick\\\" then\\\
2251 print( \\\"You need to use a pickaxe to dig through stone.\\\" )\\\
2252 return\\\
2253 end\\\
2254 end\\\
2255\\\
2256 if _sDir == \\\"north\\\" then\\\
2257 room.exits[\\\"north\\\"] = true\\\
2258 z = z + 1\\\
2259 getRoom( x, y, z ).exits[\\\"south\\\"] = true\\\
2260\\\
2261 elseif _sDir == \\\"south\\\" then\\\
2262 room.exits[\\\"south\\\"] = true\\\
2263 z = z - 1\\\
2264 getRoom( x, y, z ).exits[\\\"north\\\"] = true\\\
2265\\\
2266 elseif _sDir == \\\"east\\\" then\\\
2267 room.exits[\\\"east\\\"] = true\\\
2268 x = x - 1\\\
2269 getRoom( x, y, z ).exits[\\\"west\\\"] = true\\\
2270\\\
2271 elseif _sDir == \\\"west\\\" then\\\
2272 room.exits[\\\"west\\\"] = true\\\
2273 x = x + 1\\\
2274 getRoom( x, y, z ).exits[\\\"east\\\"] = true\\\
2275\\\
2276 elseif _sDir == \\\"up\\\" then\\\
2277 if y == 0 then\\\
2278 print( \\\"You can't dig that way.\\\" )\\\
2279 return\\\
2280 end\\\
2281\\\
2282 room.exits[\\\"up\\\"] = true\\\
2283 if y == -1 then\\\
2284 room.items[ \\\"an exit to the surface\\\" ] = items[ \\\"an exit to the surface\\\" ]\\\
2285 end\\\
2286 y = y + 1\\\
2287\\\
2288 room = getRoom( x, y, z )\\\
2289 room.exits[\\\"down\\\"] = true\\\
2290 if y == 0 then\\\
2291 room.items[ \\\"a cave entrance\\\" ] = items[ \\\"a cave entrance\\\" ]\\\
2292 end\\\
2293\\\
2294 elseif _sDir == \\\"down\\\" then\\\
2295 if y <= -3 then\\\
2296 print( \\\"You hit bedrock.\\\" )\\\
2297 return\\\
2298 end\\\
2299\\\
2300 room.exits[\\\"down\\\"] = true\\\
2301 if y == 0 then\\\
2302 room.items[ \\\"a cave entrance\\\" ] = items[ \\\"a cave entrance\\\" ]\\\
2303 end\\\
2304 y = y - 1\\\
2305\\\
2306 room = getRoom( x, y, z )\\\
2307 room.exits[\\\"up\\\"] = true\\\
2308 if y == -1 then\\\
2309 room.items[ \\\"an exit to the surface\\\" ] = items[ \\\"an exit to the surface\\\" ]\\\
2310 end\\\
2311\\\
2312 else\\\
2313 print( \\\"I don't understand that direction.\\\" )\\\
2314 return\\\
2315 end\\\
2316\\\
2317 --\\\
2318 if bActuallyDigging then\\\
2319 if _sDir == \\\"down\\\" and y == -1 or\\\
2320 _sDir == \\\"up\\\" and y == 0 then\\\
2321 inventory[ \\\"some dirt\\\" ] = items[ \\\"some dirt\\\" ]\\\
2322 inventory[ \\\"some stone\\\" ] = items[ \\\"some stone\\\" ]\\\
2323 print( \\\"You dig \\\".._sDir..\\\" using \\\"..sTool..\\\" and collect some dirt and stone.\\\" )\\\
2324 else\\\
2325 inventory[ \\\"some stone\\\" ] = items[ \\\"some stone\\\" ]\\\
2326 print( \\\"You dig \\\".._sDir..\\\" using \\\"..sTool..\\\" and collect some stone.\\\" )\\\
2327 end\\\
2328 end\\\
2329\\\
2330 nTimeInRoom = 0\\\
2331 doCommand( \\\"look\\\" )\\\
2332end\\\
2333\\\
2334function commands.inventory()\\\
2335 print( \\\"You are carrying \\\" .. itemize( inventory ) .. \\\".\\\" )\\\
2336end\\\
2337\\\
2338function commands.drop( _sItem )\\\
2339 if _sItem == nil then\\\
2340 print( \\\"Drop what?\\\" )\\\
2341 return\\\
2342 end\\\
2343\\\
2344 local room = getRoom( x,y,z )\\\
2345 local sItem = findItem( inventory, _sItem )\\\
2346 if sItem then\\\
2347 local tItem = inventory[ sItem ]\\\
2348 if tItem.droppable == false then\\\
2349 print( \\\"You can't drop that.\\\" )\\\
2350 else\\\
2351 room.items[ sItem ] = tItem\\\
2352 inventory[ sItem ] = nil\\\
2353 print( \\\"Dropped.\\\" )\\\
2354 end\\\
2355 else\\\
2356 print( \\\"You don't have a \\\".._sItem..\\\".\\\" )\\\
2357 end\\\
2358end\\\
2359\\\
2360function commands.place( _sItem )\\\
2361 if _sItem == nil then\\\
2362 print( \\\"Place what?\\\" )\\\
2363 return\\\
2364 end\\\
2365\\\
2366 if _sItem == \\\"torch\\\" or _sItem == \\\"a torch\\\" then\\\
2367 local room = getRoom( x,y,z )\\\
2368 if inventory[\\\"some torches\\\"] or inventory[\\\"a torch\\\"] then\\\
2369 inventory[\\\"a torch\\\"] = nil\\\
2370 room.items[\\\"a torch\\\"] = items[\\\"a torch\\\"]\\\
2371 if room.dark then\\\
2372 print( \\\"The cave lights up under the torchflame.\\\" )\\\
2373 room.dark = false\\\
2374 elseif y == 0 and not isSunny() then\\\
2375 print( \\\"The night gets a little brighter.\\\" )\\\
2376 else\\\
2377 print( \\\"Placed.\\\" )\\\
2378 end\\\
2379 else\\\
2380 print( \\\"You don't have torches.\\\" )\\\
2381 end\\\
2382 return\\\
2383 end\\\
2384\\\
2385 commands.drop( _sItem )\\\
2386end\\\
2387\\\
2388function commands.take( _sItem )\\\
2389 if _sItem == nil then\\\
2390 print( \\\"Take what?\\\" )\\\
2391 return\\\
2392 end\\\
2393\\\
2394 local room = getRoom( x,y,z )\\\
2395 local sItem = findItem( room.items, _sItem )\\\
2396 if sItem then\\\
2397 local tItem = room.items[ sItem ]\\\
2398 if tItem.heavy == true then\\\
2399 print( \\\"You can't carry \\\"..sItem..\\\".\\\" )\\\
2400 elseif tItem.ore == true then\\\
2401 print( \\\"You need to mine this ore.\\\" )\\\
2402 else\\\
2403 if tItem.infinite ~= true then\\\
2404 room.items[ sItem ] = nil\\\
2405 end\\\
2406 inventory[ sItem ] = tItem\\\
2407\\\
2408 if inventory[\\\"some torches\\\"] and inventory[\\\"a torch\\\"] then\\\
2409 inventory[\\\"a torch\\\"] = nil\\\
2410 end\\\
2411 if sItem == \\\"a torch\\\" and y < 0 then\\\
2412 room.dark = true\\\
2413 print( \\\"The cave plunges into darkness.\\\" )\\\
2414 else\\\
2415 print( \\\"Taken.\\\" )\\\
2416 end\\\
2417 end\\\
2418 else\\\
2419 print( \\\"You don't see a \\\".._sItem..\\\" here.\\\" )\\\
2420 end\\\
2421end\\\
2422\\\
2423function commands.mine( _sItem, _sTool )\\\
2424 if _sItem == nil then\\\
2425 print( \\\"Mine what?\\\" )\\\
2426 return\\\
2427 end\\\
2428 if _sTool == nil then\\\
2429 print( \\\"Mine \\\".._sItem..\\\" with what?\\\" )\\\
2430 return\\\
2431 end\\\
2432 commands.cbreak( _sItem, _sTool )\\\
2433end\\\
2434\\\
2435function commands.attack( _sItem, _sTool )\\\
2436 if _sItem == nil then\\\
2437 print( \\\"Attack what?\\\" )\\\
2438 return\\\
2439 end\\\
2440 commands.cbreak( _sItem, _sTool )\\\
2441end\\\
2442\\\
2443function commands.cbreak( _sItem, _sTool )\\\
2444 if _sItem == nil then\\\
2445 print( \\\"Break what?\\\" )\\\
2446 return\\\
2447 end\\\
2448\\\
2449 local sTool = nil\\\
2450 if _sTool ~= nil then\\\
2451 sTool = findItem( inventory, _sTool )\\\
2452 if sTool == nil then\\\
2453 print( \\\"You're not carrying a \\\".._sTool..\\\".\\\" )\\\
2454 return\\\
2455 end\\\
2456 end\\\
2457\\\
2458 local room = getRoom( x,y,z )\\\
2459 if _sItem == \\\"tree\\\" or _sItem == \\\"trees\\\" or _sItem == \\\"a tree\\\" then\\\
2460 print( \\\"The tree breaks into blocks of wood, which you pick up.\\\" )\\\
2461 inventory[ \\\"some wood\\\" ] = items[ \\\"some wood\\\" ]\\\
2462 return\\\
2463 elseif _sItem == \\\"self\\\" or _sItem == \\\"myself\\\" then\\\
2464 if term.isColour() then\\\
2465 term.setTextColour( colours.red )\\\
2466 end\\\
2467 print( \\\"You have died.\\\" )\\\
2468 print( \\\"Score: &e0\\\" )\\\
2469 term.setTextColour( colours.white )\\\
2470 bRunning = false\\\
2471 return\\\
2472 end\\\
2473\\\
2474 local sItem = findItem( room.items, _sItem )\\\
2475 if sItem then\\\
2476 local tItem = room.items[ sItem ]\\\
2477 if tItem.ore == true then\\\
2478 -- Breaking ore\\\
2479 if not sTool then\\\
2480 print( \\\"You need a tool to break this ore.\\\" )\\\
2481 return\\\
2482 end\\\
2483 local tTool = inventory[ sTool ]\\\
2484 if tTool.tool then\\\
2485 if tTool.toolLevel < tItem.toolLevel then\\\
2486 print( sTool ..\\\" is not strong enough to break this ore.\\\" )\\\
2487 elseif tTool.toolType ~= tItem.toolType then\\\
2488 print( \\\"You need a different kind of tool to break this ore.\\\" )\\\
2489 else\\\
2490 print( \\\"The ore breaks, dropping \\\"..sItem..\\\", which you pick up.\\\" )\\\
2491 inventory[ sItem ] = items[ sItem ]\\\
2492 if tItem.infinite ~= true then\\\
2493 room.items[ sItem ] = nil\\\
2494 end\\\
2495 end\\\
2496 else\\\
2497 print( \\\"You can't break \\\"..sItem..\\\" with \\\"..sTool..\\\".\\\")\\\
2498 end\\\
2499\\\
2500 elseif tItem.creature == true then\\\
2501 -- Fighting monsters (or pigs)\\\
2502 local toolLevel = 0\\\
2503 local tTool = nil\\\
2504 if sTool then\\\
2505 tTool = inventory[ sTool ]\\\
2506 if tTool.toolType == \\\"sword\\\" then\\\
2507 toolLevel = tTool.toolLevel\\\
2508 end\\\
2509 end\\\
2510\\\
2511 local tChances = { 0.2, 0.4, 0.55, 0.8, 1 }\\\
2512 if math.random() <= tChances[ toolLevel + 1 ] then\\\
2513 room.items[ sItem ] = nil\\\
2514 print( \\\"The \\\"..tItem.aliases[1]..\\\" dies.\\\" )\\\
2515\\\
2516 if tItem.drops then\\\
2517 for n, sDrop in pairs( tItem.drops ) do\\\
2518 if not room.items[sDrop] then\\\
2519 print( \\\"The \\\"..tItem.aliases[1]..\\\" dropped \\\"..sDrop..\\\".\\\" )\\\
2520 room.items[sDrop] = items[sDrop]\\\
2521 end\\\
2522 end\\\
2523 end\\\
2524\\\
2525 if tItem.monster then\\\
2526 room.nMonsters = room.nMonsters - 1\\\
2527 end\\\
2528 else\\\
2529 print( \\\"The \\\"..tItem.aliases[1]..\\\" is injured by your blow.\\\" )\\\
2530 end\\\
2531\\\
2532 if tItem.hitDrops then\\\
2533 for n, sDrop in pairs( tItem.hitDrops ) do\\\
2534 if not room.items[sDrop] then\\\
2535 print( \\\"The \\\"..tItem.aliases[1]..\\\" dropped \\\"..sDrop..\\\".\\\" )\\\
2536 room.items[sDrop] = items[sDrop]\\\
2537 end\\\
2538 end\\\
2539 end\\\
2540\\\
2541 else\\\
2542 print( \\\"You can't break \\\"..sItem..\\\".\\\" )\\\
2543 end\\\
2544 else\\\
2545 print( \\\"You don't see a \\\".._sItem..\\\" here.\\\" )\\\
2546 end\\\
2547end\\\
2548\\\
2549function commands.craft( _sItem )\\\
2550 if _sItem == nil then\\\
2551 print( \\\"Craft what?\\\" )\\\
2552 return\\\
2553 end\\\
2554\\\
2555 if _sItem == \\\"computer\\\" or _sItem == \\\"a computer\\\" then\\\
2556 print( \\\"By creating a computer in a computer in a computer, you tear a hole in the spacetime continuum from which no mortal being can escape.\\\" )\\\
2557 if term.isColour() then\\\
2558 term.setTextColour( colours.red )\\\
2559 end\\\
2560 print( \\\"You have died.\\\" )\\\
2561 print( \\\"Score: &e0\\\" )\\\
2562 term.setTextColour( colours.white )\\\
2563 bRunning = false\\\
2564 return\\\
2565 end\\\
2566\\\
2567 local room = getRoom( x,y,z )\\\
2568 local sItem = findItem( items, _sItem )\\\
2569 local tRecipe = (sItem and tRecipes[ sItem ]) or nil\\\
2570 if tRecipe then\\\
2571 for n,sReq in ipairs( tRecipe ) do\\\
2572 if inventory[sReq] == nil then\\\
2573 print( \\\"You don't have the items you need to craft \\\"..sItem..\\\".\\\" )\\\
2574 return\\\
2575 end\\\
2576 end\\\
2577\\\
2578 for n,sReq in ipairs( tRecipe ) do\\\
2579 inventory[sReq] = nil\\\
2580 end\\\
2581 inventory[ sItem ] = items[ sItem ]\\\
2582 if inventory[\\\"some torches\\\"] and inventory[\\\"a torch\\\"] then\\\
2583 inventory[\\\"a torch\\\"] = nil\\\
2584 end\\\
2585 print( \\\"Crafted.\\\" )\\\
2586 else\\\
2587 print( \\\"You don't know how to make \\\"..(sItem or _sItem)..\\\".\\\" )\\\
2588 end\\\
2589end\\\
2590\\\
2591function commands.build( _sThing, _sMaterial )\\\
2592 if _sThing == nil then\\\
2593 print( \\\"Build what?\\\" )\\\
2594 return\\\
2595 end\\\
2596\\\
2597 local sMaterial = nil\\\
2598 if _sMaterial == nil then\\\
2599 for sItem, tItem in pairs( inventory ) do\\\
2600 if tItem.material then\\\
2601 sMaterial = sItem\\\
2602 break\\\
2603 end\\\
2604 end\\\
2605 if sMaterial == nil then\\\
2606 print( \\\"You don't have any building materials.\\\" )\\\
2607 return\\\
2608 end\\\
2609 else\\\
2610 sMaterial = findItem( inventory, _sMaterial )\\\
2611 if not sMaterial then\\\
2612 print( \\\"You don't have any \\\".._sMaterial )\\\
2613 return\\\
2614 end\\\
2615\\\
2616 if inventory[sMaterial].material ~= true then\\\
2617 print( sMaterial..\\\" is not a good building material.\\\" )\\\
2618 return\\\
2619 end\\\
2620 end\\\
2621\\\
2622 local alias = nil\\\
2623 if string.sub(_sThing, 1, 1) == \\\"a\\\" then\\\
2624 alias = string.match( _sThing, \\\"a ([%a ]+)\\\" )\\\
2625 end\\\
2626\\\
2627 local room = getRoom( x,y,z )\\\
2628 inventory[sMaterial] = nil\\\
2629 room.items[ _sThing ] = {\\\
2630 heavy = true,\\\
2631 aliases = { alias },\\\
2632 desc = \\\"As you look at your creation (made from \\\"..sMaterial..\\\"), you feel a swelling sense of pride.\\\",\\\
2633 }\\\
2634\\\
2635 print( \\\"Your construction is complete.\\\" )\\\
2636end\\\
2637\\\
2638function commands.help()\\\
2639 local sText =\\\
2640 \\\"Welcome to adventure, the greatest text adventure game on CraftOS. \\\" ..\\\
2641 \\\"To get around the world, type actions, and the adventure will \\\" ..\\\
2642 \\\"be read back to you. The actions availiable to you are go, look, inspect, inventory, \\\" ..\\\
2643 \\\"take, drop, place, punch, attack, mine, dig, craft, build, eat and exit.\\\"\\\
2644 print( sText )\\\
2645end\\\
2646\\\
2647function commands.eat( _sItem )\\\
2648 if _sItem == nil then\\\
2649 print( \\\"Eat what?\\\" )\\\
2650 return\\\
2651 end\\\
2652\\\
2653 local sItem = findItem( inventory, _sItem )\\\
2654 if not sItem then\\\
2655 print( \\\"You don't have any \\\".._sItem..\\\".\\\" )\\\
2656 return\\\
2657 end\\\
2658\\\
2659 local tItem = inventory[sItem]\\\
2660 if tItem.food then\\\
2661 print( \\\"That was delicious!\\\" )\\\
2662 inventory[sItem] = nil\\\
2663\\\
2664 if bInjured then\\\
2665 print( \\\"You are no longer injured.\\\" )\\\
2666 bInjured = false\\\
2667 end\\\
2668 else\\\
2669 print( \\\"You can't eat \\\"..sItem..\\\".\\\" )\\\
2670 end\\\
2671end\\\
2672\\\
2673function commands.exit()\\\
2674 bRunning = false\\\
2675end\\\
2676\\\
2677function commands.badinput()\\\
2678 local tResponses = {\\\
2679 \\\"I don't understand.\\\",\\\
2680 \\\"I don't understand you.\\\",\\\
2681 \\\"You can't do that.\\\",\\\
2682 \\\"Nope.\\\",\\\
2683 \\\"Huh?\\\",\\\
2684 \\\"Say again?\\\",\\\
2685 \\\"That's crazy talk.\\\",\\\
2686 \\\"Speak clearly.\\\",\\\
2687 \\\"I'll think about it.\\\",\\\
2688 \\\"Let me get back to you on that one.\\\",\\\
2689 \\\"That doesn't make any sense.\\\",\\\
2690 \\\"What?\\\",\\\
2691 }\\\
2692 print( tResponses[ math.random(1,#tResponses) ] )\\\
2693end\\\
2694\\\
2695function commands.noinput()\\\
2696 local tResponses = {\\\
2697 \\\"Speak up.\\\",\\\
2698 \\\"Enunciate.\\\",\\\
2699 \\\"Project your voice.\\\",\\\
2700 \\\"Don't be shy.\\\",\\\
2701 \\\"Use your words.\\\",\\\
2702 }\\\
2703 print( tResponses[ math.random(1,#tResponses) ] )\\\
2704end\\\
2705\\\
2706local function simulate()\\\
2707 local bNewMonstersThisRoom = false\\\
2708\\\
2709 -- Spawn monsters in nearby rooms\\\
2710 for sx = -2,2 do\\\
2711 for sy = -1,1 do\\\
2712 for sz = -2,2 do\\\
2713 local h = y + sy\\\
2714 if h >= -3 and h <= 0 then\\\
2715 local room = getRoom( x + sx, h, z + sz )\\\
2716\\\
2717 -- Spawn monsters\\\
2718 if room.nMonsters < 2 and\\\
2719 ((h == 0 and not isSunny() and not room.items[\\\"a torch\\\"]) or room.dark) and\\\
2720 math.random(1,6) == 1 then\\\
2721\\\
2722 local sMonster = tMonsters[ math.random(1,#tMonsters) ]\\\
2723 if room.items[ sMonster ] == nil then\\\
2724 room.items[ sMonster ] = items[ sMonster ]\\\
2725 room.nMonsters = room.nMonsters + 1\\\
2726\\\
2727 if sx == 0 and sy == 0 and sz == 0 and not room.dark then\\\
2728 print( \\\"From the shadows, \\\"..sMonster..\\\" appears.\\\" )\\\
2729 bNewMonstersThisRoom = true\\\
2730 end\\\
2731 end\\\
2732 end\\\
2733\\\
2734 -- Burn monsters\\\
2735 if h == 0 and isSunny() then\\\
2736 for n,sMonster in ipairs( tMonsters ) do\\\
2737 if room.items[sMonster] and items[sMonster].nocturnal then\\\
2738 room.items[sMonster] = nil\\\
2739 if sx == 0 and sy == 0 and sz == 0 and not room.dark then\\\
2740 print( \\\"With the sun high in the sky, the \\\"..items[sMonster].aliases[1]..\\\" bursts into flame and dies.\\\" )\\\
2741 end\\\
2742 room.nMonsters = room.nMonsters - 1\\\
2743 end\\\
2744 end\\\
2745 end\\\
2746 end\\\
2747 end\\\
2748 end\\\
2749 end\\\
2750\\\
2751 -- Make monsters attack\\\
2752 local room = getRoom( x, y, z )\\\
2753 if nTimeInRoom >= 2 and not bNewMonstersThisRoom then\\\
2754 for n,sMonster in ipairs( tMonsters ) do\\\
2755 if room.items[sMonster] then\\\
2756 if math.random(1,4) == 1 and\\\
2757 not (y == 0 and isSunny() and (sMonster == \\\"a spider\\\")) then\\\
2758 if sMonster == \\\"a creeper\\\" then\\\
2759 if room.dark then\\\
2760 print( \\\"A creeper explodes.\\\" )\\\
2761 else\\\
2762 print( \\\"The creeper explodes.\\\" )\\\
2763 end\\\
2764 room.items[sMonster] = nil\\\
2765 room.nMonsters = room.nMonsters - 1\\\
2766 else\\\
2767 if room.dark then\\\
2768 print( \\\"A \\\"..items[sMonster].aliases[1]..\\\" attacks you.\\\" )\\\
2769 else\\\
2770 print( \\\"The \\\"..items[sMonster].aliases[1]..\\\" attacks you.\\\" )\\\
2771 end\\\
2772 end\\\
2773\\\
2774 if bInjured then\\\
2775 if term.isColour() then\\\
2776 term.setTextColour( colours.red )\\\
2777 end\\\
2778 print( \\\"You have died.\\\" )\\\
2779 print( \\\"Score: &e0\\\" )\\\
2780 term.setTextColour( colours.white )\\\
2781 bRunning = false\\\
2782 return\\\
2783 else\\\
2784 bInjured = true\\\
2785 end\\\
2786\\\
2787 break\\\
2788 end\\\
2789 end\\\
2790 end\\\
2791 end\\\
2792\\\
2793 -- Always print this\\\
2794 if bInjured then\\\
2795 if term.isColour() then\\\
2796 term.setTextColour( colours.red )\\\
2797 end\\\
2798 print( \\\"You are injured.\\\" )\\\
2799 term.setTextColour( colours.white )\\\
2800 end\\\
2801\\\
2802 -- Advance time\\\
2803 nTurn = nTurn + 1\\\
2804 nTimeInRoom = nTimeInRoom + 1\\\
2805end\\\
2806\\\
2807doCommand( \\\"look\\\" )\\\
2808simulate()\\\
2809\\\
2810local tCommandHistory = {}\\\
2811while bRunning do\\\
2812 if term.isColour() then\\\
2813 term.setTextColour( colours.yellow )\\\
2814 end\\\
2815 write( \\\"? \\\" )\\\
2816 term.setTextColour( colours.white )\\\
2817\\\
2818 local sRawLine = read( nil, tCommandHistory )\\\
2819 table.insert( tCommandHistory, sRawLine )\\\
2820\\\
2821 local sLine = nil\\\
2822 for match in string.gmatch(sRawLine, \\\"%a+\\\") do\\\
2823 if sLine then\\\
2824 sLine = sLine .. \\\" \\\" .. string.lower(match)\\\
2825 else\\\
2826 sLine = string.lower(match)\\\
2827 end\\\
2828 end\\\
2829\\\
2830 doCommand( sLine or \\\"\\\" )\\\
2831 if bRunning then\\\
2832 simulate()\\\
2833 end\\\
2834end\",\
2835 [ \"programs/pocket/equip.lua\" ] = \"local ok, err = pcall( pocket.equipBack )\\\
2836if not ok then\\\
2837 printError( \\\"Nothing to equip\\\" )\\\
2838else\\\
2839 print( \\\"Item equipped\\\" )\\\
2840end\",\
2841 [ \"help/eject.txt\" ] = \"eject ejects the contents of an attached disk drive.\\\
2842\\\
2843ex:\\\
2844\\\"eject left\\\" ejects the contents of the disk drive to the left of the computer.\",\
2845 [ \"programs/copy.lua\" ] = \"\\\
2846local tArgs = { ... }\\\
2847if #tArgs < 2 then\\\
2848 print( \\\"Usage: cp <source> <destination>\\\" )\\\
2849 return\\\
2850end\\\
2851\\\
2852local sSource = shell.resolve( tArgs[1] )\\\
2853local sDest = shell.resolve( tArgs[2] )\\\
2854local tFiles = fs.find( sSource )\\\
2855if #tFiles > 0 then\\\
2856 for n,sFile in ipairs( tFiles ) do\\\
2857 if fs.isDir( sDest ) then\\\
2858 fs.copy( sFile, fs.combine( sDest, fs.getName(sFile) ) )\\\
2859 elseif #tFiles == 1 then\\\
2860 if fs.exists( sDest ) then\\\
2861 printError( \\\"Destination exists\\\" )\\\
2862 else\\\
2863 fs.copy( sFile, sDest )\\\
2864 end\\\
2865 else\\\
2866 printError( \\\"Cannot overwrite file multiple times\\\" )\\\
2867 return\\\
2868 end\\\
2869 end\\\
2870else\\\
2871 printError( \\\"No matching files\\\" )\\\
2872end\",\
2873 [ \"programs/fun/advanced/paint.lua\" ] = \"-- Paint created by nitrogenfingers (edited by dan200)\\\
2874-- http://www.youtube.com/user/NitrogenFingers\\\
2875\\\
2876------------\\\
2877-- Fields --\\\
2878------------\\\
2879\\\
2880-- The width and height of the terminal\\\
2881local w,h = term.getSize()\\\
2882\\\
2883-- The selected colours on the left and right mouse button, and the colour of the canvas\\\
2884local leftColour, rightColour = colours.white, nil\\\
2885local canvasColour = colours.black\\\
2886\\\
2887-- The values stored in the canvas\\\
2888local canvas = {}\\\
2889\\\
2890-- The menu options\\\
2891local mChoices = { \\\"Save\\\",\\\"Exit\\\" }\\\
2892\\\
2893-- The message displayed in the footer bar\\\
2894local fMessage = \\\"Press Ctrl to access menu\\\"\\\
2895\\\
2896-------------------------\\\
2897-- Initialisation --\\\
2898-------------------------\\\
2899\\\
2900-- Determine if we can even run this\\\
2901if not term.isColour() then\\\
2902 print(\\\"Requires an Advanced Computer\\\")\\\
2903 return\\\
2904end\\\
2905\\\
2906-- Determines if the file exists, and can be edited on this computer\\\
2907local tArgs = {...}\\\
2908if #tArgs == 0 then\\\
2909 print(\\\"Usage: paint <path>\\\")\\\
2910 return\\\
2911end\\\
2912local sPath = shell.resolve(tArgs[1])\\\
2913local bReadOnly = fs.isReadOnly(sPath)\\\
2914if fs.exists(sPath) and fs.isDir(sPath) then\\\
2915 print(\\\"Cannot edit a directory.\\\")\\\
2916 return\\\
2917end\\\
2918\\\
2919-- Create .nfp files by default\\\
2920if not fs.exists( sPath ) and not string.find( sPath, \\\"%.\\\" ) then\\\
2921 local sExtension = settings.get(\\\"paint.default_extension\\\", \\\"\\\" )\\\
2922 if sExtension ~= \\\"\\\" and type( sExtension ) == \\\"string\\\" then\\\
2923 sPath = sPath .. \\\".\\\" .. sExtension\\\
2924 end\\\
2925end\\\
2926\\\
2927\\\
2928---------------\\\
2929-- Functions --\\\
2930---------------\\\
2931\\\
2932local function getCanvasPixel( x, y )\\\
2933 if canvas[y] then\\\
2934 return canvas[y][x]\\\
2935 end\\\
2936 return nil\\\
2937end\\\
2938\\\
2939--[[\\\
2940 Converts a colour value to a text character\\\
2941 params: colour = the number to convert to a hex value\\\
2942 returns: a string representing the chosen colour\\\
2943]]\\\
2944local function getCharOf( colour )\\\
2945 -- Incorrect values always convert to nil\\\
2946 if type(colour) == \\\"number\\\" then\\\
2947 local value = math.floor( math.log(colour) / math.log(2) ) + 1\\\
2948 if value >= 1 and value <= 16 then\\\
2949 return string.sub( \\\"0123456789abcdef\\\", value, value )\\\
2950 end\\\
2951 end\\\
2952 return \\\" \\\"\\\
2953end\\\
2954\\\
2955--[[\\\
2956 Converts a text character to colour value\\\
2957 params: char = the char (from string.byte) to convert to number\\\
2958 returns: the colour number of the hex value\\\
2959]]\\\
2960local tColourLookup = {}\\\
2961for n=1,16 do\\\
2962 tColourLookup[ string.byte( \\\"0123456789abcdef\\\",n,n ) ] = 2^(n-1)\\\
2963end\\\
2964local function getColourOf( char )\\\
2965 -- Values not in the hex table are transparent (canvas coloured)\\\
2966 return tColourLookup[char]\\\
2967end\\\
2968\\\
2969--[[\\\
2970 Loads the file into the canvas\\\
2971 params: path = the path of the file to open\\\
2972 returns: nil\\\
2973]]\\\
2974local function load(path)\\\
2975 -- Load the file\\\
2976 if fs.exists(path) then\\\
2977 local file = fs.open(sPath, \\\"r\\\")\\\
2978 local sLine = file.readLine()\\\
2979 while sLine do\\\
2980 local line = {}\\\
2981 for x=1,w-2 do\\\
2982 line[x] = getColourOf( string.byte(sLine,x,x) )\\\
2983 end\\\
2984 table.insert( canvas, line )\\\
2985 sLine = file.readLine()\\\
2986 end\\\
2987 file.close()\\\
2988 end\\\
2989end\\\
2990\\\
2991--[[\\\
2992 Saves the current canvas to file\\\
2993 params: path = the path of the file to save\\\
2994 returns: true if save was successful, false otherwise\\\
2995]]\\\
2996local function save(path)\\\
2997 -- Open file\\\
2998 local sDir = string.sub(sPath, 1, #sPath - #fs.getName(sPath))\\\
2999 if not fs.exists(sDir) then\\\
3000 fs.makeDir(sDir)\\\
3001 end\\\
3002\\\
3003 local file, err = fs.open( path, \\\"w\\\" )\\\
3004 if not file then\\\
3005 return false, err\\\
3006 end\\\
3007\\\
3008 -- Encode (and trim)\\\
3009 local tLines = {}\\\
3010 local nLastLine = 0\\\
3011 for y=1,h-1 do\\\
3012 local sLine = \\\"\\\"\\\
3013 local nLastChar = 0\\\
3014 for x=1,w-2 do\\\
3015 local c = getCharOf( getCanvasPixel( x, y ) )\\\
3016 sLine = sLine .. c\\\
3017 if c ~= \\\" \\\" then\\\
3018 nLastChar = x\\\
3019 end\\\
3020 end\\\
3021 sLine = string.sub( sLine, 1, nLastChar )\\\
3022 tLines[y] = sLine\\\
3023 if string.len( sLine ) > 0 then\\\
3024 nLastLine = y\\\
3025 end\\\
3026 end\\\
3027\\\
3028 -- Save out\\\
3029 for n=1,nLastLine do\\\
3030 file.writeLine( tLines[ n ] )\\\
3031 end\\\
3032 file.close()\\\
3033 return true\\\
3034end\\\
3035\\\
3036--[[\\\
3037 Draws colour picker sidebar, the pallette and the footer\\\
3038 returns: nil\\\
3039]]\\\
3040local function drawInterface()\\\
3041 -- Footer\\\
3042 term.setCursorPos(1, h)\\\
3043 term.setBackgroundColour(colours.black)\\\
3044 term.setTextColour(colours.yellow)\\\
3045 term.clearLine()\\\
3046 term.write(fMessage)\\\
3047\\\
3048 -- Colour Picker\\\
3049 for i=1,16 do\\\
3050 term.setCursorPos(w-1, i)\\\
3051 term.setBackgroundColour( 2^(i-1) )\\\
3052 term.write(\\\" \\\")\\\
3053 end\\\
3054\\\
3055 term.setCursorPos(w-1, 17)\\\
3056 term.setBackgroundColour( canvasColour )\\\
3057 term.setTextColour( colours.grey )\\\
3058 term.write(\\\"\\\\127\\\\127\\\")\\\
3059\\\
3060 -- Left and Right Selected Colours\\\
3061 for i=18,18 do\\\
3062 term.setCursorPos(w-1, i)\\\
3063 if leftColour ~= nil then\\\
3064 term.setBackgroundColour( leftColour )\\\
3065 term.write(\\\" \\\")\\\
3066 else\\\
3067 term.setBackgroundColour( canvasColour )\\\
3068 term.setTextColour( colours.grey )\\\
3069 term.write(\\\"\\\\127\\\")\\\
3070 end\\\
3071 if rightColour ~= nil then\\\
3072 term.setBackgroundColour( rightColour )\\\
3073 term.write(\\\" \\\")\\\
3074 else\\\
3075 term.setBackgroundColour( canvasColour )\\\
3076 term.setTextColour( colours.grey )\\\
3077 term.write(\\\"\\\\127\\\")\\\
3078 end\\\
3079 end\\\
3080\\\
3081 -- Padding\\\
3082 term.setBackgroundColour( canvasColour )\\\
3083 for i=20,h-1 do\\\
3084 term.setCursorPos(w-1, i)\\\
3085 term.write(\\\" \\\")\\\
3086 end\\\
3087end\\\
3088\\\
3089--[[\\\
3090 Converts a single pixel of a single line of the canvas and draws it\\\
3091 returns: nil\\\
3092]]\\\
3093local function drawCanvasPixel( x, y )\\\
3094 local pixel = getCanvasPixel( x, y )\\\
3095 if pixel then\\\
3096 term.setBackgroundColour( pixel or canvasColour )\\\
3097 term.setCursorPos(x, y)\\\
3098 term.write(\\\" \\\")\\\
3099 else\\\
3100 term.setBackgroundColour( canvasColour )\\\
3101 term.setTextColour( colours.grey )\\\
3102 term.setCursorPos(x, y)\\\
3103 term.write(\\\"\\\\127\\\")\\\
3104 end\\\
3105end\\\
3106\\\
3107--[[\\\
3108 Converts each colour in a single line of the canvas and draws it\\\
3109 returns: nil\\\
3110]]\\\
3111local function drawCanvasLine( y )\\\
3112 for x = 1, w-2 do\\\
3113 drawCanvasPixel( x, y )\\\
3114 end\\\
3115end\\\
3116\\\
3117--[[\\\
3118 Converts each colour in the canvas and draws it\\\
3119 returns: nil\\\
3120]]\\\
3121local function drawCanvas()\\\
3122 for y = 1, h-1 do\\\
3123 drawCanvasLine( y )\\\
3124 end\\\
3125end\\\
3126\\\
3127--[[\\\
3128 Draws menu options and handles input from within the menu.\\\
3129 returns: true if the program is to be exited; false otherwise\\\
3130]]\\\
3131local function accessMenu()\\\
3132 -- Selected menu option\\\
3133 local selection = 1\\\
3134\\\
3135 term.setBackgroundColour(colours.black)\\\
3136 while true do\\\
3137 -- Draw the menu\\\
3138 term.setCursorPos(1,h)\\\
3139 term.clearLine()\\\
3140 term.setTextColour(colours.white)\\\
3141 for k,v in pairs(mChoices) do\\\
3142 if selection==k then\\\
3143 term.setTextColour(colours.yellow)\\\
3144 local ox,_ = term.getCursorPos()\\\
3145 term.write(\\\"[\\\"..string.rep(\\\" \\\",#v)..\\\"]\\\")\\\
3146 term.setCursorPos(ox+1,h)\\\
3147 term.setTextColour(colours.white)\\\
3148 term.write(v)\\\
3149 term.setCursorPos(term.getCursorPos()+1,h)\\\
3150 else\\\
3151 term.write(\\\" \\\"..v..\\\" \\\")\\\
3152 end\\\
3153 end\\\
3154\\\
3155 -- Handle input in the menu\\\
3156 local id,key = os.pullEvent(\\\"key\\\")\\\
3157 if id == \\\"key\\\" then\\\
3158 -- S and E are shortcuts\\\
3159 if key == keys.s then\\\
3160 selection = 1\\\
3161 key = keys.enter\\\
3162 elseif key == keys.e then\\\
3163 selection = 2\\\
3164 key = keys.enter\\\
3165 end\\\
3166\\\
3167 if key == keys.right then\\\
3168 -- Move right\\\
3169 selection = selection + 1\\\
3170 if selection > #mChoices then\\\
3171 selection = 1\\\
3172 end\\\
3173\\\
3174 elseif key == keys.left and selection > 1 then\\\
3175 -- Move left\\\
3176 selection = selection - 1\\\
3177 if selection < 1 then\\\
3178 selection = #mChoices\\\
3179 end\\\
3180\\\
3181 elseif key == keys.enter then\\\
3182 -- Select an option\\\
3183 if mChoices[selection]==\\\"Save\\\" then\\\
3184 if bReadOnly then\\\
3185 fMessage = \\\"Access denied\\\"\\\
3186 return false\\\
3187 end\\\
3188 local success, err = save(sPath)\\\
3189 if success then\\\
3190 fMessage = \\\"Saved to \\\"..sPath\\\
3191 else\\\
3192 if err then\\\
3193 fMessage = \\\"Error saving to \\\"..err\\\
3194 else\\\
3195 fMessage = \\\"Error saving to \\\"..sPath\\\
3196 end\\\
3197 end\\\
3198 return false\\\
3199 elseif mChoices[selection]==\\\"Exit\\\" then\\\
3200 return true\\\
3201 end\\\
3202 elseif key == keys.leftCtrl or keys == keys.rightCtrl then\\\
3203 -- Cancel the menu\\\
3204 return false\\\
3205 end\\\
3206 end\\\
3207 end\\\
3208end\\\
3209\\\
3210--[[\\\
3211 Runs the main thread of execution. Draws the canvas and interface, and handles\\\
3212 mouse and key events.\\\
3213 returns: nil\\\
3214]]\\\
3215local function handleEvents()\\\
3216 local programActive = true\\\
3217 while programActive do\\\
3218 local id,p1,p2,p3 = os.pullEvent()\\\
3219 if id==\\\"mouse_click\\\" or id==\\\"mouse_drag\\\" then\\\
3220 if p2 >= w-1 and p3 >= 1 and p3 <= 17 then\\\
3221 if id ~= \\\"mouse_drag\\\" then\\\
3222 -- Selecting an items in the colour picker\\\
3223 if p3 <= 16 then\\\
3224 if p1==1 then\\\
3225 leftColour = 2^(p3-1)\\\
3226 else\\\
3227 rightColour = 2^(p3-1)\\\
3228 end\\\
3229 else\\\
3230 if p1==1 then\\\
3231 leftColour = nil\\\
3232 else\\\
3233 rightColour = nil\\\
3234 end\\\
3235 end\\\
3236 --drawCanvas()\\\
3237 drawInterface()\\\
3238 end\\\
3239 elseif p2 < w-1 and p3 <= h-1 then\\\
3240 -- Clicking on the canvas\\\
3241 local paintColour = nil\\\
3242 if p1==1 then\\\
3243 paintColour = leftColour\\\
3244 elseif p1==2 then\\\
3245 paintColour = rightColour\\\
3246 end\\\
3247 if not canvas[p3] then\\\
3248 canvas[p3] = {}\\\
3249 end\\\
3250 canvas[p3][p2] = paintColour\\\
3251\\\
3252 drawCanvasPixel( p2, p3 )\\\
3253 end\\\
3254 elseif id==\\\"key\\\" then\\\
3255 if p1==keys.leftCtrl or p1==keys.rightCtrl then\\\
3256 programActive = not accessMenu()\\\
3257 drawInterface()\\\
3258 end\\\
3259 elseif id==\\\"term_resize\\\" then\\\
3260 w,h = term.getSize()\\\
3261 drawCanvas()\\\
3262 drawInterface()\\\
3263 end\\\
3264 end\\\
3265end\\\
3266\\\
3267-- Init\\\
3268load(sPath)\\\
3269drawCanvas()\\\
3270drawInterface()\\\
3271\\\
3272-- Main loop\\\
3273handleEvents()\\\
3274\\\
3275-- Shutdown\\\
3276term.setBackgroundColour(colours.black)\\\
3277term.setTextColour(colours.white)\\\
3278term.clear()\\\
3279term.setCursorPos(1,1)\",\
3280 [ \"help/cd.txt\" ] = \"cd changes the directory you're in.\\\
3281\\\
3282ex:\\\
3283\\\"cd rom\\\" will move to \\\"rom\\\" folder.\\\
3284\\\"cd ..\\\" will move up one folder.\\\
3285\\\"cd /\\\" will move to the root.\",\
3286 [ \"programs/fun/advanced/levels/8.dat\" ] = \"4\\\
3287777777 7777\\\
32887287b7 7867\\\
3289788787 7887\\\
329077878777877\\\
3291 7888eb8887\\\
3292 77877787877\\\
3293 7887 787887\\\
3294 7487 7e7807\\\
3295 7777 777777\",\
3296 [ \"apis/paintutils.lua\" ] = \"\\\
3297local function drawPixelInternal( xPos, yPos )\\\
3298 term.setCursorPos( xPos, yPos )\\\
3299 term.write(\\\" \\\")\\\
3300end\\\
3301\\\
3302local tColourLookup = {}\\\
3303for n=1,16 do\\\
3304 tColourLookup[ string.byte( \\\"0123456789abcdef\\\",n,n ) ] = 2^(n-1)\\\
3305end\\\
3306\\\
3307local function parseLine( tImageArg, sLine )\\\
3308 local tLine = {}\\\
3309 for x=1,sLine:len() do\\\
3310 tLine[x] = tColourLookup[ string.byte(sLine,x,x) ] or 0\\\
3311 end\\\
3312 table.insert( tImageArg, tLine )\\\
3313end\\\
3314\\\
3315function parseImage( sRawData )\\\
3316 if type( sRawData ) ~= \\\"string\\\" then\\\
3317 error( \\\"bad argument #1 (expected string, got \\\" .. type( sRawData ) .. \\\")\\\" )\\\
3318 end\\\
3319 local tImage = {}\\\
3320 for sLine in ( sRawData .. \\\"\\\\n\\\" ):gmatch( \\\"(.-)\\\\n\\\" ) do -- read each line like original file handling did\\\
3321 parseLine( tImage, sLine )\\\
3322 end\\\
3323 return tImage\\\
3324end\\\
3325\\\
3326function loadImage( sPath )\\\
3327 if type( sPath ) ~= \\\"string\\\" then\\\
3328 error( \\\"bad argument #1 (expected string, got \\\" .. type( sPath ) .. \\\")\\\", 2 )\\\
3329 end\\\
3330\\\
3331 if fs.exists( sPath ) then\\\
3332 local file = io.open( sPath, \\\"r\\\" )\\\
3333 local sContent = file:read(\\\"*a\\\")\\\
3334 file:close()\\\
3335 return parseImage( sContent ) -- delegate image parse to parseImage\\\
3336 end\\\
3337 return nil\\\
3338end\\\
3339\\\
3340function drawPixel( xPos, yPos, nColour )\\\
3341 if type( xPos ) ~= \\\"number\\\" then error( \\\"bad argument #1 (expected number, got \\\" .. type( xPos ) .. \\\")\\\", 2 ) end\\\
3342 if type( yPos ) ~= \\\"number\\\" then error( \\\"bad argument #2 (expected number, got \\\" .. type( yPos ) .. \\\")\\\", 2 ) end\\\
3343 if nColour ~= nil and type( nColour ) ~= \\\"number\\\" then error( \\\"bad argument #3 (expected number, got \\\" .. type( nColour ) .. \\\")\\\", 2 ) end\\\
3344 if nColour then\\\
3345 term.setBackgroundColor( nColour )\\\
3346 end\\\
3347 drawPixelInternal( xPos, yPos )\\\
3348end\\\
3349\\\
3350function drawLine( startX, startY, endX, endY, nColour )\\\
3351 if type( startX ) ~= \\\"number\\\" then error( \\\"bad argument #1 (expected number, got \\\" .. type( startX ) .. \\\")\\\", 2 ) end\\\
3352 if type( startY ) ~= \\\"number\\\" then error( \\\"bad argument #2 (expected number, got \\\" .. type( startY ) .. \\\")\\\", 2 ) end\\\
3353 if type( endX ) ~= \\\"number\\\" then error( \\\"bad argument #3 (expected number, got \\\" .. type( endX ) .. \\\")\\\", 2 ) end\\\
3354 if type( endY ) ~= \\\"number\\\" then error( \\\"bad argument #4 (expected number, got \\\" .. type( endY ) .. \\\")\\\", 2 ) end\\\
3355 if nColour ~= nil and type( nColour ) ~= \\\"number\\\" then error( \\\"bad argument #5 (expected number, got \\\" .. type( nColour ) .. \\\")\\\", 2 ) end\\\
3356\\\
3357 startX = math.floor(startX)\\\
3358 startY = math.floor(startY)\\\
3359 endX = math.floor(endX)\\\
3360 endY = math.floor(endY)\\\
3361\\\
3362 if nColour then\\\
3363 term.setBackgroundColor( nColour )\\\
3364 end\\\
3365 if startX == endX and startY == endY then\\\
3366 drawPixelInternal( startX, startY )\\\
3367 return\\\
3368 end\\\
3369\\\
3370 local minX = math.min( startX, endX )\\\
3371 local maxX, minY, maxY\\\
3372 if minX == startX then\\\
3373 minY = startY\\\
3374 maxX = endX\\\
3375 maxY = endY\\\
3376 else\\\
3377 minY = endY\\\
3378 maxX = startX\\\
3379 maxY = startY\\\
3380 end\\\
3381\\\
3382 -- TODO: clip to screen rectangle?\\\
3383\\\
3384 local xDiff = maxX - minX\\\
3385 local yDiff = maxY - minY\\\
3386\\\
3387 if xDiff > math.abs(yDiff) then\\\
3388 local y = minY\\\
3389 local dy = yDiff / xDiff\\\
3390 for x=minX,maxX do\\\
3391 drawPixelInternal( x, math.floor( y + 0.5 ) )\\\
3392 y = y + dy\\\
3393 end\\\
3394 else\\\
3395 local x = minX\\\
3396 local dx = xDiff / yDiff\\\
3397 if maxY >= minY then\\\
3398 for y=minY,maxY do\\\
3399 drawPixelInternal( math.floor( x + 0.5 ), y )\\\
3400 x = x + dx\\\
3401 end\\\
3402 else\\\
3403 for y=minY,maxY,-1 do\\\
3404 drawPixelInternal( math.floor( x + 0.5 ), y )\\\
3405 x = x - dx\\\
3406 end\\\
3407 end\\\
3408 end\\\
3409end\\\
3410\\\
3411function drawBox( startX, startY, endX, endY, nColour )\\\
3412 if type( startX ) ~= \\\"number\\\" then error( \\\"bad argument #1 (expected number, got \\\" .. type( startX ) .. \\\")\\\", 2 ) end\\\
3413 if type( startY ) ~= \\\"number\\\" then error( \\\"bad argument #2 (expected number, got \\\" .. type( startY ) .. \\\")\\\", 2 ) end\\\
3414 if type( endX ) ~= \\\"number\\\" then error( \\\"bad argument #3 (expected number, got \\\" .. type( endX ) .. \\\")\\\", 2 ) end\\\
3415 if type( endY ) ~= \\\"number\\\" then error( \\\"bad argument #4 (expected number, got \\\" .. type( endY ) .. \\\")\\\", 2 ) end\\\
3416 if nColour ~= nil and type( nColour ) ~= \\\"number\\\" then error( \\\"bad argument #5 (expected number, got \\\" .. type( nColour ) .. \\\")\\\", 2 ) end\\\
3417\\\
3418 startX = math.floor(startX)\\\
3419 startY = math.floor(startY)\\\
3420 endX = math.floor(endX)\\\
3421 endY = math.floor(endY)\\\
3422\\\
3423 if nColour then\\\
3424 term.setBackgroundColor( nColour )\\\
3425 end\\\
3426 if startX == endX and startY == endY then\\\
3427 drawPixelInternal( startX, startY )\\\
3428 return\\\
3429 end\\\
3430\\\
3431 local minX = math.min( startX, endX )\\\
3432 local maxX, minY, maxY\\\
3433 if minX == startX then\\\
3434 minY = startY\\\
3435 maxX = endX\\\
3436 maxY = endY\\\
3437 else\\\
3438 minY = endY\\\
3439 maxX = startX\\\
3440 maxY = startY\\\
3441 end\\\
3442\\\
3443 for x=minX,maxX do\\\
3444 drawPixelInternal( x, minY )\\\
3445 drawPixelInternal( x, maxY )\\\
3446 end\\\
3447\\\
3448 if (maxY - minY) >= 2 then\\\
3449 for y=(minY+1),(maxY-1) do\\\
3450 drawPixelInternal( minX, y )\\\
3451 drawPixelInternal( maxX, y )\\\
3452 end\\\
3453 end\\\
3454end\\\
3455\\\
3456function drawFilledBox( startX, startY, endX, endY, nColour )\\\
3457 if type( startX ) ~= \\\"number\\\" then error( \\\"bad argument #1 (expected number, got \\\" .. type( startX ) .. \\\")\\\", 2 ) end\\\
3458 if type( startY ) ~= \\\"number\\\" then error( \\\"bad argument #2 (expected number, got \\\" .. type( startY ) .. \\\")\\\", 2 ) end\\\
3459 if type( endX ) ~= \\\"number\\\" then error( \\\"bad argument #3 (expected number, got \\\" .. type( endX ) .. \\\")\\\", 2 ) end\\\
3460 if type( endY ) ~= \\\"number\\\" then error( \\\"bad argument #4 (expected number, got \\\" .. type( endY ) .. \\\")\\\", 2 ) end\\\
3461 if nColour ~= nil and type( nColour ) ~= \\\"number\\\" then error( \\\"bad argument #5 (expected number, got \\\" .. type( nColour ) .. \\\")\\\", 2 ) end\\\
3462\\\
3463 startX = math.floor(startX)\\\
3464 startY = math.floor(startY)\\\
3465 endX = math.floor(endX)\\\
3466 endY = math.floor(endY)\\\
3467\\\
3468 if nColour then\\\
3469 term.setBackgroundColor( nColour )\\\
3470 end\\\
3471 if startX == endX and startY == endY then\\\
3472 drawPixelInternal( startX, startY )\\\
3473 return\\\
3474 end\\\
3475\\\
3476 local minX = math.min( startX, endX )\\\
3477 local maxX, minY, maxY\\\
3478 if minX == startX then\\\
3479 minY = startY\\\
3480 maxX = endX\\\
3481 maxY = endY\\\
3482 else\\\
3483 minY = endY\\\
3484 maxX = startX\\\
3485 maxY = startY\\\
3486 end\\\
3487\\\
3488 for x=minX,maxX do\\\
3489 for y=minY,maxY do\\\
3490 drawPixelInternal( x, y )\\\
3491 end\\\
3492 end\\\
3493end\\\
3494\\\
3495function drawImage( tImage, xPos, yPos )\\\
3496 if type( tImage ) ~= \\\"table\\\" then error( \\\"bad argument #1 (expected table, got \\\" .. type( tImage ) .. \\\")\\\", 2 ) end\\\
3497 if type( xPos ) ~= \\\"number\\\" then error( \\\"bad argument #2 (expected number, got \\\" .. type( xPos ) .. \\\")\\\", 2 ) end\\\
3498 if type( yPos ) ~= \\\"number\\\" then error( \\\"bad argument #3 (expected number, got \\\" .. type( yPos ) .. \\\")\\\", 2 ) end\\\
3499 for y=1,#tImage do\\\
3500 local tLine = tImage[y]\\\
3501 for x=1,#tLine do\\\
3502 if tLine[x] > 0 then\\\
3503 term.setBackgroundColor( tLine[x] )\\\
3504 drawPixelInternal( x + xPos - 1, y + yPos - 1 )\\\
3505 end\\\
3506 end\\\
3507 end\\\
3508end\",\
3509 [ \"help/id.txt\" ] = \"id prints the unique identifier of this computer, or a Disk in an attached Disk Drive.\\\
3510\\\
3511ex:\\\
3512\\\"id\\\" will print this Computers ID and label\\\
3513\\\"id left\\\" will print the ID and label of the disk in the Disk Drive on the left\",\
3514 [ \"programs/http/wget.lua\" ] = \"\\\
3515local function printUsage()\\\
3516 print( \\\"Usage:\\\" )\\\
3517 print( \\\"wget <url> [filename]\\\" )\\\
3518end\\\
3519\\\
3520local tArgs = { ... }\\\
3521if #tArgs < 1 then\\\
3522 printUsage()\\\
3523 return\\\
3524end\\\
3525\\\
3526if not http then\\\
3527 printError( \\\"wget requires http API\\\" )\\\
3528 printError( \\\"Set http_enable to true in ComputerCraft.cfg\\\" )\\\
3529 return\\\
3530end\\\
3531\\\
3532local function getFilename( sUrl )\\\
3533 sUrl = sUrl:gsub( \\\"[#?].*\\\" , \\\"\\\" ):gsub( \\\"/+$\\\" , \\\"\\\" )\\\
3534 return sUrl:match( \\\"/([^/]+)$\\\" )\\\
3535end\\\
3536\\\
3537local function get( sUrl )\\\
3538 write( \\\"Connecting to \\\" .. sUrl .. \\\"... \\\" )\\\
3539\\\
3540 local response = http.get( sUrl , nil , true )\\\
3541 if not response then\\\
3542 print( \\\"Failed.\\\" )\\\
3543 return nil\\\
3544 end\\\
3545\\\
3546 print( \\\"Success.\\\" )\\\
3547\\\
3548 local sResponse = response.readAll()\\\
3549 response.close()\\\
3550 return sResponse\\\
3551end\\\
3552\\\
3553-- Determine file to download\\\
3554local sUrl = tArgs[1]\\\
3555\\\
3556--Check if the URL is valid\\\
3557local ok, err = http.checkURL( sUrl )\\\
3558if not ok then\\\
3559 printError( err or \\\"Invalid URL.\\\" )\\\
3560 return\\\
3561end\\\
3562\\\
3563local sFile = tArgs[2] or getFilename( sUrl )\\\
3564local sPath = shell.resolve( sFile )\\\
3565if fs.exists( sPath ) then\\\
3566 print( \\\"File already exists\\\" )\\\
3567 return\\\
3568end\\\
3569\\\
3570-- Do the get\\\
3571local res = get( sUrl )\\\
3572if res then\\\
3573 local file = fs.open( sPath, \\\"wb\\\" )\\\
3574 file.write( res )\\\
3575 file.close()\\\
3576\\\
3577 print( \\\"Downloaded as \\\"..sFile )\\\
3578end\",\
3579 [ \"programs/command/commands.lua\" ] = \"\\\
3580if not commands then\\\
3581 printError( \\\"Requires a Command Computer.\\\" )\\\
3582 return\\\
3583end\\\
3584\\\
3585local tCommands = commands.list()\\\
3586table.sort( tCommands )\\\
3587\\\
3588if term.isColor() then\\\
3589 term.setTextColor( colors.green )\\\
3590end\\\
3591print( \\\"Available commands:\\\" )\\\
3592term.setTextColor( colors.white )\\\
3593\\\
3594textutils.pagedTabulate( tCommands )\",\
3595 [ \"autorun/emu.lua\" ] = \"-- Setup completion functions\\\
3596local function completeMultipleChoice(text, options, addSpaces)\\\
3597 local tResults = {}\\\
3598 for n = 1, #options do\\\
3599 local sOption = options[n]\\\
3600 if #sOption + (addSpaces and 1 or 0) > #text and sOption:sub(1, #text) == text then\\\
3601 local sResult = sOption:sub(#text + 1)\\\
3602 if addSpaces then\\\
3603 table.insert(tResults, sResult .. \\\" \\\")\\\
3604 else\\\
3605 table.insert(tResults, sResult)\\\
3606 end\\\
3607 end\\\
3608 end\\\
3609 return tResults\\\
3610end\\\
3611\\\
3612local commands = { \\\"close\\\", \\\"open\\\", \\\"data\\\", \\\"config\\\" }\\\
3613shell.setCompletionFunction(\\\"rom/programs/emu.lua\\\", function(shell, index, text, previous)\\\
3614 if index == 1 then\\\
3615 return completeMultipleChoice(text, commands, true)\\\
3616 end\\\
3617end)\",\
3618 [ \"help/string.txt\" ] = \"string is a standard Lua5.1 API.\\\
3619Refer to http://www.lua.org/manual/5.1/ for more information.\",\
3620 [ \"help/turtle.txt\" ] = \"turtle is an api availiable on Turtles, which controls their movement.\\\
3621Functions in the Turtle API:\\\
3622turtle.forward()\\\
3623turtle.back()\\\
3624turtle.up()\\\
3625turtle.down()\\\
3626turtle.turnLeft()\\\
3627turtle.turnRight()\\\
3628turtle.select( slotNum )\\\
3629turtle.getSelectedSlot()\\\
3630turtle.getItemCount( [slotNum] )\\\
3631turtle.getItemSpace( [slotNum] )\\\
3632turtle.getItemDetail( [slotNum] )\\\
3633turtle.equipLeft()\\\
3634turtle.equipRight()\\\
3635turtle.dig( [toolSide] )\\\
3636turtle.digUp( [toolSide] )\\\
3637turtle.digDown( [toolSide] )\\\
3638turtle.place()\\\
3639turtle.placeUp()\\\
3640turtle.placeDown()\\\
3641turtle.attack( [toolSide] )\\\
3642turtle.attackUp( [toolSide] )\\\
3643turtle.attackDown( [toolSide] )\\\
3644turtle.detect()\\\
3645turtle.detectUp()\\\
3646turtle.detectDown()\\\
3647turtle.compare()\\\
3648turtle.compareUp()\\\
3649turtle.compareDown()\\\
3650turtle.inspect()\\\
3651turtle.inspectUp()\\\
3652turtle.inspectDown()\\\
3653turtle.compareTo( slotNum )\\\
3654turtle.transferTo( slotNum, [quantity] )\\\
3655turtle.drop( [quantity] )\\\
3656turtle.dropUp( [quantity] )\\\
3657turtle.dropDown( [quantity] )\\\
3658turtle.suck( [quantity] )\\\
3659turtle.suckUp( [quantity] )\\\
3660turtle.suckDown( [quantity] )\\\
3661turtle.getFuelLevel()\\\
3662turtle.getFuelLimit()\\\
3663turtle.refuel( [quantity] )\\\
3664turtle.craft( [quantity] ) (requires Crafty Turtle)\\\
3665\\\
3666Events fired by the Turtle API:\\\
3667\\\"turtle_inventory\\\" when any of the items in the inventory are changed. Use comparison operations to inspect the changes.\",\
3668 [ \"apis/help.lua\" ] = \"\\\
3669local sPath = \\\"/rom/help\\\"\\\
3670\\\
3671function path()\\\
3672 return sPath\\\
3673end\\\
3674\\\
3675function setPath( _sPath )\\\
3676 if type( _sPath ) ~= \\\"string\\\" then\\\
3677 error( \\\"bad argument #1 (expected string, got \\\" .. type( _sPath ) .. \\\")\\\", 2 )\\\
3678 end\\\
3679 sPath = _sPath\\\
3680end\\\
3681\\\
3682function lookup( _sTopic )\\\
3683 if type( _sTopic ) ~= \\\"string\\\" then\\\
3684 error( \\\"bad argument #1 (expected string, got \\\" .. type( _sTopic ) .. \\\")\\\", 2 )\\\
3685 end\\\
3686 -- Look on the path variable\\\
3687 for sPath in string.gmatch(sPath, \\\"[^:]+\\\") do\\\
3688 sPath = fs.combine( sPath, _sTopic )\\\
3689 if fs.exists( sPath ) and not fs.isDir( sPath ) then\\\
3690 return sPath\\\
3691 elseif fs.exists( sPath..\\\".txt\\\" ) and not fs.isDir( sPath..\\\".txt\\\" ) then\\\
3692 return sPath..\\\".txt\\\"\\\
3693 end\\\
3694 end\\\
3695\\\
3696 -- Not found\\\
3697 return nil\\\
3698end\\\
3699\\\
3700function topics()\\\
3701 -- Add index\\\
3702 local tItems = {\\\
3703 [ \\\"index\\\" ] = true\\\
3704 }\\\
3705\\\
3706 -- Add topics from the path\\\
3707 for sPath in string.gmatch(sPath, \\\"[^:]+\\\") do\\\
3708 if fs.isDir( sPath ) then\\\
3709 local tList = fs.list( sPath )\\\
3710 for n,sFile in pairs( tList ) do\\\
3711 if string.sub( sFile, 1, 1 ) ~= \\\".\\\" then\\\
3712 if not fs.isDir( fs.combine( sPath, sFile ) ) then\\\
3713 if #sFile > 4 and sFile:sub(-4) == \\\".txt\\\" then\\\
3714 sFile = sFile:sub(1,-5)\\\
3715 end\\\
3716 tItems[ sFile ] = true\\\
3717 end\\\
3718 end\\\
3719 end\\\
3720 end\\\
3721 end\\\
3722\\\
3723 -- Sort and return\\\
3724 local tItemList = {}\\\
3725 for sItem, b in pairs( tItems ) do\\\
3726 table.insert( tItemList, sItem )\\\
3727 end\\\
3728 table.sort( tItemList )\\\
3729 return tItemList\\\
3730end\\\
3731\\\
3732function completeTopic( sText )\\\
3733 if type( sText ) ~= \\\"string\\\" then\\\
3734 error( \\\"bad argument #1 (expected string, got \\\" .. type( sText ) .. \\\")\\\", 2 )\\\
3735 end\\\
3736 local tTopics = topics()\\\
3737 local tResults = {}\\\
3738 for n=1,#tTopics do\\\
3739 local sTopic = tTopics[n]\\\
3740 if #sTopic > #sText and string.sub( sTopic, 1, #sText ) == sText then\\\
3741 table.insert( tResults, string.sub( sTopic, #sText + 1 ) )\\\
3742 end\\\
3743 end\\\
3744 return tResults\\\
3745end\",\
3746 [ \"help/settings.txt\" ] = \"Functions in the Settings API:\\\
3747settings.get( name, [default] )\\\
3748settings.set( name, value )\\\
3749settings.unset( name )\\\
3750settings.load( path )\\\
3751settings.save( path )\\\
3752settings.clear()\\\
3753settings.getNames()\\\
3754\\\
3755Default Settings:\\\
3756shell.autocomplete - enables auto-completion in the Shell.\\\
3757lua.autocomplete - enables auto-completion in the Lua program.\\\
3758edit.autocomplete - enables auto-completion in the Edit program.\\\
3759edit.default_extension - sets the default file extension for files created with the Edit program\\\
3760paint.default_extension - sets the default file extension for files created with the Paint program\\\
3761bios.use_multishell - enables Multishell on Advanced Computers, Turtles, Pocket Computers and Command Computers.\\\
3762shell.allow_disk_startup - if a Disk Drive with a Disk inside that has a 'startup' script is attached to a computer, this setting allows to automatically run that script when the computer starts.\\\
3763shell.allow_startup - if there is a 'startup' script in a computer's root, this setting allow to automatically run that script when the computer runs.\\\
3764list.show_hidden - determines, whether the List program will list hidden files or not.\",\
3765 [ \"help/colours.txt\" ] = \"Functions in the colours api\\\
3766(used for redstone.setBundledOutput):\\\
3767colours.combine( colour1, colour2, colour3, ...)\\\
3768colours.subtract( colours, colour1, colour2, ...)\\\
3769colours.test( colours, colour )\\\
3770colours.rgb8( r, g, b )\\\
3771\\\
3772Colour constants in the colours api, in ascending bit order:\\\
3773colours.white, colours.orange, colours.magenta, colours.lightBlue, colours.yellow, colours.lime, colours.pink, colours.grey, colours.lightGrey, colours.cyan, colours.purple, colours.blue, colours.brown, colours.green, colours.red, colours.black.\",\
3774 [ \"help/os.txt\" ] = \"Functions in the os (Operating System) API:\\\
3775os.version()\\\
3776os.getComputerID()\\\
3777os.getComputerLabel()\\\
3778os.setComputerLabel()\\\
3779os.run( environment, programpath, arguments )\\\
3780os.loadAPI( path )\\\
3781os.unloadAPI( name )\\\
3782os.pullEvent( [filter] )\\\
3783os.queueEvent( event, arguments )\\\
3784os.clock()\\\
3785os.startTimer( timeout )\\\
3786os.cancelTimer( token )\\\
3787os.sleep( timeout )\\\
3788os.time( [source] )\\\
3789os.day( [source] )\\\
3790os.epoch( [source] )\\\
3791os.setAlarm( time )\\\
3792os.cancelAlarm( token )\\\
3793os.shutdown()\\\
3794os.reboot()\\\
3795\\\
3796Events emitted by the os API:\\\
3797\\\"timer\\\" when a timeout started by os.startTimer() completes. Argument is the token returned by os.startTimer().\\\
3798\\\"alarm\\\" when a time passed to os.setAlarm() is reached. Argument is the token returned by os.setAlarm().\\\
3799Type \\\"help events\\\" to learn about the event system.\",\
3800 [ \"help/unequip.txt\" ] = \"unequip is a program for Turtles and Pocket Computers. unequip will remove tools of peripherals from the specified side of the turtle. On a Pocket Computer you don't need to write a side.\\\
3801\\\
3802ex:\\\
3803\\\"unequip left\\\" will remove the item on the left side of the turtle\\\
3804\\\"unequip\\\" on a Pocket Computer will remove the item from the Pocket Computer\",\
3805 [ \"modules/main/.ignoreme\" ] = \"--[[\\\
3806Alright then, don't ignore me. This file is to ensure the existence of the \\\"modules/main\\\" folder.\\\
3807You can use this folder to add modules who can be loaded with require() to your Resourcepack.\\\
3808]]\",\
3809 [ \"apis/command/commands.lua\" ] = \"\\\
3810if not commands then\\\
3811 error( \\\"Cannot load command API on normal computer\\\", 2 )\\\
3812end\\\
3813native = commands.native or commands\\\
3814\\\
3815local function collapseArgs( errorDepth, bJSONIsNBT, arg1, ... )\\\
3816 if arg1 ~= nil then\\\
3817 if type(arg1) == \\\"boolean\\\" or type(arg1) == \\\"number\\\" or type(arg1) == \\\"string\\\" then\\\
3818 return tostring(arg1) .. \\\" \\\" .. collapseArgs( errorDepth + 1, bJSONIsNBT, ... )\\\
3819 elseif type(arg1) == \\\"table\\\" then\\\
3820 return textutils.serialiseJSON( arg1, bJSONIsNBT ) .. \\\" \\\" .. collapseArgs( errorDepth + 1, bJSONIsNBT, ... )\\\
3821 else\\\
3822 error( \\\"Expected string, number, boolean or table\\\", errorDepth )\\\
3823 end\\\
3824 end\\\
3825 return \\\"\\\"\\\
3826end\\\
3827\\\
3828-- Put native functions into the environment\\\
3829local env = _ENV\\\
3830for k,v in pairs( native ) do\\\
3831 env[k] = v\\\
3832end\\\
3833\\\
3834-- Create wrapper functions for all the commands\\\
3835local tAsync = {}\\\
3836local tNonNBTJSONCommands = {\\\
3837 [ \\\"tellraw\\\" ] = true,\\\
3838 [ \\\"title\\\" ] = true\\\
3839}\\\
3840local tCommands = native.list()\\\
3841for n,sCommandName in ipairs(tCommands) do\\\
3842 if env[ sCommandName ] == nil then\\\
3843 local bJSONIsNBT = (tNonNBTJSONCommands[ sCommandName ] == nil)\\\
3844 env[ sCommandName ] = function( ... )\\\
3845 local sCommand = sCommandName .. \\\" \\\" .. collapseArgs( 3, bJSONIsNBT, ... )\\\
3846 return native.exec( sCommand )\\\
3847 end\\\
3848 tAsync[ sCommandName ] = function( ... )\\\
3849 local sCommand = sCommandName .. \\\" \\\" .. collapseArgs( 3, bJSONIsNBT, ... )\\\
3850 return native.execAsync( sCommand )\\\
3851 end\\\
3852 end\\\
3853end\\\
3854env.async = tAsync\",\
3855 [ \"help/reboot.txt\" ] = \"reboot will turn the computer off and on again.\\\
3856You can also hold Ctrl+R at any time to quickly reboot.\",\
3857 [ \"apis/textutils.lua\" ] = \"\\\
3858function slowWrite( sText, nRate )\\\
3859 if nRate ~= nil and type( nRate ) ~= \\\"number\\\" then\\\
3860 error( \\\"bad argument #2 (expected number, got \\\" .. type( nRate ) .. \\\")\\\", 2 )\\\
3861 end\\\
3862 nRate = nRate or 20\\\
3863 if nRate < 0 then\\\
3864 error( \\\"Rate must be positive\\\", 2 )\\\
3865 end\\\
3866 local nSleep = 1 / nRate\\\
3867\\\
3868 sText = tostring( sText )\\\
3869 local x,y = term.getCursorPos()\\\
3870 local len = string.len( sText )\\\
3871\\\
3872 for n=1,len do\\\
3873 term.setCursorPos( x, y )\\\
3874 sleep( nSleep )\\\
3875 local nLines = write( string.sub( sText, 1, n ) )\\\
3876 local newX, newY = term.getCursorPos()\\\
3877 y = newY - nLines\\\
3878 end\\\
3879end\\\
3880\\\
3881function slowPrint( sText, nRate )\\\
3882 slowWrite( sText, nRate )\\\
3883 print()\\\
3884end\\\
3885\\\
3886function formatTime( nTime, bTwentyFourHour )\\\
3887 if type( nTime ) ~= \\\"number\\\" then\\\
3888 error( \\\"bad argument #1 (expected number, got \\\" .. type( nTime ) .. \\\")\\\", 2 )\\\
3889 end\\\
3890 if bTwentyFourHour ~= nil and type( bTwentyFourHour ) ~= \\\"boolean\\\" then\\\
3891 error( \\\"bad argument #2 (expected boolean, got \\\" .. type( bTwentyFourHour ) .. \\\")\\\", 2 )\\\
3892 end\\\
3893 local sTOD = nil\\\
3894 if not bTwentyFourHour then\\\
3895 if nTime >= 12 then\\\
3896 sTOD = \\\"PM\\\"\\\
3897 else\\\
3898 sTOD = \\\"AM\\\"\\\
3899 end\\\
3900 if nTime >= 13 then\\\
3901 nTime = nTime - 12\\\
3902 end\\\
3903 end\\\
3904\\\
3905 local nHour = math.floor(nTime)\\\
3906 local nMinute = math.floor((nTime - nHour)*60)\\\
3907 if sTOD then\\\
3908 return string.format( \\\"%d:%02d %s\\\", nHour, nMinute, sTOD )\\\
3909 else\\\
3910 return string.format( \\\"%d:%02d\\\", nHour, nMinute )\\\
3911 end\\\
3912end\\\
3913\\\
3914local function makePagedScroll( _term, _nFreeLines )\\\
3915 local nativeScroll = _term.scroll\\\
3916 local nFreeLines = _nFreeLines or 0\\\
3917 return function( _n )\\\
3918 for n=1,_n do\\\
3919 nativeScroll( 1 )\\\
3920\\\
3921 if nFreeLines <= 0 then\\\
3922 local w,h = _term.getSize()\\\
3923 _term.setCursorPos( 1, h )\\\
3924 _term.write( \\\"Press any key to continue\\\" )\\\
3925 os.pullEvent( \\\"key\\\" )\\\
3926 _term.clearLine()\\\
3927 _term.setCursorPos( 1, h )\\\
3928 else\\\
3929 nFreeLines = nFreeLines - 1\\\
3930 end\\\
3931 end\\\
3932 end\\\
3933end\\\
3934\\\
3935function pagedPrint( _sText, _nFreeLines )\\\
3936 if _nFreeLines ~= nil and type( _nFreeLines ) ~= \\\"number\\\" then\\\
3937 error( \\\"bad argument #2 (expected number, got \\\" .. type( _nFreeLines ) .. \\\")\\\", 2 )\\\
3938 end\\\
3939 -- Setup a redirector\\\
3940 local oldTerm = term.current()\\\
3941 local newTerm = {}\\\
3942 for k,v in pairs( oldTerm ) do\\\
3943 newTerm[k] = v\\\
3944 end\\\
3945 newTerm.scroll = makePagedScroll( oldTerm, _nFreeLines )\\\
3946 term.redirect( newTerm )\\\
3947\\\
3948 -- Print the text\\\
3949 local result\\\
3950 local ok, err = pcall( function()\\\
3951 if _sText ~= nil then\\\
3952 result = print( _sText )\\\
3953 else\\\
3954 result = print()\\\
3955 end\\\
3956 end )\\\
3957\\\
3958 -- Removed the redirector\\\
3959 term.redirect( oldTerm )\\\
3960\\\
3961 -- Propogate errors\\\
3962 if not ok then\\\
3963 error( err, 0 )\\\
3964 end\\\
3965 return result\\\
3966end\\\
3967\\\
3968local function tabulateCommon( bPaged, ... )\\\
3969 local tAll = { ... }\\\
3970 for k,v in ipairs( tAll ) do\\\
3971 if type( v ) ~= \\\"number\\\" and type( v ) ~= \\\"table\\\" then\\\
3972 error( \\\"bad argument #\\\"..k..\\\" (expected number or table, got \\\" .. type( v ) .. \\\")\\\", 3 )\\\
3973 end\\\
3974 end\\\
3975\\\
3976 local w,h = term.getSize()\\\
3977 local nMaxLen = w / 8\\\
3978 for n, t in ipairs( tAll ) do\\\
3979 if type(t) == \\\"table\\\" then\\\
3980 for nu, sItem in pairs(t) do\\\
3981 if type( sItem ) ~= \\\"string\\\" then\\\
3982 error( \\\"bad argument #\\\"..n..\\\".\\\"..nu..\\\" (expected string, got \\\" .. type( sItem ) .. \\\")\\\", 3 )\\\
3983 end\\\
3984 nMaxLen = math.max( string.len( sItem ) + 1, nMaxLen )\\\
3985 end\\\
3986 end\\\
3987 end\\\
3988 local nCols = math.floor( w / nMaxLen )\\\
3989 local nLines = 0\\\
3990 local function newLine()\\\
3991 if bPaged and nLines >= (h-3) then\\\
3992 pagedPrint()\\\
3993 else\\\
3994 print()\\\
3995 end\\\
3996 nLines = nLines + 1\\\
3997 end\\\
3998\\\
3999 local function drawCols( _t )\\\
4000 local nCol = 1\\\
4001 for n, s in ipairs( _t ) do\\\
4002 if nCol > nCols then\\\
4003 nCol = 1\\\
4004 newLine()\\\
4005 end\\\
4006\\\
4007 local cx, cy = term.getCursorPos()\\\
4008 cx = 1 + ((nCol - 1) * nMaxLen)\\\
4009 term.setCursorPos( cx, cy )\\\
4010 term.write( s )\\\
4011\\\
4012 nCol = nCol + 1\\\
4013 end\\\
4014 print()\\\
4015 end\\\
4016 for n, t in ipairs( tAll ) do\\\
4017 if type(t) == \\\"table\\\" then\\\
4018 if #t > 0 then\\\
4019 drawCols( t )\\\
4020 end\\\
4021 elseif type(t) == \\\"number\\\" then\\\
4022 term.setTextColor( t )\\\
4023 end\\\
4024 end\\\
4025end\\\
4026\\\
4027function tabulate( ... )\\\
4028 tabulateCommon( false, ... )\\\
4029end\\\
4030\\\
4031function pagedTabulate( ... )\\\
4032 tabulateCommon( true, ... )\\\
4033end\\\
4034\\\
4035local g_tLuaKeywords = {\\\
4036 [ \\\"and\\\" ] = true,\\\
4037 [ \\\"break\\\" ] = true,\\\
4038 [ \\\"do\\\" ] = true,\\\
4039 [ \\\"else\\\" ] = true,\\\
4040 [ \\\"elseif\\\" ] = true,\\\
4041 [ \\\"end\\\" ] = true,\\\
4042 [ \\\"false\\\" ] = true,\\\
4043 [ \\\"for\\\" ] = true,\\\
4044 [ \\\"function\\\" ] = true,\\\
4045 [ \\\"if\\\" ] = true,\\\
4046 [ \\\"in\\\" ] = true,\\\
4047 [ \\\"local\\\" ] = true,\\\
4048 [ \\\"nil\\\" ] = true,\\\
4049 [ \\\"not\\\" ] = true,\\\
4050 [ \\\"or\\\" ] = true,\\\
4051 [ \\\"repeat\\\" ] = true,\\\
4052 [ \\\"return\\\" ] = true,\\\
4053 [ \\\"then\\\" ] = true,\\\
4054 [ \\\"true\\\" ] = true,\\\
4055 [ \\\"until\\\" ] = true,\\\
4056 [ \\\"while\\\" ] = true,\\\
4057}\\\
4058\\\
4059local function serializeImpl( t, tTracking, sIndent )\\\
4060 local sType = type(t)\\\
4061 if sType == \\\"table\\\" then\\\
4062 if tTracking[t] ~= nil then\\\
4063 error( \\\"Cannot serialize table with recursive entries\\\", 0 )\\\
4064 end\\\
4065 tTracking[t] = true\\\
4066\\\
4067 if next(t) == nil then\\\
4068 -- Empty tables are simple\\\
4069 return \\\"{}\\\"\\\
4070 else\\\
4071 -- Other tables take more work\\\
4072 local sResult = \\\"{\\\\n\\\"\\\
4073 local sSubIndent = sIndent .. \\\" \\\"\\\
4074 local tSeen = {}\\\
4075 for k,v in ipairs(t) do\\\
4076 tSeen[k] = true\\\
4077 sResult = sResult .. sSubIndent .. serializeImpl( v, tTracking, sSubIndent ) .. \\\",\\\\n\\\"\\\
4078 end\\\
4079 for k,v in pairs(t) do\\\
4080 if not tSeen[k] then\\\
4081 local sEntry\\\
4082 if type(k) == \\\"string\\\" and not g_tLuaKeywords[k] and string.match( k, \\\"^[%a_][%a%d_]*$\\\" ) then\\\
4083 sEntry = k .. \\\" = \\\" .. serializeImpl( v, tTracking, sSubIndent ) .. \\\",\\\\n\\\"\\\
4084 else\\\
4085 sEntry = \\\"[ \\\" .. serializeImpl( k, tTracking, sSubIndent ) .. \\\" ] = \\\" .. serializeImpl( v, tTracking, sSubIndent ) .. \\\",\\\\n\\\"\\\
4086 end\\\
4087 sResult = sResult .. sSubIndent .. sEntry\\\
4088 end\\\
4089 end\\\
4090 sResult = sResult .. sIndent .. \\\"}\\\"\\\
4091 return sResult\\\
4092 end\\\
4093\\\
4094 elseif sType == \\\"string\\\" then\\\
4095 return string.format( \\\"%q\\\", t )\\\
4096\\\
4097 elseif sType == \\\"number\\\" or sType == \\\"boolean\\\" or sType == \\\"nil\\\" then\\\
4098 return tostring(t)\\\
4099\\\
4100 else\\\
4101 error( \\\"Cannot serialize type \\\"..sType, 0 )\\\
4102\\\
4103 end\\\
4104end\\\
4105\\\
4106empty_json_array = {}\\\
4107\\\
4108local function serializeJSONImpl( t, tTracking, bNBTStyle )\\\
4109 local sType = type(t)\\\
4110 if t == empty_json_array then\\\
4111 return \\\"[]\\\"\\\
4112\\\
4113 elseif sType == \\\"table\\\" then\\\
4114 if tTracking[t] ~= nil then\\\
4115 error( \\\"Cannot serialize table with recursive entries\\\", 0 )\\\
4116 end\\\
4117 tTracking[t] = true\\\
4118\\\
4119 if next(t) == nil then\\\
4120 -- Empty tables are simple\\\
4121 return \\\"{}\\\"\\\
4122 else\\\
4123 -- Other tables take more work\\\
4124 local sObjectResult = \\\"{\\\"\\\
4125 local sArrayResult = \\\"[\\\"\\\
4126 local nObjectSize = 0\\\
4127 local nArraySize = 0\\\
4128 for k,v in pairs(t) do\\\
4129 if type(k) == \\\"string\\\" then\\\
4130 local sEntry\\\
4131 if bNBTStyle then\\\
4132 sEntry = tostring(k) .. \\\":\\\" .. serializeJSONImpl( v, tTracking, bNBTStyle )\\\
4133 else\\\
4134 sEntry = string.format( \\\"%q\\\", k ) .. \\\":\\\" .. serializeJSONImpl( v, tTracking, bNBTStyle )\\\
4135 end\\\
4136 if nObjectSize == 0 then\\\
4137 sObjectResult = sObjectResult .. sEntry\\\
4138 else\\\
4139 sObjectResult = sObjectResult .. \\\",\\\" .. sEntry\\\
4140 end\\\
4141 nObjectSize = nObjectSize + 1\\\
4142 end\\\
4143 end\\\
4144 for n,v in ipairs(t) do\\\
4145 local sEntry = serializeJSONImpl( v, tTracking, bNBTStyle )\\\
4146 if nArraySize == 0 then\\\
4147 sArrayResult = sArrayResult .. sEntry\\\
4148 else\\\
4149 sArrayResult = sArrayResult .. \\\",\\\" .. sEntry\\\
4150 end\\\
4151 nArraySize = nArraySize + 1\\\
4152 end\\\
4153 sObjectResult = sObjectResult .. \\\"}\\\"\\\
4154 sArrayResult = sArrayResult .. \\\"]\\\"\\\
4155 if nObjectSize > 0 or nArraySize == 0 then\\\
4156 return sObjectResult\\\
4157 else\\\
4158 return sArrayResult\\\
4159 end\\\
4160 end\\\
4161\\\
4162 elseif sType == \\\"string\\\" then\\\
4163 return string.format( \\\"%q\\\", t )\\\
4164\\\
4165 elseif sType == \\\"number\\\" or sType == \\\"boolean\\\" then\\\
4166 return tostring(t)\\\
4167\\\
4168 else\\\
4169 error( \\\"Cannot serialize type \\\"..sType, 0 )\\\
4170\\\
4171 end\\\
4172end\\\
4173\\\
4174function serialize( t )\\\
4175 local tTracking = {}\\\
4176 return serializeImpl( t, tTracking, \\\"\\\" )\\\
4177end\\\
4178\\\
4179function unserialize( s )\\\
4180 if type( s ) ~= \\\"string\\\" then\\\
4181 error( \\\"bad argument #1 (expected string, got \\\" .. type( s ) .. \\\")\\\", 2 )\\\
4182 end\\\
4183 local func = load( \\\"return \\\"..s, \\\"unserialize\\\", \\\"t\\\", {} )\\\
4184 if func then\\\
4185 local ok, result = pcall( func )\\\
4186 if ok then\\\
4187 return result\\\
4188 end\\\
4189 end\\\
4190 return nil\\\
4191end\\\
4192\\\
4193function serializeJSON( t, bNBTStyle )\\\
4194 if type( t ) ~= \\\"table\\\" and type( t ) ~= \\\"string\\\" and type( t ) ~= \\\"number\\\" and type( t ) ~= \\\"boolean\\\" then\\\
4195 error( \\\"bad argument #1 (expected table/string/number/boolean, got \\\" .. type( t ) .. \\\")\\\", 2 )\\\
4196 end\\\
4197 if bNBTStyle ~= nil and type( bNBTStyle ) ~= \\\"boolean\\\" then\\\
4198 error( \\\"bad argument #2 (expected boolean, got \\\" .. type( bNBTStyle ) .. \\\")\\\", 2 )\\\
4199 end\\\
4200 local tTracking = {}\\\
4201 return serializeJSONImpl( t, tTracking, bNBTStyle or false )\\\
4202end\\\
4203\\\
4204function urlEncode( str )\\\
4205 if type( str ) ~= \\\"string\\\" then\\\
4206 error( \\\"bad argument #1 (expected string, got \\\" .. type( str ) .. \\\")\\\", 2 )\\\
4207 end\\\
4208 if str then\\\
4209 str = string.gsub(str, \\\"\\\\n\\\", \\\"\\\\r\\\\n\\\")\\\
4210 str = string.gsub(str, \\\"([^A-Za-z0-9 %-%_%.])\\\", function(c)\\\
4211 local n = string.byte(c)\\\
4212 if n < 128 then\\\
4213 -- ASCII\\\
4214 return string.format(\\\"%%%02X\\\", n)\\\
4215 else\\\
4216 -- Non-ASCII (encode as UTF-8)\\\
4217 return\\\
4218 string.format(\\\"%%%02X\\\", 192 + bit32.band( bit32.arshift(n,6), 31 ) ) ..\\\
4219 string.format(\\\"%%%02X\\\", 128 + bit32.band( n, 63 ) )\\\
4220 end\\\
4221 end )\\\
4222 str = string.gsub(str, \\\" \\\", \\\"+\\\")\\\
4223 end\\\
4224 return str\\\
4225end\\\
4226\\\
4227local tEmpty = {}\\\
4228function complete( sSearchText, tSearchTable )\\\
4229 if type( sSearchText ) ~= \\\"string\\\" then\\\
4230 error( \\\"bad argument #1 (expected string, got \\\" .. type( sSearchText ) .. \\\")\\\", 2 )\\\
4231 end\\\
4232 if tSearchTable ~= nil and type( tSearchTable ) ~= \\\"table\\\" then\\\
4233 error( \\\"bad argument #2 (expected table, got \\\" .. type( tSearchTable ) .. \\\")\\\", 2 )\\\
4234 end\\\
4235\\\
4236 if g_tLuaKeywords[sSearchText] then return tEmpty end\\\
4237 local nStart = 1\\\
4238 local nDot = string.find( sSearchText, \\\".\\\", nStart, true )\\\
4239 local tTable = tSearchTable or _ENV\\\
4240 while nDot do\\\
4241 local sPart = string.sub( sSearchText, nStart, nDot - 1 )\\\
4242 local value = tTable[ sPart ]\\\
4243 if type( value ) == \\\"table\\\" then\\\
4244 tTable = value\\\
4245 nStart = nDot + 1\\\
4246 nDot = string.find( sSearchText, \\\".\\\", nStart, true )\\\
4247 else\\\
4248 return tEmpty\\\
4249 end\\\
4250 end\\\
4251 local nColon = string.find( sSearchText, \\\":\\\", nStart, true )\\\
4252 if nColon then\\\
4253 local sPart = string.sub( sSearchText, nStart, nColon - 1 )\\\
4254 local value = tTable[ sPart ]\\\
4255 if type( value ) == \\\"table\\\" then\\\
4256 tTable = value\\\
4257 nStart = nColon + 1\\\
4258 else\\\
4259 return tEmpty\\\
4260 end\\\
4261 end\\\
4262\\\
4263 local sPart = string.sub( sSearchText, nStart )\\\
4264 local nPartLength = string.len( sPart )\\\
4265\\\
4266 local tResults = {}\\\
4267 local tSeen = {}\\\
4268 while tTable do\\\
4269 for k,v in pairs( tTable ) do\\\
4270 if not tSeen[k] and type(k) == \\\"string\\\" then\\\
4271 if string.find( k, sPart, 1, true ) == 1 then\\\
4272 if not g_tLuaKeywords[k] and string.match( k, \\\"^[%a_][%a%d_]*$\\\" ) then\\\
4273 local sResult = string.sub( k, nPartLength + 1 )\\\
4274 if nColon then\\\
4275 if type(v) == \\\"function\\\" then\\\
4276 table.insert( tResults, sResult .. \\\"(\\\" )\\\
4277 elseif type(v) == \\\"table\\\" then\\\
4278 local tMetatable = getmetatable( v )\\\
4279 if tMetatable and ( type( tMetatable.__call ) == \\\"function\\\" or type( tMetatable.__call ) == \\\"table\\\" ) then\\\
4280 table.insert( tResults, sResult .. \\\"(\\\" )\\\
4281 end\\\
4282 end\\\
4283 else\\\
4284 if type(v) == \\\"function\\\" then\\\
4285 sResult = sResult .. \\\"(\\\"\\\
4286 elseif type(v) == \\\"table\\\" and next(v) ~= nil then\\\
4287 sResult = sResult .. \\\".\\\"\\\
4288 end\\\
4289 table.insert( tResults, sResult )\\\
4290 end\\\
4291 end\\\
4292 end\\\
4293 end\\\
4294 tSeen[k] = true\\\
4295 end\\\
4296 local tMetatable = getmetatable( tTable )\\\
4297 if tMetatable and type( tMetatable.__index ) == \\\"table\\\" then\\\
4298 tTable = tMetatable.__index\\\
4299 else\\\
4300 tTable = nil\\\
4301 end\\\
4302 end\\\
4303\\\
4304 table.sort( tResults )\\\
4305 return tResults\\\
4306end\\\
4307\\\
4308-- GB versions\\\
4309serialise = serialize\\\
4310unserialise = unserialize\\\
4311serialiseJSON = serializeJSON\",\
4312 [ \"help/bundled.txt\" ] = \"To set bundled outputs:\\\
4313c = colors.combine( colors.red, colors.blue )\\\
4314rs.setBundledOutput( \\\"left\\\", c )\\\
4315\\\
4316c = colors.combine( c, colors.green )\\\
4317rs.setBundledOutput( \\\"left\\\", c )\\\
4318\\\
4319c = colors.subtract( c, colors.blue )\\\
4320rs.setBundledOutput( \\\"left\\\", c )\\\
4321\\\
4322To get bundled inputs:\\\
4323c = rs.getBundledInput( \\\"right\\\" )\\\
4324red = colors.test( c, colors.red )\\\
4325\\\
4326Type \\\"help colors\\\" for the list of wire colors.\",\
4327 [ \"help/go.txt\" ] = \"go is a program for Turtles, used to control the turtle without programming. It accepts one or more commands as a direction followed by a distance.\\\
4328\\\
4329ex:\\\
4330\\\"go forward\\\" moves the turtle 1 space forward.\\\
4331\\\"go forward 3\\\" moves the turtle 3 spaces forward.\\\
4332\\\"go forward 3 up left 2\\\" moves the turtle 3 spaces forward, 1 spaces up, then left 180 degrees.\",\
4333 [ \"help/monitor.txt\" ] = \"monitor will connect to an attached Monitor peripheral, and run a program on its display.\\\
4334Type \\\"help monitors\\\" for help using monitors as peripherals in lua programs.\\\
4335\\\
4336ex:\\\
4337\\\"monitor left hello\\\" will run the \\\"hello\\\" program on the monitor to the left of the computer.\\\
4338\\\"monitor top edit foo\\\" will run the edit program on the top monitor, editing the file \\\"foo\\\".\",\
4339 [ \"help/list.txt\" ] = \"ls will list all the directories and files in the current location. Use \\\"type\\\" to find out if an item is a file or a directory.\",\
4340 [ \"help/falling.txt\" ] = \"\\\"From Russia with Fun\\\" comes a fun, new, suspiciously-familiar falling block game for CraftOS. Only on Pocket Computers!\",\
4341 [ \"programs/drive.lua\" ] = \"local tArgs = { ... }\\\
4342\\\
4343-- Get where a directory is mounted\\\
4344local sPath = shell.dir()\\\
4345if tArgs[1] ~= nil then\\\
4346 sPath = shell.resolve( tArgs[1] )\\\
4347end\\\
4348\\\
4349if fs.exists( sPath ) then\\\
4350 write( fs.getDrive( sPath ) .. \\\" (\\\" )\\\
4351 local nSpace = fs.getFreeSpace( sPath )\\\
4352 if nSpace >= 1000 * 1000 then\\\
4353 print( (math.floor( nSpace / (100 * 1000) ) / 10) .. \\\"MB remaining)\\\" )\\\
4354 elseif nSpace >= 1000 then\\\
4355 print( (math.floor( nSpace / 100 ) / 10) .. \\\"KB remaining)\\\" )\\\
4356 else\\\
4357 print( nSpace .. \\\"B remaining)\\\" )\\\
4358 end\\\
4359else\\\
4360 print( \\\"No such path\\\" )\\\
4361end\",\
4362 [ \"programs/mkdir.lua\" ] = \"local tArgs = { ... }\\\
4363if #tArgs < 1 then\\\
4364 print( \\\"Usage: mkdir <path>\\\" )\\\
4365 return\\\
4366end\\\
4367\\\
4368local sNewDir = shell.resolve( tArgs[1] )\\\
4369\\\
4370if fs.exists( sNewDir ) and not fs.isDir(sNewDir) then\\\
4371 printError( \\\"Destination exists\\\" )\\\
4372 return\\\
4373end\\\
4374\\\
4375fs.makeDir( sNewDir )\\\
4376\",\
4377 [ \"programs/eject.lua\" ] = \"\\\
4378-- Get arguments\\\
4379local tArgs = { ... }\\\
4380if #tArgs == 0 then\\\
4381 print( \\\"Usage: eject <drive>\\\" )\\\
4382 return\\\
4383end\\\
4384\\\
4385local sDrive = tArgs[1]\\\
4386\\\
4387-- Check the disk exists\\\
4388local bPresent = disk.isPresent( sDrive )\\\
4389if not bPresent then\\\
4390 print( \\\"Nothing in \\\"..sDrive..\\\" drive\\\" )\\\
4391 return\\\
4392end\\\
4393\\\
4394disk.eject( sDrive )\",\
4395 [ \"programs/turtle/turn.lua\" ] = \"local tArgs = { ... }\\\
4396if #tArgs < 1 then\\\
4397 print( \\\"Usage: turn <direction> <turns>\\\" )\\\
4398 return\\\
4399end\\\
4400\\\
4401local tHandlers = {\\\
4402 [\\\"lt\\\"] = turtle.turnLeft,\\\
4403 [\\\"left\\\"] = turtle.turnLeft,\\\
4404 [\\\"rt\\\"] = turtle.turnRight,\\\
4405 [\\\"right\\\"] = turtle.turnRight,\\\
4406}\\\
4407\\\
4408local nArg = 1\\\
4409while nArg <= #tArgs do\\\
4410 local sDirection = tArgs[nArg]\\\
4411 local nDistance = 1\\\
4412 if nArg < #tArgs then\\\
4413 local num = tonumber( tArgs[nArg + 1] )\\\
4414 if num then\\\
4415 nDistance = num\\\
4416 nArg = nArg + 1\\\
4417 end\\\
4418 end\\\
4419 nArg = nArg + 1\\\
4420\\\
4421 local fnHandler = tHandlers[string.lower(sDirection)]\\\
4422 if fnHandler then\\\
4423 for n=1,nDistance do\\\
4424 fnHandler( nArg )\\\
4425 end\\\
4426 else\\\
4427 print( \\\"No such direction: \\\"..sDirection )\\\
4428 print( \\\"Try: left, right\\\" )\\\
4429 return\\\
4430 end\\\
4431end\",\
4432 [ \"help/rename.txt\" ] = \"rename renames a file or directory.\\\
4433\\\
4434ex:\\\
4435\\\"rename foo bar\\\" renames the file \\\"foo\\\" to \\\"bar\\\".\",\
4436 [ \"apis/colors.lua\" ] = \"-- Colors\\\
4437white = 1\\\
4438orange = 2\\\
4439magenta = 4\\\
4440lightBlue = 8\\\
4441yellow = 16\\\
4442lime = 32\\\
4443pink = 64\\\
4444gray = 128\\\
4445lightGray = 256\\\
4446cyan = 512\\\
4447purple = 1024\\\
4448blue = 2048\\\
4449brown = 4096\\\
4450green = 8192\\\
4451red = 16384\\\
4452black = 32768\\\
4453\\\
4454function combine( ... )\\\
4455 local r = 0\\\
4456 for n,c in ipairs( { ... } ) do\\\
4457 if type( c ) ~= \\\"number\\\" then\\\
4458 error( \\\"bad argument #\\\"..n..\\\" (expected number, got \\\" .. type( c ) .. \\\")\\\", 2 )\\\
4459 end\\\
4460 r = bit32.bor(r,c)\\\
4461 end\\\
4462 return r\\\
4463end\\\
4464\\\
4465function subtract( colors, ... )\\\
4466 if type( colors ) ~= \\\"number\\\" then\\\
4467 error( \\\"bad argument #1 (expected number, got \\\" .. type( colors ) .. \\\")\\\", 2 )\\\
4468 end\\\
4469 local r = colors\\\
4470 for n,c in ipairs( { ... } ) do\\\
4471 if type( c ) ~= \\\"number\\\" then\\\
4472 error( \\\"bad argument #\\\"..tostring( n+1 )..\\\" (expected number, got \\\" .. type( c ) .. \\\")\\\", 2 )\\\
4473 end\\\
4474 r = bit32.band(r, bit32.bnot(c))\\\
4475 end\\\
4476 return r\\\
4477end\\\
4478\\\
4479function test( colors, color )\\\
4480 if type( colors ) ~= \\\"number\\\" then\\\
4481 error( \\\"bad argument #1 (expected number, got \\\" .. type( colors ) .. \\\")\\\", 2 )\\\
4482 end\\\
4483 if type( color ) ~= \\\"number\\\" then\\\
4484 error( \\\"bad argument #2 (expected number, got \\\" .. type( color ) .. \\\")\\\", 2 )\\\
4485 end\\\
4486 return ((bit32.band(colors, color)) == color)\\\
4487end\\\
4488\\\
4489function rgb8( r, g, b )\\\
4490 if type( r ) ~= \\\"number\\\" then\\\
4491 error( \\\"bad argument #1 (expected number, got \\\" .. type( r ) .. \\\")\\\", 2 )\\\
4492 elseif type(r) == \\\"number\\\" and g == nil and b == nil then\\\
4493 return bit32.band( bit32.rshift( r, 16 ), 0xFF ) / 255, bit32.band( bit32.rshift( r, 8 ), 0xFF ) / 255, bit32.band( r, 0xFF ) / 255\\\
4494 elseif type(r) == \\\"number\\\" and type(g) == \\\"number\\\" and type(b) == \\\"number\\\" then\\\
4495 return\\\
4496 bit32.lshift( bit32.band(r * 255, 0xFF), 16 ) +\\\
4497 bit32.lshift( bit32.band(g * 255, 0xFF), 8 ) +\\\
4498 bit32.band(b * 255, 0xFF)\\\
4499 elseif type( g ) ~= \\\"number\\\" then\\\
4500 error( \\\"bad argument #2 (expected number, got \\\" .. type( g ) .. \\\")\\\", 2 )\\\
4501 elseif type( b ) ~= \\\"number\\\" then\\\
4502 error( \\\"bad argument #3 (expected number, got \\\" .. type( b ) .. \\\")\\\", 2 )\\\
4503 end\\\
4504end\",\
4505 [ \"help/coroutine.txt\" ] = \"coroutine is a standard Lua5.1 API.\\\
4506Refer to http://www.lua.org/manual/5.1/ for more information.\",\
4507 [ \"apis/gps.lua\" ] = \"CHANNEL_GPS = 65534\\\
4508\\\
4509local function trilaterate( A, B, C )\\\
4510 local a2b = B.vPosition - A.vPosition\\\
4511 local a2c = C.vPosition - A.vPosition\\\
4512\\\
4513 if math.abs( a2b:normalize():dot( a2c:normalize() ) ) > 0.999 then\\\
4514 return nil\\\
4515 end\\\
4516\\\
4517 local d = a2b:length()\\\
4518 local ex = a2b:normalize( )\\\
4519 local i = ex:dot( a2c )\\\
4520 local ey = (a2c - (ex * i)):normalize()\\\
4521 local j = ey:dot( a2c )\\\
4522 local ez = ex:cross( ey )\\\
4523\\\
4524 local r1 = A.nDistance\\\
4525 local r2 = B.nDistance\\\
4526 local r3 = C.nDistance\\\
4527\\\
4528 local x = (r1*r1 - r2*r2 + d*d) / (2*d)\\\
4529 local y = (r1*r1 - r3*r3 - x*x + (x-i)*(x-i) + j*j) / (2*j)\\\
4530\\\
4531 local result = A.vPosition + (ex * x) + (ey * y)\\\
4532\\\
4533 local zSquared = r1*r1 - x*x - y*y\\\
4534 if zSquared > 0 then\\\
4535 local z = math.sqrt( zSquared )\\\
4536 local result1 = result + (ez * z)\\\
4537 local result2 = result - (ez * z)\\\
4538\\\
4539 local rounded1, rounded2 = result1:round( 0.01 ), result2:round( 0.01 )\\\
4540 if rounded1.x ~= rounded2.x or rounded1.y ~= rounded2.y or rounded1.z ~= rounded2.z then\\\
4541 return rounded1, rounded2\\\
4542 else\\\
4543 return rounded1\\\
4544 end\\\
4545 end\\\
4546 return result:round( 0.01 )\\\
4547\\\
4548end\\\
4549\\\
4550local function narrow( p1, p2, fix )\\\
4551 local dist1 = math.abs( (p1 - fix.vPosition):length() - fix.nDistance )\\\
4552 local dist2 = math.abs( (p2 - fix.vPosition):length() - fix.nDistance )\\\
4553\\\
4554 if math.abs(dist1 - dist2) < 0.01 then\\\
4555 return p1, p2\\\
4556 elseif dist1 < dist2 then\\\
4557 return p1:round( 0.01 )\\\
4558 else\\\
4559 return p2:round( 0.01 )\\\
4560 end\\\
4561end\\\
4562\\\
4563function locate( _nTimeout, _bDebug )\\\
4564 if _nTimeout ~= nil and type( _nTimeout ) ~= \\\"number\\\" then\\\
4565 error( \\\"bad argument #1 (expected number, got \\\" .. type( _nTimeout ) .. \\\")\\\", 2 )\\\
4566 end\\\
4567 if _bDebug ~= nil and type( _bDebug ) ~= \\\"boolean\\\" then\\\
4568 error( \\\"bad argument #2 (expected boolean, got \\\" .. type( _bDebug) .. \\\")\\\", 2 )\\\
4569 end\\\
4570 -- Let command computers use their magic fourth-wall-breaking special abilities\\\
4571 if commands then\\\
4572 return commands.getBlockPosition()\\\
4573 end\\\
4574\\\
4575 -- Find a modem\\\
4576 local sModemSide = nil\\\
4577 for n,sSide in ipairs( rs.getSides() ) do\\\
4578 if peripheral.getType( sSide ) == \\\"modem\\\" and peripheral.call( sSide, \\\"isWireless\\\" ) then\\\
4579 sModemSide = sSide\\\
4580 break\\\
4581 end\\\
4582 end\\\
4583\\\
4584 if sModemSide == nil then\\\
4585 if _bDebug then\\\
4586 print( \\\"No wireless modem attached\\\" )\\\
4587 end\\\
4588 return nil\\\
4589 end\\\
4590\\\
4591 if _bDebug then\\\
4592 print( \\\"Finding position...\\\" )\\\
4593 end\\\
4594\\\
4595 -- Open a channel\\\
4596 local modem = peripheral.wrap( sModemSide )\\\
4597 local bCloseChannel = false\\\
4598 if not modem.isOpen( os.getComputerID() ) then\\\
4599 modem.open( os.getComputerID() )\\\
4600 bCloseChannel = true\\\
4601 end\\\
4602\\\
4603 -- Send a ping to listening GPS hosts\\\
4604 modem.transmit( CHANNEL_GPS, os.getComputerID(), \\\"PING\\\" )\\\
4605\\\
4606 -- Wait for the responses\\\
4607 local tFixes = {}\\\
4608 local pos1, pos2 = nil, nil\\\
4609 local timeout = os.startTimer( _nTimeout or 2 )\\\
4610 while true do\\\
4611 local e, p1, p2, p3, p4, p5 = os.pullEvent()\\\
4612 if e == \\\"modem_message\\\" then\\\
4613 -- We received a reply from a modem\\\
4614 local sSide, sChannel, sReplyChannel, tMessage, nDistance = p1, p2, p3, p4, p5\\\
4615 if sSide == sModemSide and sChannel == os.getComputerID() and sReplyChannel == CHANNEL_GPS and nDistance then\\\
4616 -- Received the correct message from the correct modem: use it to determine position\\\
4617 if type(tMessage) == \\\"table\\\" and #tMessage == 3 and tonumber(tMessage[1]) and tonumber(tMessage[2]) and tonumber(tMessage[3]) then\\\
4618 local tFix = { vPosition = vector.new( tMessage[1], tMessage[2], tMessage[3] ), nDistance = nDistance }\\\
4619 if _bDebug then\\\
4620 print( tFix.nDistance..\\\" metres from \\\"..tostring( tFix.vPosition ) )\\\
4621 end\\\
4622 if tFix.nDistance == 0 then\\\
4623 pos1, pos2 = tFix.vPosition, nil\\\
4624 else\\\
4625 table.insert( tFixes, tFix )\\\
4626 if #tFixes >= 3 then\\\
4627 if not pos1 then\\\
4628 pos1, pos2 = trilaterate( tFixes[1], tFixes[2], tFixes[#tFixes] )\\\
4629 else\\\
4630 pos1, pos2 = narrow( pos1, pos2, tFixes[#tFixes] )\\\
4631 end\\\
4632 end\\\
4633 end\\\
4634 if pos1 and not pos2 then\\\
4635 break\\\
4636 end\\\
4637 end\\\
4638 end\\\
4639\\\
4640 elseif e == \\\"timer\\\" then\\\
4641 -- We received a timeout\\\
4642 local timer = p1\\\
4643 if timer == timeout then\\\
4644 break\\\
4645 end\\\
4646\\\
4647 end\\\
4648 end\\\
4649\\\
4650 -- Close the channel, if we opened one\\\
4651 if bCloseChannel then\\\
4652 modem.close( os.getComputerID() )\\\
4653 end\\\
4654\\\
4655 -- Return the response\\\
4656 if pos1 and pos2 then\\\
4657 if _bDebug then\\\
4658 print( \\\"Ambiguous position\\\" )\\\
4659 print( \\\"Could be \\\"..pos1.x..\\\",\\\"..pos1.y..\\\",\\\"..pos1.z..\\\" or \\\"..pos2.x..\\\",\\\"..pos2.y..\\\",\\\"..pos2.z )\\\
4660 end\\\
4661 return nil\\\
4662 elseif pos1 then\\\
4663 if _bDebug then\\\
4664 print( \\\"Position is \\\"..pos1.x..\\\",\\\"..pos1.y..\\\",\\\"..pos1.z )\\\
4665 end\\\
4666 return pos1.x, pos1.y, pos1.z\\\
4667 else\\\
4668 if _bDebug then\\\
4669 print( \\\"Could not determine position\\\" )\\\
4670 end\\\
4671 return nil\\\
4672 end\\\
4673end\",\
4674 [ \"help/exit.txt\" ] = \"exit will exit the current shell.\",\
4675 [ \"programs/edit.lua\" ] = \"-- Get file to edit\\\
4676local tArgs = { ... }\\\
4677if #tArgs == 0 then\\\
4678 print( \\\"Usage: edit <path>\\\" )\\\
4679 return\\\
4680end\\\
4681\\\
4682-- Error checking\\\
4683local sPath = shell.resolve( tArgs[1] )\\\
4684local bReadOnly = fs.isReadOnly( sPath )\\\
4685if fs.exists( sPath ) and fs.isDir( sPath ) then\\\
4686 print( \\\"Cannot edit a directory.\\\" )\\\
4687 return\\\
4688end\\\
4689\\\
4690-- Create .lua files by default\\\
4691if not fs.exists( sPath ) and not string.find( sPath, \\\"%.\\\" ) then\\\
4692 local sExtension = settings.get(\\\"edit.default_extension\\\", \\\"\\\" )\\\
4693 if sExtension ~= \\\"\\\" and type( sExtension ) == \\\"string\\\" then\\\
4694 sPath = sPath .. \\\".\\\" .. sExtension\\\
4695 end\\\
4696end\\\
4697\\\
4698local x,y = 1,1\\\
4699local w,h = term.getSize()\\\
4700local scrollX, scrollY = 0,0\\\
4701\\\
4702local tLines = {}\\\
4703local bRunning = true\\\
4704\\\
4705-- Colours\\\
4706local highlightColour, keywordColour, commentColour, textColour, bgColour, stringColour\\\
4707if term.isColour() then\\\
4708 bgColour = colours.black\\\
4709 textColour = colours.white\\\
4710 highlightColour = colours.yellow\\\
4711 keywordColour = colours.yellow\\\
4712 commentColour = colours.green\\\
4713 stringColour = colours.red\\\
4714else\\\
4715 bgColour = colours.black\\\
4716 textColour = colours.white\\\
4717 highlightColour = colours.white\\\
4718 keywordColour = colours.white\\\
4719 commentColour = colours.white\\\
4720 stringColour = colours.white\\\
4721end\\\
4722\\\
4723-- Menus\\\
4724local bMenu = false\\\
4725local nMenuItem = 1\\\
4726local tMenuItems = {}\\\
4727if not bReadOnly then\\\
4728 table.insert( tMenuItems, \\\"Save\\\" )\\\
4729end\\\
4730if shell.openTab then\\\
4731 table.insert( tMenuItems, \\\"Run\\\" )\\\
4732end\\\
4733if peripheral.find( \\\"printer\\\" ) then\\\
4734 table.insert( tMenuItems, \\\"Print\\\" )\\\
4735end\\\
4736table.insert( tMenuItems, \\\"Exit\\\" )\\\
4737\\\
4738local sStatus = \\\"Press Ctrl to access menu\\\"\\\
4739if string.len( sStatus ) > w - 5 then\\\
4740 sStatus = \\\"Press Ctrl for menu\\\"\\\
4741end\\\
4742\\\
4743local function load( _sPath )\\\
4744 tLines = {}\\\
4745 if fs.exists( _sPath ) then\\\
4746 local file = io.open( _sPath, \\\"r\\\" )\\\
4747 local sLine = file:read()\\\
4748 while sLine do\\\
4749 table.insert( tLines, sLine )\\\
4750 sLine = file:read()\\\
4751 end\\\
4752 file:close()\\\
4753 end\\\
4754\\\
4755 if #tLines == 0 then\\\
4756 table.insert( tLines, \\\"\\\" )\\\
4757 end\\\
4758end\\\
4759\\\
4760local function save( _sPath )\\\
4761 -- Create intervening folder\\\
4762 local sDir = _sPath:sub(1, _sPath:len() - fs.getName(_sPath):len() )\\\
4763 if not fs.exists( sDir ) then\\\
4764 fs.makeDir( sDir )\\\
4765 end\\\
4766\\\
4767 -- Save\\\
4768 local file, fileerr\\\
4769 local function innerSave()\\\
4770 file, fileerr = fs.open( _sPath, \\\"w\\\" )\\\
4771 if file then\\\
4772 for n, sLine in ipairs( tLines ) do\\\
4773 file.write( sLine .. \\\"\\\\n\\\" )\\\
4774 end\\\
4775 else\\\
4776 error( \\\"Failed to open \\\".._sPath )\\\
4777 end\\\
4778 end\\\
4779\\\
4780 local ok, err = pcall( innerSave )\\\
4781 if file then\\\
4782 file.close()\\\
4783 end\\\
4784 return ok, err, fileerr\\\
4785end\\\
4786\\\
4787local tKeywords = {\\\
4788 [\\\"and\\\"] = true,\\\
4789 [\\\"break\\\"] = true,\\\
4790 [\\\"do\\\"] = true,\\\
4791 [\\\"else\\\"] = true,\\\
4792 [\\\"elseif\\\"] = true,\\\
4793 [\\\"end\\\"] = true,\\\
4794 [\\\"false\\\"] = true,\\\
4795 [\\\"for\\\"] = true,\\\
4796 [\\\"function\\\"] = true,\\\
4797 [\\\"if\\\"] = true,\\\
4798 [\\\"in\\\"] = true,\\\
4799 [\\\"local\\\"] = true,\\\
4800 [\\\"nil\\\"] = true,\\\
4801 [\\\"not\\\"] = true,\\\
4802 [\\\"or\\\"] = true,\\\
4803 [\\\"repeat\\\"] = true,\\\
4804 [\\\"return\\\"] = true,\\\
4805 [\\\"then\\\"] = true,\\\
4806 [\\\"true\\\"] = true,\\\
4807 [\\\"until\\\"]= true,\\\
4808 [\\\"while\\\"] = true,\\\
4809}\\\
4810\\\
4811local function tryWrite( sLine, regex, colour )\\\
4812 local match = string.match( sLine, regex )\\\
4813 if match then\\\
4814 if type(colour) == \\\"number\\\" then\\\
4815 term.setTextColour( colour )\\\
4816 else\\\
4817 term.setTextColour( colour(match) )\\\
4818 end\\\
4819 term.write( match )\\\
4820 term.setTextColour( textColour )\\\
4821 return string.sub( sLine, string.len(match) + 1 )\\\
4822 end\\\
4823 return nil\\\
4824end\\\
4825\\\
4826local function writeHighlighted( sLine )\\\
4827 while string.len(sLine) > 0 do\\\
4828 sLine =\\\
4829 tryWrite( sLine, \\\"^%-%-%[%[.-%]%]\\\", commentColour ) or\\\
4830 tryWrite( sLine, \\\"^%-%-.*\\\", commentColour ) or\\\
4831 tryWrite( sLine, \\\"^\\\\\\\"\\\\\\\"\\\", stringColour ) or\\\
4832 tryWrite( sLine, \\\"^\\\\\\\".-[^\\\\\\\\]\\\\\\\"\\\", stringColour ) or\\\
4833 tryWrite( sLine, \\\"^\\\\'\\\\'\\\", stringColour ) or\\\
4834 tryWrite( sLine, \\\"^\\\\'.-[^\\\\\\\\]\\\\'\\\", stringColour ) or\\\
4835 tryWrite( sLine, \\\"^%[%[.-%]%]\\\", stringColour ) or\\\
4836 tryWrite( sLine, \\\"^[%w_]+\\\", function( match )\\\
4837 if tKeywords[ match ] then\\\
4838 return keywordColour\\\
4839 end\\\
4840 return textColour\\\
4841 end ) or\\\
4842 tryWrite( sLine, \\\"^[^%w_]\\\", textColour )\\\
4843 end\\\
4844end\\\
4845\\\
4846local tCompletions\\\
4847local nCompletion\\\
4848\\\
4849local tCompleteEnv = _ENV\\\
4850local function complete( sLine )\\\
4851 if settings.get( \\\"edit.autocomplete\\\" ) then\\\
4852 local nStartPos = string.find( sLine, \\\"[a-zA-Z0-9_%.:]+$\\\" )\\\
4853 if nStartPos then\\\
4854 sLine = string.sub( sLine, nStartPos )\\\
4855 end\\\
4856 if #sLine > 0 then\\\
4857 return textutils.complete( sLine, tCompleteEnv )\\\
4858 end\\\
4859 end\\\
4860 return nil\\\
4861end\\\
4862\\\
4863local function recomplete()\\\
4864 local sLine = tLines[y]\\\
4865 if not bMenu and not bReadOnly and x == string.len(sLine) + 1 then\\\
4866 tCompletions = complete( sLine )\\\
4867 if tCompletions and #tCompletions > 0 then\\\
4868 nCompletion = 1\\\
4869 else\\\
4870 nCompletion = nil\\\
4871 end\\\
4872 else\\\
4873 tCompletions = nil\\\
4874 nCompletion = nil\\\
4875 end\\\
4876end\\\
4877\\\
4878local function writeCompletion( sLine )\\\
4879 if nCompletion then\\\
4880 local sCompletion = tCompletions[ nCompletion ]\\\
4881 term.setTextColor( colours.white )\\\
4882 term.setBackgroundColor( colours.grey )\\\
4883 term.write( sCompletion )\\\
4884 term.setTextColor( textColour )\\\
4885 term.setBackgroundColor( bgColour )\\\
4886 end\\\
4887end\\\
4888\\\
4889local function redrawText()\\\
4890 local cursorX, cursorY = x, y\\\
4891 for y=1,h-1 do\\\
4892 term.setCursorPos( 1 - scrollX, y )\\\
4893 term.clearLine()\\\
4894\\\
4895 local sLine = tLines[ y + scrollY ]\\\
4896 if sLine ~= nil then\\\
4897 writeHighlighted( sLine )\\\
4898 if cursorY == y and cursorX == #sLine + 1 then\\\
4899 writeCompletion()\\\
4900 end\\\
4901 end\\\
4902 end\\\
4903 term.setCursorPos( x - scrollX, y - scrollY )\\\
4904end\\\
4905\\\
4906local function redrawLine(_nY)\\\
4907 local sLine = tLines[_nY]\\\
4908 if sLine then\\\
4909 term.setCursorPos( 1 - scrollX, _nY - scrollY )\\\
4910 term.clearLine()\\\
4911 writeHighlighted( sLine )\\\
4912 if _nY == y and x == #sLine + 1 then\\\
4913 writeCompletion()\\\
4914 end\\\
4915 term.setCursorPos( x - scrollX, _nY - scrollY )\\\
4916 end\\\
4917end\\\
4918\\\
4919local function redrawMenu()\\\
4920 -- Clear line\\\
4921 term.setCursorPos( 1, h )\\\
4922 term.clearLine()\\\
4923\\\
4924 -- Draw line numbers\\\
4925 term.setCursorPos( w - string.len( \\\"Ln \\\"..y ) + 1, h )\\\
4926 term.setTextColour( highlightColour )\\\
4927 term.write( \\\"Ln \\\" )\\\
4928 term.setTextColour( textColour )\\\
4929 term.write( y )\\\
4930\\\
4931 term.setCursorPos( 1, h )\\\
4932 if bMenu then\\\
4933 -- Draw menu\\\
4934 term.setTextColour( textColour )\\\
4935 for nItem,sItem in pairs( tMenuItems ) do\\\
4936 if nItem == nMenuItem then\\\
4937 term.setTextColour( highlightColour )\\\
4938 term.write( \\\"[\\\" )\\\
4939 term.setTextColour( textColour )\\\
4940 term.write( sItem )\\\
4941 term.setTextColour( highlightColour )\\\
4942 term.write( \\\"]\\\" )\\\
4943 term.setTextColour( textColour )\\\
4944 else\\\
4945 term.write( \\\" \\\"..sItem..\\\" \\\" )\\\
4946 end\\\
4947 end\\\
4948 else\\\
4949 -- Draw status\\\
4950 term.setTextColour( highlightColour )\\\
4951 term.write( sStatus )\\\
4952 term.setTextColour( textColour )\\\
4953 end\\\
4954\\\
4955 -- Reset cursor\\\
4956 term.setCursorPos( x - scrollX, y - scrollY )\\\
4957end\\\
4958\\\
4959local tMenuFuncs = {\\\
4960 Save = function()\\\
4961 if bReadOnly then\\\
4962 sStatus = \\\"Access denied\\\"\\\
4963 else\\\
4964 local ok, err, fileerr = save( sPath )\\\
4965 if ok then\\\
4966 sStatus=\\\"Saved to \\\"..sPath\\\
4967 else\\\
4968 if fileerr then\\\
4969 sStatus=\\\"Error saving to \\\"..fileerr\\\
4970 else\\\
4971 sStatus=\\\"Error saving to \\\"..sPath\\\
4972 end\\\
4973 end\\\
4974 end\\\
4975 redrawMenu()\\\
4976 end,\\\
4977 Print = function()\\\
4978 local printer = peripheral.find( \\\"printer\\\" )\\\
4979 if not printer then\\\
4980 sStatus = \\\"No printer attached\\\"\\\
4981 return\\\
4982 end\\\
4983\\\
4984 local nPage = 0\\\
4985 local sName = fs.getName( sPath )\\\
4986 if printer.getInkLevel() < 1 then\\\
4987 sStatus = \\\"Printer out of ink\\\"\\\
4988 return\\\
4989 elseif printer.getPaperLevel() < 1 then\\\
4990 sStatus = \\\"Printer out of paper\\\"\\\
4991 return\\\
4992 end\\\
4993\\\
4994 local screenTerminal = term.current()\\\
4995 local printerTerminal = {\\\
4996 getCursorPos = printer.getCursorPos,\\\
4997 setCursorPos = printer.setCursorPos,\\\
4998 getSize = printer.getPageSize,\\\
4999 write = printer.write,\\\
5000 }\\\
5001 printerTerminal.scroll = function()\\\
5002 if nPage == 1 then\\\
5003 printer.setPageTitle( sName..\\\" (page \\\"..nPage..\\\")\\\" )\\\
5004 end\\\
5005\\\
5006 while not printer.newPage() do\\\
5007 if printer.getInkLevel() < 1 then\\\
5008 sStatus = \\\"Printer out of ink, please refill\\\"\\\
5009 elseif printer.getPaperLevel() < 1 then\\\
5010 sStatus = \\\"Printer out of paper, please refill\\\"\\\
5011 else\\\
5012 sStatus = \\\"Printer output tray full, please empty\\\"\\\
5013 end\\\
5014\\\
5015 term.redirect( screenTerminal )\\\
5016 redrawMenu()\\\
5017 term.redirect( printerTerminal )\\\
5018\\\
5019 local timer = os.startTimer(0.5)\\\
5020 sleep(0.5)\\\
5021 end\\\
5022\\\
5023 nPage = nPage + 1\\\
5024 if nPage == 1 then\\\
5025 printer.setPageTitle( sName )\\\
5026 else\\\
5027 printer.setPageTitle( sName..\\\" (page \\\"..nPage..\\\")\\\" )\\\
5028 end\\\
5029 end\\\
5030\\\
5031 bMenu = false\\\
5032 term.redirect( printerTerminal )\\\
5033 local ok, error = pcall( function()\\\
5034 term.scroll()\\\
5035 for n, sLine in ipairs( tLines ) do\\\
5036 print( sLine )\\\
5037 end\\\
5038 end )\\\
5039 term.redirect( screenTerminal )\\\
5040 if not ok then\\\
5041 print( error )\\\
5042 end\\\
5043\\\
5044 while not printer.endPage() do\\\
5045 sStatus = \\\"Printer output tray full, please empty\\\"\\\
5046 redrawMenu()\\\
5047 sleep( 0.5 )\\\
5048 end\\\
5049 bMenu = true\\\
5050\\\
5051 if nPage > 1 then\\\
5052 sStatus = \\\"Printed \\\"..nPage..\\\" Pages\\\"\\\
5053 else\\\
5054 sStatus = \\\"Printed 1 Page\\\"\\\
5055 end\\\
5056 redrawMenu()\\\
5057 end,\\\
5058 Exit = function()\\\
5059 bRunning = false\\\
5060 end,\\\
5061 Run = function()\\\
5062 local sTempPath = \\\"/.temp\\\"\\\
5063 local ok, err = save( sTempPath )\\\
5064 if ok then\\\
5065 local nTask = shell.openTab( sTempPath )\\\
5066 if nTask then\\\
5067 shell.switchTab( nTask )\\\
5068 else\\\
5069 sStatus=\\\"Error starting Task\\\"\\\
5070 end\\\
5071 fs.delete( sTempPath )\\\
5072 else\\\
5073 sStatus=\\\"Error saving to \\\"..sTempPath\\\
5074 end\\\
5075 redrawMenu()\\\
5076 end\\\
5077}\\\
5078\\\
5079local function doMenuItem( _n )\\\
5080 tMenuFuncs[tMenuItems[_n]]()\\\
5081 if bMenu then\\\
5082 bMenu = false\\\
5083 term.setCursorBlink( true )\\\
5084 end\\\
5085 redrawMenu()\\\
5086end\\\
5087\\\
5088local function setCursor( newX, newY )\\\
5089 local oldX, oldY = x, y\\\
5090 x, y = newX, newY\\\
5091 local screenX = x - scrollX\\\
5092 local screenY = y - scrollY\\\
5093\\\
5094 local bRedraw = false\\\
5095 if screenX < 1 then\\\
5096 scrollX = x - 1\\\
5097 screenX = 1\\\
5098 bRedraw = true\\\
5099 elseif screenX > w then\\\
5100 scrollX = x - w\\\
5101 screenX = w\\\
5102 bRedraw = true\\\
5103 end\\\
5104\\\
5105 if screenY < 1 then\\\
5106 scrollY = y - 1\\\
5107 screenY = 1\\\
5108 bRedraw = true\\\
5109 elseif screenY > h-1 then\\\
5110 scrollY = y - (h-1)\\\
5111 screenY = h-1\\\
5112 bRedraw = true\\\
5113 end\\\
5114\\\
5115 recomplete()\\\
5116 if bRedraw then\\\
5117 redrawText()\\\
5118 elseif y ~= oldY then\\\
5119 redrawLine( oldY )\\\
5120 redrawLine( y )\\\
5121 else\\\
5122 redrawLine( y )\\\
5123 end\\\
5124 term.setCursorPos( screenX, screenY )\\\
5125\\\
5126 redrawMenu()\\\
5127end\\\
5128\\\
5129-- Actual program functionality begins\\\
5130load(sPath)\\\
5131\\\
5132term.setBackgroundColour( bgColour )\\\
5133term.clear()\\\
5134term.setCursorPos(x,y)\\\
5135term.setCursorBlink( true )\\\
5136\\\
5137recomplete()\\\
5138redrawText()\\\
5139redrawMenu()\\\
5140\\\
5141local function acceptCompletion()\\\
5142 if nCompletion then\\\
5143 -- Append the completion\\\
5144 local sCompletion = tCompletions[ nCompletion ]\\\
5145 tLines[y] = tLines[y] .. sCompletion\\\
5146 setCursor( x + string.len( sCompletion ), y )\\\
5147 end\\\
5148end\\\
5149\\\
5150-- Handle input\\\
5151while bRunning do\\\
5152 local sEvent, param, param2, param3 = os.pullEvent()\\\
5153 if sEvent == \\\"key\\\" then\\\
5154 local oldX, oldY = x, y\\\
5155 if param == keys.up then\\\
5156 -- Up\\\
5157 if not bMenu then\\\
5158 if nCompletion then\\\
5159 -- Cycle completions\\\
5160 nCompletion = nCompletion - 1\\\
5161 if nCompletion < 1 then\\\
5162 nCompletion = #tCompletions\\\
5163 end\\\
5164 redrawLine(y)\\\
5165\\\
5166 elseif y > 1 then\\\
5167 -- Move cursor up\\\
5168 setCursor(\\\
5169 math.min( x, string.len( tLines[y - 1] ) + 1 ),\\\
5170 y - 1\\\
5171 )\\\
5172 end\\\
5173 end\\\
5174\\\
5175 elseif param == keys.down then\\\
5176 -- Down\\\
5177 if not bMenu then\\\
5178 -- Move cursor down\\\
5179 if nCompletion then\\\
5180 -- Cycle completions\\\
5181 nCompletion = nCompletion + 1\\\
5182 if nCompletion > #tCompletions then\\\
5183 nCompletion = 1\\\
5184 end\\\
5185 redrawLine(y)\\\
5186\\\
5187 elseif y < #tLines then\\\
5188 -- Move cursor down\\\
5189 setCursor(\\\
5190 math.min( x, string.len( tLines[y + 1] ) + 1 ),\\\
5191 y + 1\\\
5192 )\\\
5193 end\\\
5194 end\\\
5195\\\
5196 elseif param == keys.tab then\\\
5197 -- Tab\\\
5198 if not bMenu and not bReadOnly then\\\
5199 if nCompletion and x == string.len(tLines[y]) + 1 then\\\
5200 -- Accept autocomplete\\\
5201 acceptCompletion()\\\
5202 else\\\
5203 -- Indent line\\\
5204 local sLine = tLines[y]\\\
5205 tLines[y] = string.sub(sLine,1,x-1) .. \\\" \\\" .. string.sub(sLine,x)\\\
5206 setCursor( x + 4, y )\\\
5207 end\\\
5208 end\\\
5209\\\
5210 elseif param == keys.pageUp then\\\
5211 -- Page Up\\\
5212 if not bMenu then\\\
5213 -- Move up a page\\\
5214 local newY\\\
5215 if y - (h - 1) >= 1 then\\\
5216 newY = y - (h - 1)\\\
5217 else\\\
5218 newY = 1\\\
5219 end\\\
5220 setCursor(\\\
5221 math.min( x, string.len( tLines[newY] ) + 1 ),\\\
5222 newY\\\
5223 )\\\
5224 end\\\
5225\\\
5226 elseif param == keys.pageDown then\\\
5227 -- Page Down\\\
5228 if not bMenu then\\\
5229 -- Move down a page\\\
5230 local newY\\\
5231 if y + (h - 1) <= #tLines then\\\
5232 newY = y + (h - 1)\\\
5233 else\\\
5234 newY = #tLines\\\
5235 end\\\
5236 local newX = math.min( x, string.len( tLines[newY] ) + 1 )\\\
5237 setCursor( newX, newY )\\\
5238 end\\\
5239\\\
5240 elseif param == keys.home then\\\
5241 -- Home\\\
5242 if not bMenu then\\\
5243 -- Move cursor to the beginning\\\
5244 if x > 1 then\\\
5245 setCursor(1,y)\\\
5246 end\\\
5247 end\\\
5248\\\
5249 elseif param == keys[\\\"end\\\"] then\\\
5250 -- End\\\
5251 if not bMenu then\\\
5252 -- Move cursor to the end\\\
5253 local nLimit = string.len( tLines[y] ) + 1\\\
5254 if x < nLimit then\\\
5255 setCursor( nLimit, y )\\\
5256 end\\\
5257 end\\\
5258\\\
5259 elseif param == keys.left then\\\
5260 -- Left\\\
5261 if not bMenu then\\\
5262 if x > 1 then\\\
5263 -- Move cursor left\\\
5264 setCursor( x - 1, y )\\\
5265 elseif x==1 and y>1 then\\\
5266 setCursor( string.len( tLines[y-1] ) + 1, y - 1 )\\\
5267 end\\\
5268 else\\\
5269 -- Move menu left\\\
5270 nMenuItem = nMenuItem - 1\\\
5271 if nMenuItem < 1 then\\\
5272 nMenuItem = #tMenuItems\\\
5273 end\\\
5274 redrawMenu()\\\
5275 end\\\
5276\\\
5277 elseif param == keys.right then\\\
5278 -- Right\\\
5279 if not bMenu then\\\
5280 local nLimit = string.len( tLines[y] ) + 1\\\
5281 if x < nLimit then\\\
5282 -- Move cursor right\\\
5283 setCursor( x + 1, y )\\\
5284 elseif nCompletion and x == string.len(tLines[y]) + 1 then\\\
5285 -- Accept autocomplete\\\
5286 acceptCompletion()\\\
5287 elseif x==nLimit and y<#tLines then\\\
5288 -- Go to next line\\\
5289 setCursor( 1, y + 1 )\\\
5290 end\\\
5291 else\\\
5292 -- Move menu right\\\
5293 nMenuItem = nMenuItem + 1\\\
5294 if nMenuItem > #tMenuItems then\\\
5295 nMenuItem = 1\\\
5296 end\\\
5297 redrawMenu()\\\
5298 end\\\
5299\\\
5300 elseif param == keys.delete then\\\
5301 -- Delete\\\
5302 if not bMenu and not bReadOnly then\\\
5303 local nLimit = string.len( tLines[y] ) + 1\\\
5304 if x < nLimit then\\\
5305 local sLine = tLines[y]\\\
5306 tLines[y] = string.sub(sLine,1,x-1) .. string.sub(sLine,x+1)\\\
5307 recomplete()\\\
5308 redrawLine(y)\\\
5309 elseif y<#tLines then\\\
5310 tLines[y] = tLines[y] .. tLines[y+1]\\\
5311 table.remove( tLines, y+1 )\\\
5312 recomplete()\\\
5313 redrawText()\\\
5314 end\\\
5315 end\\\
5316\\\
5317 elseif param == keys.backspace then\\\
5318 -- Backspace\\\
5319 if not bMenu and not bReadOnly then\\\
5320 if x > 1 then\\\
5321 -- Remove character\\\
5322 local sLine = tLines[y]\\\
5323 if x > 4 and string.sub(sLine,x-4,x-1) == \\\" \\\" and not string.sub(sLine, 1, x - 1):find(\\\"%S\\\") then\\\
5324 tLines[y] = string.sub(sLine,1,x-5) .. string.sub(sLine,x)\\\
5325 setCursor( x - 4, y )\\\
5326 else\\\
5327 tLines[y] = string.sub(sLine,1,x-2) .. string.sub(sLine,x)\\\
5328 setCursor( x - 1, y )\\\
5329 end\\\
5330 elseif y > 1 then\\\
5331 -- Remove newline\\\
5332 local sPrevLen = string.len( tLines[y-1] )\\\
5333 tLines[y-1] = tLines[y-1] .. tLines[y]\\\
5334 table.remove( tLines, y )\\\
5335 setCursor( sPrevLen + 1, y - 1 )\\\
5336 redrawText()\\\
5337 end\\\
5338 end\\\
5339\\\
5340 elseif param == keys.enter then\\\
5341 -- Enter\\\
5342 if not bMenu and not bReadOnly then\\\
5343 -- Newline\\\
5344 local sLine = tLines[y]\\\
5345 local _,spaces=string.find(sLine,\\\"^[ ]+\\\")\\\
5346 if not spaces then\\\
5347 spaces=0\\\
5348 end\\\
5349 tLines[y] = string.sub(sLine,1,x-1)\\\
5350 table.insert( tLines, y+1, string.rep(' ',spaces)..string.sub(sLine,x) )\\\
5351 setCursor( spaces + 1, y + 1 )\\\
5352 redrawText()\\\
5353\\\
5354 elseif bMenu then\\\
5355 -- Menu selection\\\
5356 doMenuItem( nMenuItem )\\\
5357\\\
5358 end\\\
5359\\\
5360 elseif param == keys.leftCtrl or param == keys.rightCtrl or param == keys.rightAlt then\\\
5361 -- Menu toggle\\\
5362 bMenu = not bMenu\\\
5363 if bMenu then\\\
5364 term.setCursorBlink( false )\\\
5365 else\\\
5366 term.setCursorBlink( true )\\\
5367 end\\\
5368 redrawMenu()\\\
5369\\\
5370 end\\\
5371\\\
5372 elseif sEvent == \\\"char\\\" then\\\
5373 if not bMenu and not bReadOnly then\\\
5374 -- Input text\\\
5375 local sLine = tLines[y]\\\
5376 tLines[y] = string.sub(sLine,1,x-1) .. param .. string.sub(sLine,x)\\\
5377 setCursor( x + 1, y )\\\
5378\\\
5379 elseif bMenu then\\\
5380 -- Select menu items\\\
5381 for n,sMenuItem in ipairs( tMenuItems ) do\\\
5382 if string.lower(string.sub(sMenuItem,1,1)) == string.lower(param) then\\\
5383 doMenuItem( n )\\\
5384 break\\\
5385 end\\\
5386 end\\\
5387 end\\\
5388\\\
5389 elseif sEvent == \\\"paste\\\" then\\\
5390 if not bReadOnly then\\\
5391 -- Close menu if open\\\
5392 if bMenu then\\\
5393 bMenu = false\\\
5394 term.setCursorBlink( true )\\\
5395 redrawMenu()\\\
5396 end\\\
5397 -- Input text\\\
5398 local sLine = tLines[y]\\\
5399 tLines[y] = string.sub(sLine,1,x-1) .. param .. string.sub(sLine,x)\\\
5400 setCursor( x + string.len( param ), y )\\\
5401 end\\\
5402\\\
5403 elseif sEvent == \\\"mouse_click\\\" then\\\
5404 if not bMenu then\\\
5405 if param == 1 then\\\
5406 -- Left click\\\
5407 local cx,cy = param2, param3\\\
5408 if cy < h then\\\
5409 local newY = math.min( math.max( scrollY + cy, 1 ), #tLines )\\\
5410 local newX = math.min( math.max( scrollX + cx, 1 ), string.len( tLines[newY] ) + 1 )\\\
5411 setCursor( newX, newY )\\\
5412 end\\\
5413 end\\\
5414 end\\\
5415\\\
5416 elseif sEvent == \\\"mouse_scroll\\\" then\\\
5417 if not bMenu then\\\
5418 if param == -1 then\\\
5419 -- Scroll up\\\
5420 if scrollY > 0 then\\\
5421 -- Move cursor up\\\
5422 scrollY = scrollY - 1\\\
5423 redrawText()\\\
5424 end\\\
5425\\\
5426 elseif param == 1 then\\\
5427 -- Scroll down\\\
5428 local nMaxScroll = #tLines - (h-1)\\\
5429 if scrollY < nMaxScroll then\\\
5430 -- Move cursor down\\\
5431 scrollY = scrollY + 1\\\
5432 redrawText()\\\
5433 end\\\
5434\\\
5435 end\\\
5436 end\\\
5437\\\
5438 elseif sEvent == \\\"term_resize\\\" then\\\
5439 w,h = term.getSize()\\\
5440 setCursor( x, y )\\\
5441 redrawMenu()\\\
5442 redrawText()\\\
5443\\\
5444 end\\\
5445end\\\
5446\\\
5447-- Cleanup\\\
5448term.clear()\\\
5449term.setCursorBlink( false )\\\
5450term.setCursorPos( 1, 1 )\",\
5451 [ \"help/mkdir.txt\" ] = \"mkdir creates a directory in the current location.\\\
5452\\\
5453ex:\\\
5454\\\"mkdir foo\\\" creates a directory named \\\"foo\\\".\\\
5455\\\"mkdir ../foo\\\" creates a directory named \\\"foo\\\" in the directory above the current directory.\",\
5456 [ \"apis/peripheral.lua\" ] = \"local native = peripheral\\\
5457\\\
5458function getNames()\\\
5459 local tResults = {}\\\
5460 for n,sSide in ipairs( rs.getSides() ) do\\\
5461 if native.isPresent( sSide ) then\\\
5462 table.insert( tResults, sSide )\\\
5463 if native.getType( sSide ) == \\\"modem\\\" and not native.call( sSide, \\\"isWireless\\\" ) then\\\
5464 local tRemote = native.call( sSide, \\\"getNamesRemote\\\" )\\\
5465 for n,sName in ipairs( tRemote ) do\\\
5466 table.insert( tResults, sName )\\\
5467 end\\\
5468 end\\\
5469 end\\\
5470 end\\\
5471 return tResults\\\
5472end\\\
5473\\\
5474function isPresent( _sSide )\\\
5475 if type( _sSide ) ~= \\\"string\\\" then\\\
5476 error( \\\"bad argument #1 (expected string, got \\\" .. type( _sSide ) .. \\\")\\\", 2 )\\\
5477 end\\\
5478 if native.isPresent( _sSide ) then\\\
5479 return true\\\
5480 end\\\
5481 for n,sSide in ipairs( rs.getSides() ) do\\\
5482 if native.getType( sSide ) == \\\"modem\\\" and not native.call( sSide, \\\"isWireless\\\" ) then\\\
5483 if native.call( sSide, \\\"isPresentRemote\\\", _sSide ) then\\\
5484 return true\\\
5485 end\\\
5486 end\\\
5487 end\\\
5488 return false\\\
5489end\\\
5490\\\
5491function getType( _sSide )\\\
5492 if type( _sSide ) ~= \\\"string\\\" then\\\
5493 error( \\\"bad argument #1 (expected string, got \\\" .. type( _sSide ) .. \\\")\\\", 2 )\\\
5494 end\\\
5495 if native.isPresent( _sSide ) then\\\
5496 return native.getType( _sSide )\\\
5497 end\\\
5498 for n,sSide in ipairs( rs.getSides() ) do\\\
5499 if native.getType( sSide ) == \\\"modem\\\" and not native.call( sSide, \\\"isWireless\\\" ) then\\\
5500 if native.call( sSide, \\\"isPresentRemote\\\", _sSide ) then\\\
5501 return native.call( sSide, \\\"getTypeRemote\\\", _sSide )\\\
5502 end\\\
5503 end\\\
5504 end\\\
5505 return nil\\\
5506end\\\
5507\\\
5508function getMethods( _sSide )\\\
5509 if type( _sSide ) ~= \\\"string\\\" then\\\
5510 error( \\\"bad argument #1 (expected string, got \\\" .. type( _sSide ) .. \\\")\\\", 2 )\\\
5511 end\\\
5512 if native.isPresent( _sSide ) then\\\
5513 return native.getMethods( _sSide )\\\
5514 end\\\
5515 for n,sSide in ipairs( rs.getSides() ) do\\\
5516 if native.getType( sSide ) == \\\"modem\\\" and not native.call( sSide, \\\"isWireless\\\" ) then\\\
5517 if native.call( sSide, \\\"isPresentRemote\\\", _sSide ) then\\\
5518 return native.call( sSide, \\\"getMethodsRemote\\\", _sSide )\\\
5519 end\\\
5520 end\\\
5521 end\\\
5522 return nil\\\
5523end\\\
5524\\\
5525function call( _sSide, _sMethod, ... )\\\
5526 if type( _sSide ) ~= \\\"string\\\" then\\\
5527 error( \\\"bad argument #1 (expected string, got \\\" .. type( _sSide ) .. \\\")\\\", 2 )\\\
5528 end\\\
5529 if type( _sSide ) ~= \\\"string\\\" then\\\
5530 error( \\\"bad argument #2 (expected string, got \\\" .. type( _sMethod ) .. \\\")\\\", 2 )\\\
5531 end\\\
5532 if native.isPresent( _sSide ) then\\\
5533 return native.call( _sSide, _sMethod, ... )\\\
5534 end\\\
5535 for n,sSide in ipairs( rs.getSides() ) do\\\
5536 if native.getType( sSide ) == \\\"modem\\\" and not native.call( sSide, \\\"isWireless\\\" ) then\\\
5537 if native.call( sSide, \\\"isPresentRemote\\\", _sSide ) then\\\
5538 return native.call( sSide, \\\"callRemote\\\", _sSide, _sMethod, ... )\\\
5539 end\\\
5540 end\\\
5541 end\\\
5542 return nil\\\
5543end\\\
5544\\\
5545function wrap( _sSide )\\\
5546 if type( _sSide ) ~= \\\"string\\\" then\\\
5547 error( \\\"bad argument #1 (expected string, got \\\" .. type( _sSide ) .. \\\")\\\", 2 )\\\
5548 end\\\
5549 if peripheral.isPresent( _sSide ) then\\\
5550 local tMethods = peripheral.getMethods( _sSide )\\\
5551 local tResult = {}\\\
5552 for n,sMethod in ipairs( tMethods ) do\\\
5553 tResult[sMethod] = function( ... )\\\
5554 return peripheral.call( _sSide, sMethod, ... )\\\
5555 end\\\
5556 end\\\
5557 return tResult\\\
5558 end\\\
5559 return nil\\\
5560end\\\
5561\\\
5562function find( sType, fnFilter )\\\
5563 if type( sType ) ~= \\\"string\\\" then\\\
5564 error( \\\"bad argument #1 (expected string, got \\\" .. type( sType ) .. \\\")\\\", 2 )\\\
5565 end\\\
5566 if fnFilter ~= nil and type( fnFilter ) ~= \\\"function\\\" then\\\
5567 error( \\\"bad argument #2 (expected function, got \\\" .. type( fnFilter ) .. \\\")\\\", 2 )\\\
5568 end\\\
5569 local tResults = {}\\\
5570 for n,sName in ipairs( peripheral.getNames() ) do\\\
5571 if peripheral.getType( sName ) == sType then\\\
5572 local wrapped = peripheral.wrap( sName )\\\
5573 if fnFilter == nil or fnFilter( sName, wrapped ) then\\\
5574 table.insert( tResults, wrapped )\\\
5575 end\\\
5576 end\\\
5577 end\\\
5578 return table.unpack( tResults )\\\
5579end\",\
5580 [ \"help/programming.txt\" ] = \"To learn the lua programming language, visit http://lua-users.org/wiki/TutorialDirectory.\\\
5581\\\
5582To experiment with lua in CraftOS, run the \\\"lua\\\" program and start typing code.\\\
5583To create programs, use \\\"edit\\\" to create files, then type their names in the shell to run them. If you name a program \\\"startup\\\" and place it in the root or on a disk drive, it will run automatically when the computer starts.\\\
5584\\\
5585To terminate a program stuck in a loop, hold Ctrl+T for 1 second.\\\
5586To quickly shutdown a computer, hold Ctrl+S for 1 second.\\\
5587To quickly reboot a computer, hold Ctrl+R for 1 second.\\\
5588\\\
5589To learn about the programming APIs availiable, type \\\"apis\\\" or \\\"help apis\\\".\\\
5590If you get stuck, visit the forums at http://www.computercraft.info/ for advice and tutorials.\",\
5591 [ \"help/fg.txt\" ] = \"fg is a program for Advanced Computers which opens a new tab in the foreground.\\\
5592\\\
5593ex:\\\
5594\\\"fg\\\" will open a foreground tab running the shell\\\
5595\\\"fg worm\\\" will open a foreground tab running the \\\"worm\\\" program\",\
5596 [ \"apis/colours.lua\" ] = \"-- Colours (for lovers of british spelling)\\\
5597local colours = _ENV\\\
5598for k,v in pairs(colors) do\\\
5599 colours[k] = v\\\
5600end\\\
5601\\\
5602colours.grey = colors.gray\\\
5603colours.gray = nil\\\
5604\\\
5605colours.lightGrey = colors.lightGray\\\
5606colours.lightGray = nil\",\
5607 [ \"apis/turtle/turtle.lua\" ] = \"\\\
5608if not turtle then\\\
5609 error( \\\"Cannot load turtle API on computer\\\", 2 )\\\
5610end\\\
5611native = turtle.native or turtle\\\
5612\\\
5613local function addCraftMethod( object )\\\
5614 if peripheral.getType( \\\"left\\\" ) == \\\"workbench\\\" then\\\
5615 object.craft = function( ... )\\\
5616 return peripheral.call( \\\"left\\\", \\\"craft\\\", ... )\\\
5617 end\\\
5618 elseif peripheral.getType( \\\"right\\\" ) == \\\"workbench\\\" then\\\
5619 object.craft = function( ... )\\\
5620 return peripheral.call( \\\"right\\\", \\\"craft\\\", ... )\\\
5621 end\\\
5622 else\\\
5623 object.craft = nil\\\
5624 end\\\
5625end\\\
5626\\\
5627-- Put commands into environment table\\\
5628local env = _ENV\\\
5629for k,v in pairs( native ) do\\\
5630 if k == \\\"equipLeft\\\" or k == \\\"equipRight\\\" then\\\
5631 env[k] = function( ... )\\\
5632 local result, err = v( ... )\\\
5633 addCraftMethod( turtle )\\\
5634 return result, err\\\
5635 end\\\
5636 else\\\
5637 env[k] = v\\\
5638 end\\\
5639end\\\
5640addCraftMethod( env )\",\
5641 [ \"programs/set.lua\" ] = \"\\\
5642local tArgs = { ... }\\\
5643if #tArgs == 0 then\\\
5644 -- \\\"set\\\"\\\
5645 local x,y = term.getCursorPos()\\\
5646 local tSettings = {}\\\
5647 for n,sName in ipairs( settings.getNames() ) do\\\
5648 tSettings[n] = textutils.serialize(sName) .. \\\" is \\\" .. textutils.serialize(settings.get(sName))\\\
5649 end\\\
5650 textutils.pagedPrint(table.concat(tSettings,\\\"\\\\n\\\"),y-3)\\\
5651\\\
5652elseif #tArgs == 1 then\\\
5653 -- \\\"set foo\\\"\\\
5654 local sName = tArgs[1]\\\
5655 print( textutils.serialize(sName) .. \\\" is \\\" .. textutils.serialize(settings.get(sName)) )\\\
5656\\\
5657else\\\
5658 -- \\\"set foo bar\\\"\\\
5659 local sName = tArgs[1]\\\
5660 local sValue = tArgs[2]\\\
5661 local value\\\
5662 if sValue == \\\"true\\\" then\\\
5663 value = true\\\
5664 elseif sValue == \\\"false\\\" then\\\
5665 value = false\\\
5666 elseif sValue == \\\"nil\\\" then\\\
5667 value = nil\\\
5668 elseif tonumber(sValue) then\\\
5669 value = tonumber(sValue)\\\
5670 else\\\
5671 value = sValue\\\
5672 end\\\
5673\\\
5674 local oldValue = settings.get( sValue )\\\
5675 if value ~= nil then\\\
5676 settings.set( sName, value )\\\
5677 print( textutils.serialize(sName) .. \\\" set to \\\" .. textutils.serialize(value) )\\\
5678 else\\\
5679 settings.unset( sName )\\\
5680 print( textutils.serialize(sName) .. \\\" unset\\\" )\\\
5681 end\\\
5682 if value ~= oldValue then\\\
5683 settings.save( \\\".settings\\\" )\\\
5684 end\\\
5685end\",\
5686 [ \"help/parallel.txt\" ] = \"Functions in the Parallel API:\\\
5687parallel.waitForAny( function1, function2, ... )\\\
5688parallel.waitForAll( function1, function2, ... )\\\
5689These methods provide an easy way to run multiple lua functions simultaneously.\",\
5690 [ \"help/wget.txt\" ] = \"wget is a program for downloading files from the internet. This is useful for downloading programs created by other players.\\\
5691If no filename is specified wget will try to determine the filename from the URL by stripping any anchors, parameters and trailing slashes and then taking everything remaining after the last slash.\\\
5692The HTTP API must be enabled in ComputerCraft.cfg to use this program.\\\
5693ex:\\\
5694\\\"wget http://pastebin.com/raw/CxaWmPrX test\\\" will download the file from the URL http://pastebin.com/raw/CxaWmPrX, and save it as \\\"test\\\".\\\
5695\\\"wget http://example.org/test.lua/?foo=bar#qzu\\\" will download the file from the URL http://example.org/test.lua/?foo=bar#qzu and save it as \\\"test.lua\\\"\\\
5696\\\"wget http://example.org/\\\" will download the file from the URL http://example.org and save it as \\\"example.org\\\"\",\
5697 [ \"help/edit.txt\" ] = \"edit is a text editor for creating or modifying programs or text files. After creating a program with edit, type its filename in the shell to run it. You can open any of the builtin programs with edit to learn how to program.\\\
5698\\\
5699ex:\\\
5700\\\"edit hello\\\" opens a file called \\\"hello\\\" for editing.\",\
5701 [ \"programs/exit.lua\" ] = \"shell.exit()\",\
5702 [ \"help/rednet.txt\" ] = \"The rednet API provides a simple computer networking model using modems.\\\
5703\\\
5704Functions in the rednet API:\\\
5705rednet.open( side )\\\
5706rednet.close( [side] )\\\
5707rednet.isOpen( [side] )\\\
5708rednet.send( receiverID, message, [protocol] ) -- Send to a specific computer\\\
5709rednet.broadcast( message, [protocol] ) -- Send to all computers\\\
5710rednet.receive( [protocol], [timeout] ) -- Returns: senderID, message, protocol\\\
5711rednet.host( protocol, hostname )\\\
5712rednet.unhost( protocol )\\\
5713rednet.lookup( protocol, [hostname] ) -- Returns: ID\\\
5714\\\
5715Events fired by the rednet API:\\\
5716\\\"rednet_message\\\" when a message is received. Arguments are senderID, message, protocol\\\
5717Type \\\"help events\\\" to learn about the event system.\\\
5718\\\
5719Rednet is not the only way to use modems for networking. Interfacing with the modem directly using the peripheral API and listening for the \\\"modem_message\\\" event allows for lower level control, at the expense of powerful high level networking features.\",\
5720 [ \"help/turn.txt\" ] = \"turn is a program for Turtles, used to turn the turtle around without programming. It accepts one or more commands as a direction and a number of turns. The \\\"go\\\" program can also be used for turning.\\\
5721\\\
5722ex:\\\
5723\\\"turn left\\\" turns the turtle 90 degrees left.\\\
5724\\\"turn right 2\\\" turns the turtle 180 degrees right.\\\
5725\\\"turn left 2 right\\\" turns left 180 degrees, then right 90 degrees.\",\
5726 [ \"programs/fun/advanced/levels/4.dat\" ] = \"2\\\
5727 77777777\\\
5728777778888887\\\
5729788888777787\\\
57307b77787 787\\\
5731787 787 787\\\
57327b77787 787\\\
57337888887 787\\\
57347777707 707\\\
5735 777 777\",\
5736 [ \"programs/fun/advanced/levels/0.dat\" ] = \"0\\\
573777 77\\\
5738718888887\\\
5739 8 8\\\
5740 8 8\\\
5741 8 8\\\
5742788888897\\\
574377 77\",\
5744 [ \"help/workbench.txt\" ] = \"Workbenches are peripheral devices found on Crafty Turtles running CraftOS. Type \\\"help peripheral\\\" to learn about using the Peripheral API to connect with peripherals. When a workbench is attached to a turtle, peripheral.getType() will return \\\"workbench\\\".\\\
5745\\\
5746Methods exposed by Workbenches:\\\
5747craft( channel )\",\
5748 [ \"programs/fun/advanced/levels/9.dat\" ] = \"2\\\
5749 777 777\\\
5750 777877778777\\\
5751 788838888887\\\
57527778bbbbbbbb8777\\\
57537888b888888b8897\\\
57547878be8888eb8787\\\
57557588b888888b8887\\\
57567778bbbbbbbb8777\\\
5757 788888818887\\\
5758 777877778777\\\
5759 777 777\",\
5760 [ \"startup.lua\" ] = \"\\\
5761-- Setup paths\\\
5762local sPath = \\\".:/rom/programs\\\"\\\
5763if term.isColor() then\\\
5764 sPath = sPath..\\\":/rom/programs/advanced\\\"\\\
5765end\\\
5766if turtle then\\\
5767 sPath = sPath..\\\":/rom/programs/turtle\\\"\\\
5768else\\\
5769 sPath = sPath..\\\":/rom/programs/rednet:/rom/programs/fun\\\"\\\
5770 if term.isColor() then\\\
5771 sPath = sPath..\\\":/rom/programs/fun/advanced\\\"\\\
5772 end\\\
5773end\\\
5774if pocket then\\\
5775 sPath = sPath..\\\":/rom/programs/pocket\\\"\\\
5776end\\\
5777if commands then\\\
5778 sPath = sPath..\\\":/rom/programs/command\\\"\\\
5779end\\\
5780if http then\\\
5781 sPath = sPath..\\\":/rom/programs/http\\\"\\\
5782end\\\
5783shell.setPath( sPath )\\\
5784help.setPath( \\\"/rom/help\\\" )\\\
5785\\\
5786-- Setup aliases\\\
5787shell.setAlias( \\\"ls\\\", \\\"list\\\" )\\\
5788shell.setAlias( \\\"dir\\\", \\\"list\\\" )\\\
5789shell.setAlias( \\\"cp\\\", \\\"copy\\\" )\\\
5790shell.setAlias( \\\"mv\\\", \\\"move\\\" )\\\
5791shell.setAlias( \\\"rm\\\", \\\"delete\\\" )\\\
5792shell.setAlias( \\\"clr\\\", \\\"clear\\\" )\\\
5793shell.setAlias( \\\"rs\\\", \\\"redstone\\\" )\\\
5794shell.setAlias( \\\"sh\\\", \\\"shell\\\" )\\\
5795if term.isColor() then\\\
5796 shell.setAlias( \\\"background\\\", \\\"bg\\\" )\\\
5797 shell.setAlias( \\\"foreground\\\", \\\"fg\\\" )\\\
5798end\\\
5799\\\
5800-- Setup completion functions\\\
5801local function completeMultipleChoice( sText, tOptions, bAddSpaces )\\\
5802 local tResults = {}\\\
5803 for n=1,#tOptions do\\\
5804 local sOption = tOptions[n]\\\
5805 if #sOption + (bAddSpaces and 1 or 0) > #sText and string.sub( sOption, 1, #sText ) == sText then\\\
5806 local sResult = string.sub( sOption, #sText + 1 )\\\
5807 if bAddSpaces then\\\
5808 table.insert( tResults, sResult .. \\\" \\\" )\\\
5809 else\\\
5810 table.insert( tResults, sResult )\\\
5811 end\\\
5812 end\\\
5813 end\\\
5814 return tResults\\\
5815end\\\
5816local function completePeripheralName( sText, bAddSpaces )\\\
5817 return completeMultipleChoice( sText, peripheral.getNames(), bAddSpaces )\\\
5818end\\\
5819local tRedstoneSides = redstone.getSides()\\\
5820local function completeSide( sText, bAddSpaces )\\\
5821 return completeMultipleChoice( sText, tRedstoneSides, bAddSpaces )\\\
5822end\\\
5823local function completeFile( shell, nIndex, sText, tPreviousText )\\\
5824 if nIndex == 1 then\\\
5825 return fs.complete( sText, shell.dir(), true, false )\\\
5826 end\\\
5827end\\\
5828local function completeDir( shell, nIndex, sText, tPreviousText )\\\
5829 if nIndex == 1 then\\\
5830 return fs.complete( sText, shell.dir(), false, true )\\\
5831 end\\\
5832end\\\
5833local function completeEither( shell, nIndex, sText, tPreviousText )\\\
5834 if nIndex == 1 then\\\
5835 return fs.complete( sText, shell.dir(), true, true )\\\
5836 end\\\
5837end\\\
5838local function completeEitherEither( shell, nIndex, sText, tPreviousText )\\\
5839 if nIndex == 1 then\\\
5840 local tResults = fs.complete( sText, shell.dir(), true, true )\\\
5841 for n=1,#tResults do\\\
5842 local sResult = tResults[n]\\\
5843 if string.sub( sResult, #sResult, #sResult ) ~= \\\"/\\\" then\\\
5844 tResults[n] = sResult .. \\\" \\\"\\\
5845 end\\\
5846 end\\\
5847 return tResults\\\
5848 elseif nIndex == 2 then\\\
5849 return fs.complete( sText, shell.dir(), true, true )\\\
5850 end\\\
5851end\\\
5852local function completeProgram( shell, nIndex, sText, tPreviousText )\\\
5853 if nIndex == 1 then\\\
5854 return shell.completeProgram( sText )\\\
5855 end\\\
5856end\\\
5857local function completeHelp( shell, nIndex, sText, tPreviousText )\\\
5858 if nIndex == 1 then\\\
5859 return help.completeTopic( sText )\\\
5860 end\\\
5861end\\\
5862local function completeAlias( shell, nIndex, sText, tPreviousText )\\\
5863 if nIndex == 2 then\\\
5864 return shell.completeProgram( sText )\\\
5865 end\\\
5866end\\\
5867local function completePeripheral( shell, nIndex, sText, tPreviousText )\\\
5868 if nIndex == 1 then\\\
5869 return completePeripheralName( sText )\\\
5870 end\\\
5871end\\\
5872local tGPSOptions = { \\\"host\\\", \\\"host \\\", \\\"locate\\\" }\\\
5873local function completeGPS( shell, nIndex, sText, tPreviousText )\\\
5874 if nIndex == 1 then\\\
5875 return completeMultipleChoice( sText, tGPSOptions )\\\
5876 end\\\
5877end\\\
5878local tLabelOptions = { \\\"get\\\", \\\"get \\\", \\\"set \\\", \\\"clear\\\", \\\"clear \\\" }\\\
5879local function completeLabel( shell, nIndex, sText, tPreviousText )\\\
5880 if nIndex == 1 then\\\
5881 return completeMultipleChoice( sText, tLabelOptions )\\\
5882 elseif nIndex == 2 then\\\
5883 return completePeripheralName( sText )\\\
5884 end\\\
5885end\\\
5886local function completeMonitor( shell, nIndex, sText, tPreviousText )\\\
5887 if nIndex == 1 then\\\
5888 return completePeripheralName( sText, true )\\\
5889 elseif nIndex == 2 then\\\
5890 return shell.completeProgram( sText )\\\
5891 end\\\
5892end\\\
5893local tRedstoneOptions = { \\\"probe\\\", \\\"set \\\", \\\"pulse \\\" }\\\
5894local function completeRedstone( shell, nIndex, sText, tPreviousText )\\\
5895 if nIndex == 1 then\\\
5896 return completeMultipleChoice( sText, tRedstoneOptions )\\\
5897 elseif nIndex == 2 then\\\
5898 return completeSide( sText )\\\
5899 end\\\
5900end\\\
5901local tDJOptions = { \\\"play\\\", \\\"play \\\", \\\"stop \\\" }\\\
5902local function completeDJ( shell, nIndex, sText, tPreviousText )\\\
5903 if nIndex == 1 then\\\
5904 return completeMultipleChoice( sText, tDJOptions )\\\
5905 elseif nIndex == 2 then\\\
5906 return completePeripheralName( sText )\\\
5907 end\\\
5908end\\\
5909local tPastebinOptions = { \\\"put \\\", \\\"get \\\", \\\"run \\\" }\\\
5910local function completePastebin( shell, nIndex, sText, tPreviousText )\\\
5911 if nIndex == 1 then\\\
5912 return completeMultipleChoice( sText, tPastebinOptions )\\\
5913 elseif nIndex == 2 then\\\
5914 if tPreviousText[2] == \\\"put\\\" then\\\
5915 return fs.complete( sText, shell.dir(), true, false )\\\
5916 end\\\
5917 end\\\
5918end\\\
5919local tChatOptions = { \\\"host \\\", \\\"join \\\" }\\\
5920local function completeChat( shell, nIndex, sText, tPreviousText )\\\
5921 if nIndex == 1 then\\\
5922 return completeMultipleChoice( sText, tChatOptions )\\\
5923 end\\\
5924end\\\
5925local function completeSet( shell, nIndex, sText, tPreviousText )\\\
5926 if nIndex == 1 then\\\
5927 return completeMultipleChoice( sText, settings.getNames(), true )\\\
5928 end\\\
5929end\\\
5930local tCommands\\\
5931if commands then\\\
5932 tCommands = commands.list()\\\
5933end\\\
5934local function completeExec( shell, nIndex, sText, tPreviousText )\\\
5935 if nIndex == 1 and commands then\\\
5936 return completeMultipleChoice( sText, tCommands, true )\\\
5937 end\\\
5938end\\\
5939shell.setCompletionFunction( \\\"rom/programs/alias.lua\\\", completeAlias )\\\
5940shell.setCompletionFunction( \\\"rom/programs/cd.lua\\\", completeDir )\\\
5941shell.setCompletionFunction( \\\"rom/programs/copy.lua\\\", completeEitherEither )\\\
5942shell.setCompletionFunction( \\\"rom/programs/delete.lua\\\", completeEither )\\\
5943shell.setCompletionFunction( \\\"rom/programs/drive.lua\\\", completeDir )\\\
5944shell.setCompletionFunction( \\\"rom/programs/edit.lua\\\", completeFile )\\\
5945shell.setCompletionFunction( \\\"rom/programs/eject.lua\\\", completePeripheral )\\\
5946shell.setCompletionFunction( \\\"rom/programs/gps.lua\\\", completeGPS )\\\
5947shell.setCompletionFunction( \\\"rom/programs/help.lua\\\", completeHelp )\\\
5948shell.setCompletionFunction( \\\"rom/programs/id.lua\\\", completePeripheral )\\\
5949shell.setCompletionFunction( \\\"rom/programs/label.lua\\\", completeLabel )\\\
5950shell.setCompletionFunction( \\\"rom/programs/list.lua\\\", completeDir )\\\
5951shell.setCompletionFunction( \\\"rom/programs/mkdir.lua\\\", completeFile )\\\
5952shell.setCompletionFunction( \\\"rom/programs/monitor.lua\\\", completeMonitor )\\\
5953shell.setCompletionFunction( \\\"rom/programs/move.lua\\\", completeEitherEither )\\\
5954shell.setCompletionFunction( \\\"rom/programs/redstone.lua\\\", completeRedstone )\\\
5955shell.setCompletionFunction( \\\"rom/programs/rename.lua\\\", completeEitherEither )\\\
5956shell.setCompletionFunction( \\\"rom/programs/shell.lua\\\", completeProgram )\\\
5957shell.setCompletionFunction( \\\"rom/programs/type.lua\\\", completeEither )\\\
5958shell.setCompletionFunction( \\\"rom/programs/set.lua\\\", completeSet )\\\
5959shell.setCompletionFunction( \\\"rom/programs/advanced/bg.lua\\\", completeProgram )\\\
5960shell.setCompletionFunction( \\\"rom/programs/advanced/fg.lua\\\", completeProgram )\\\
5961shell.setCompletionFunction( \\\"rom/programs/fun/dj.lua\\\", completeDJ )\\\
5962shell.setCompletionFunction( \\\"rom/programs/fun/advanced/paint.lua\\\", completeFile )\\\
5963shell.setCompletionFunction( \\\"rom/programs/http/pastebin.lua\\\", completePastebin )\\\
5964shell.setCompletionFunction( \\\"rom/programs/rednet/chat.lua\\\", completeChat )\\\
5965shell.setCompletionFunction( \\\"rom/programs/command/exec.lua\\\", completeExec )\\\
5966\\\
5967if turtle then\\\
5968 local tGoOptions = { \\\"left\\\", \\\"right\\\", \\\"forward\\\", \\\"back\\\", \\\"down\\\", \\\"up\\\" }\\\
5969 local function completeGo( shell, nIndex, sText )\\\
5970 return completeMultipleChoice( sText, tGoOptions, true)\\\
5971 end\\\
5972 local tTurnOptions = { \\\"left\\\", \\\"right\\\" }\\\
5973 local function completeTurn( shell, nIndex, sText )\\\
5974 return completeMultipleChoice( sText, tTurnOptions, true )\\\
5975 end\\\
5976 local tEquipOptions = { \\\"left\\\", \\\"right\\\" }\\\
5977 local function completeEquip( shell, nIndex, sText )\\\
5978 if nIndex == 2 then\\\
5979 return completeMultipleChoice( sText, tEquipOptions )\\\
5980 end\\\
5981 end\\\
5982 local function completeUnequip( shell, nIndex, sText )\\\
5983 if nIndex == 1 then\\\
5984 return completeMultipleChoice( sText, tEquipOptions )\\\
5985 end\\\
5986 end\\\
5987 shell.setCompletionFunction( \\\"rom/programs/turtle/go.lua\\\", completeGo )\\\
5988 shell.setCompletionFunction( \\\"rom/programs/turtle/turn.lua\\\", completeTurn )\\\
5989 shell.setCompletionFunction( \\\"rom/programs/turtle/equip.lua\\\", completeEquip )\\\
5990 shell.setCompletionFunction( \\\"rom/programs/turtle/unequip.lua\\\", completeUnequip )\\\
5991end\\\
5992\\\
5993\\\
5994-- Run autorun files\\\
5995if fs.exists( \\\"/rom/autorun\\\" ) and fs.isDir( \\\"/rom/autorun\\\" ) then\\\
5996 local tFiles = fs.list( \\\"/rom/autorun\\\" )\\\
5997 table.sort( tFiles )\\\
5998 for n, sFile in ipairs( tFiles ) do\\\
5999 if string.sub( sFile, 1, 1 ) ~= \\\".\\\" then\\\
6000 local sPath = \\\"/rom/autorun/\\\"..sFile\\\
6001 if not fs.isDir( sPath ) then\\\
6002 shell.run( sPath )\\\
6003 end\\\
6004 end\\\
6005 end\\\
6006end\\\
6007\\\
6008local function findStartups( sBaseDir )\\\
6009 local tStartups = nil\\\
6010 local sBasePath = \\\"/\\\" .. fs.combine( sBaseDir, \\\"startup\\\" )\\\
6011 local sStartupNode = shell.resolveProgram( sBasePath )\\\
6012 if sStartupNode then\\\
6013 tStartups = { sStartupNode }\\\
6014 end\\\
6015 -- It's possible that there is a startup directory and a startup.lua file, so this has to be\\\
6016 -- executed even if a file has already been found.\\\
6017 if fs.isDir( sBasePath ) then\\\
6018 if tStartups == nil then\\\
6019 tStartups = {}\\\
6020 end\\\
6021 for _,v in pairs( fs.list( sBasePath ) ) do\\\
6022 local sPath = \\\"/\\\" .. fs.combine( sBasePath, v )\\\
6023 if not fs.isDir( sPath ) then\\\
6024 tStartups[ #tStartups + 1 ] = sPath\\\
6025 end\\\
6026 end\\\
6027 end\\\
6028 return tStartups\\\
6029end\\\
6030\\\
6031-- Run the user created startup, either from disk drives or the root\\\
6032local tUserStartups = nil\\\
6033if settings.get( \\\"shell.allow_startup\\\" ) then\\\
6034 tUserStartups = findStartups( \\\"/\\\" )\\\
6035end\\\
6036if settings.get( \\\"shell.allow_disk_startup\\\" ) then\\\
6037 for n,sName in pairs( peripheral.getNames() ) do\\\
6038 if disk.isPresent( sName ) and disk.hasData( sName ) then\\\
6039 local startups = findStartups( disk.getMountPath( sName ) )\\\
6040 if startups then\\\
6041 tUserStartups = startups\\\
6042 break\\\
6043 end\\\
6044 end\\\
6045 end\\\
6046end\\\
6047if tUserStartups then\\\
6048 for _,v in pairs( tUserStartups ) do\\\
6049 shell.run( v )\\\
6050 end\\\
6051end\",\
6052 [ \"programs/type.lua\" ] = \"\\\
6053local tArgs = { ... }\\\
6054if #tArgs < 1 then\\\
6055 print( \\\"Usage: type <path>\\\" )\\\
6056 return\\\
6057end\\\
6058\\\
6059local sPath = shell.resolve( tArgs[1] )\\\
6060if fs.exists( sPath ) then\\\
6061 if fs.isDir( sPath ) then\\\
6062 print( \\\"directory\\\" )\\\
6063 else\\\
6064 print( \\\"file\\\" )\\\
6065 end\\\
6066else\\\
6067 print( \\\"No such path\\\" )\\\
6068end\\\
6069\",\
6070 [ \"help/set.txt\" ] = \"The set program can be used to inspect and change system settings.\\\
6071\\\
6072Usage:\\\
6073\\\"set\\\" will print all the system settings and their values\\\
6074\\\"set foo\\\" will print the value of the system setting \\\"foo\\\"\\\
6075\\\"set foo bar\\\" will set the value of the system setting \\\"foo\\\" to \\\"bar\\\"\",\
6076 [ \"programs/turtle/unequip.lua\" ] = \"\\\
6077local tArgs = { ... }\\\
6078local function printUsage()\\\
6079 print( \\\"Usage: unequip <side>\\\" )\\\
6080end\\\
6081\\\
6082if #tArgs ~= 1 then\\\
6083 printUsage()\\\
6084 return\\\
6085end\\\
6086\\\
6087local function unequip( fnEquipFunction )\\\
6088 for nSlot=1,16 do\\\
6089 local nOldCount = turtle.getItemCount( nSlot )\\\
6090 if nOldCount == 0 then\\\
6091 turtle.select( nSlot )\\\
6092 if fnEquipFunction() then\\\
6093 local nNewCount = turtle.getItemCount( nSlot )\\\
6094 if nNewCount > 0 then\\\
6095 print( \\\"Item unequipped\\\" )\\\
6096 return\\\
6097 else\\\
6098 print( \\\"Nothing to unequip\\\" )\\\
6099 return\\\
6100 end\\\
6101 end\\\
6102 end\\\
6103 end\\\
6104 print( \\\"No space to unequip item\\\" )\\\
6105end\\\
6106\\\
6107local sSide = tArgs[1]\\\
6108if sSide == \\\"left\\\" then\\\
6109 unequip( turtle.equipLeft )\\\
6110elseif sSide == \\\"right\\\" then\\\
6111 unequip( turtle.equipRight )\\\
6112else\\\
6113 printUsage()\\\
6114 return\\\
6115end\",\
6116 [ \"help/intro.txt\" ] = \"Welcome to CraftOS!\\\
6117Type \\\"programs\\\" to see the programs you can run.\\\
6118Type \\\"help <program>\\\" to see help for a specific program.\\\
6119Type \\\"help programming\\\" to learn about programming.\\\
6120Type \\\"help whatsnew\\\" to find out about new features.\\\
6121Type \\\"help credits\\\" to learn who made all this.\\\
6122Type \\\"help index\\\" to see all help topics.\",\
6123 [ \"help/gps.txt\" ] = \"gps can be used to host a GPS server, or to determine a position using trilateration.\\\
6124Type \\\"help gpsapi\\\" for help using GPS functions in lua programs.\\\
6125\\\
6126ex:\\\
6127\\\"gps locate\\\" will connect to nearby GPS servers, and try to determine the position of the computer or turtle.\\\
6128\\\"gps host\\\" will try to determine the position, and host a GPS server if successful.\\\
6129\\\"gps host 10 20 30\\\" will host a GPS server, using the manually entered position 10,20,30. \\\
6130\\\
6131Take care when manually entering host positions. If the positions entered into multiple GPS hosts\\\
6132are not consistent, the results of locate calls will be incorrect.\",\
6133 [ \"help/peripheral.txt\" ] = \"The peripheral API is for interacting with external peripheral devices. Type \\\"help peripherals\\\" to learn about the peripherals available.\\\
6134\\\
6135Functions in the peripheral API:\\\
6136peripheral.getNames()\\\
6137peripheral.isPresent( name )\\\
6138peripheral.getType( name )\\\
6139peripheral.getMethods( name )\\\
6140peripheral.call( name, methodName, param1, param2, etc )\\\
6141peripheral.wrap( name )\\\
6142peripheral.find( type, [fnFilter] )\\\
6143\\\
6144Events fired by the peripheral API:\\\
6145\\\"peripheral\\\" when a new peripheral is attached. Argument is the name.\\\
6146\\\"peripheral_detach\\\" when a peripheral is removed. Argument is the name.\\\
6147Type \\\"help events\\\" to learn about the event system.\",\
6148 [ \"help/paintutils.txt\" ] = \"Functions in the Paint Utilities API:\\\
6149paintutils.drawPixel( x, y, colour )\\\
6150paintutils.drawLine( startX, startY, endX, endY, colour )\\\
6151paintutils.drawBox( startX, startY, endX, endY, colour )\\\
6152paintutils.drawFilledBox( startX, startY, endX, endY, colour )\\\
6153paintutils.loadImage( path )\\\
6154paintutils.drawImage( image, x, y )\",\
6155 [ \"programs/turtle/go.lua\" ] = \"local tArgs = { ... }\\\
6156if #tArgs < 1 then\\\
6157 print( \\\"Usage: go <direction> <distance>\\\" )\\\
6158 return\\\
6159end\\\
6160\\\
6161local tHandlers = {\\\
6162 [\\\"fd\\\"] = turtle.forward,\\\
6163 [\\\"forward\\\"] = turtle.forward,\\\
6164 [\\\"forwards\\\"] = turtle.forward,\\\
6165 [\\\"bk\\\"] = turtle.back,\\\
6166 [\\\"back\\\"] = turtle.back,\\\
6167 [\\\"up\\\"] = turtle.up,\\\
6168 [\\\"dn\\\"] = turtle.down,\\\
6169 [\\\"down\\\"] = turtle.down,\\\
6170 [\\\"lt\\\"] = turtle.turnLeft,\\\
6171 [\\\"left\\\"] = turtle.turnLeft,\\\
6172 [\\\"rt\\\"] = turtle.turnRight,\\\
6173 [\\\"right\\\"] = turtle.turnRight,\\\
6174}\\\
6175\\\
6176local nArg = 1\\\
6177while nArg <= #tArgs do\\\
6178 local sDirection = tArgs[nArg]\\\
6179 local nDistance = 1\\\
6180 if nArg < #tArgs then\\\
6181 local num = tonumber( tArgs[nArg + 1] )\\\
6182 if num then\\\
6183 nDistance = num\\\
6184 nArg = nArg + 1\\\
6185 end\\\
6186 end\\\
6187 nArg = nArg + 1\\\
6188\\\
6189 local fnHandler = tHandlers[string.lower(sDirection)]\\\
6190 if fnHandler then\\\
6191 while nDistance > 0 do\\\
6192 if fnHandler() then\\\
6193 nDistance = nDistance - 1\\\
6194 elseif turtle.getFuelLevel() == 0 then\\\
6195 print( \\\"Out of fuel\\\" )\\\
6196 return\\\
6197 else\\\
6198 sleep(0.5)\\\
6199 end\\\
6200 end\\\
6201 else\\\
6202 print( \\\"No such direction: \\\"..sDirection )\\\
6203 print( \\\"Try: forward, back, up, down\\\" )\\\
6204 return\\\
6205 end\\\
6206\\\
6207end\",\
6208 [ \"programs/turtle/excavate.lua\" ] = \"\\\
6209local tArgs = { ... }\\\
6210if #tArgs ~= 1 then\\\
6211 print( \\\"Usage: excavate <diameter>\\\" )\\\
6212 return\\\
6213end\\\
6214\\\
6215-- Mine in a quarry pattern until we hit something we can't dig\\\
6216local size = tonumber( tArgs[1] )\\\
6217if size < 1 then\\\
6218 print( \\\"Excavate diameter must be positive\\\" )\\\
6219 return\\\
6220end\\\
6221\\\
6222local depth = 0\\\
6223local unloaded = 0\\\
6224local collected = 0\\\
6225\\\
6226local xPos,zPos = 0,0\\\
6227local xDir,zDir = 0,1\\\
6228\\\
6229local goTo -- Filled in further down\\\
6230local refuel -- Filled in further down\\\
6231\\\
6232local function unload( _bKeepOneFuelStack )\\\
6233 print( \\\"Unloading items...\\\" )\\\
6234 for n=1,16 do\\\
6235 local nCount = turtle.getItemCount(n)\\\
6236 if nCount > 0 then\\\
6237 turtle.select(n)\\\
6238 local bDrop = true\\\
6239 if _bKeepOneFuelStack and turtle.refuel(0) then\\\
6240 bDrop = false\\\
6241 _bKeepOneFuelStack = false\\\
6242 end\\\
6243 if bDrop then\\\
6244 turtle.drop()\\\
6245 unloaded = unloaded + nCount\\\
6246 end\\\
6247 end\\\
6248 end\\\
6249 collected = 0\\\
6250 turtle.select(1)\\\
6251end\\\
6252\\\
6253local function returnSupplies()\\\
6254 local x,y,z,xd,zd = xPos,depth,zPos,xDir,zDir\\\
6255 print( \\\"Returning to surface...\\\" )\\\
6256 goTo( 0,0,0,0,-1 )\\\
6257\\\
6258 local fuelNeeded = 2*(x+y+z) + 1\\\
6259 if not refuel( fuelNeeded ) then\\\
6260 unload( true )\\\
6261 print( \\\"Waiting for fuel\\\" )\\\
6262 while not refuel( fuelNeeded ) do\\\
6263 os.pullEvent( \\\"turtle_inventory\\\" )\\\
6264 end\\\
6265 else\\\
6266 unload( true )\\\
6267 end\\\
6268\\\
6269 print( \\\"Resuming mining...\\\" )\\\
6270 goTo( x,y,z,xd,zd )\\\
6271end\\\
6272\\\
6273local function collect()\\\
6274 local bFull = true\\\
6275 local nTotalItems = 0\\\
6276 for n=1,16 do\\\
6277 local nCount = turtle.getItemCount(n)\\\
6278 if nCount == 0 then\\\
6279 bFull = false\\\
6280 end\\\
6281 nTotalItems = nTotalItems + nCount\\\
6282 end\\\
6283\\\
6284 if nTotalItems > collected then\\\
6285 collected = nTotalItems\\\
6286 if math.fmod(collected + unloaded, 50) == 0 then\\\
6287 print( \\\"Mined \\\"..(collected + unloaded)..\\\" items.\\\" )\\\
6288 end\\\
6289 end\\\
6290\\\
6291 if bFull then\\\
6292 print( \\\"No empty slots left.\\\" )\\\
6293 return false\\\
6294 end\\\
6295 return true\\\
6296end\\\
6297\\\
6298function refuel( ammount )\\\
6299 local fuelLevel = turtle.getFuelLevel()\\\
6300 if fuelLevel == \\\"unlimited\\\" then\\\
6301 return true\\\
6302 end\\\
6303\\\
6304 local needed = ammount or (xPos + zPos + depth + 2)\\\
6305 if turtle.getFuelLevel() < needed then\\\
6306 local fueled = false\\\
6307 for n=1,16 do\\\
6308 if turtle.getItemCount(n) > 0 then\\\
6309 turtle.select(n)\\\
6310 if turtle.refuel(1) then\\\
6311 while turtle.getItemCount(n) > 0 and turtle.getFuelLevel() < needed do\\\
6312 turtle.refuel(1)\\\
6313 end\\\
6314 if turtle.getFuelLevel() >= needed then\\\
6315 turtle.select(1)\\\
6316 return true\\\
6317 end\\\
6318 end\\\
6319 end\\\
6320 end\\\
6321 turtle.select(1)\\\
6322 return false\\\
6323 end\\\
6324\\\
6325 return true\\\
6326end\\\
6327\\\
6328local function tryForwards()\\\
6329 if not refuel() then\\\
6330 print( \\\"Not enough Fuel\\\" )\\\
6331 returnSupplies()\\\
6332 end\\\
6333\\\
6334 while not turtle.forward() do\\\
6335 if turtle.detect() then\\\
6336 if turtle.dig() then\\\
6337 if not collect() then\\\
6338 returnSupplies()\\\
6339 end\\\
6340 else\\\
6341 return false\\\
6342 end\\\
6343 elseif turtle.attack() then\\\
6344 if not collect() then\\\
6345 returnSupplies()\\\
6346 end\\\
6347 else\\\
6348 sleep( 0.5 )\\\
6349 end\\\
6350 end\\\
6351\\\
6352 xPos = xPos + xDir\\\
6353 zPos = zPos + zDir\\\
6354 return true\\\
6355end\\\
6356\\\
6357local function tryDown()\\\
6358 if not refuel() then\\\
6359 print( \\\"Not enough Fuel\\\" )\\\
6360 returnSupplies()\\\
6361 end\\\
6362\\\
6363 while not turtle.down() do\\\
6364 if turtle.detectDown() then\\\
6365 if turtle.digDown() then\\\
6366 if not collect() then\\\
6367 returnSupplies()\\\
6368 end\\\
6369 else\\\
6370 return false\\\
6371 end\\\
6372 elseif turtle.attackDown() then\\\
6373 if not collect() then\\\
6374 returnSupplies()\\\
6375 end\\\
6376 else\\\
6377 sleep( 0.5 )\\\
6378 end\\\
6379 end\\\
6380\\\
6381 depth = depth + 1\\\
6382 if math.fmod( depth, 10 ) == 0 then\\\
6383 print( \\\"Descended \\\"..depth..\\\" metres.\\\" )\\\
6384 end\\\
6385\\\
6386 return true\\\
6387end\\\
6388\\\
6389local function turnLeft()\\\
6390 turtle.turnLeft()\\\
6391 xDir, zDir = -zDir, xDir\\\
6392end\\\
6393\\\
6394local function turnRight()\\\
6395 turtle.turnRight()\\\
6396 xDir, zDir = zDir, -xDir\\\
6397end\\\
6398\\\
6399function goTo( x, y, z, xd, zd )\\\
6400 while depth > y do\\\
6401 if turtle.up() then\\\
6402 depth = depth - 1\\\
6403 elseif turtle.digUp() or turtle.attackUp() then\\\
6404 collect()\\\
6405 else\\\
6406 sleep( 0.5 )\\\
6407 end\\\
6408 end\\\
6409\\\
6410 if xPos > x then\\\
6411 while xDir ~= -1 do\\\
6412 turnLeft()\\\
6413 end\\\
6414 while xPos > x do\\\
6415 if turtle.forward() then\\\
6416 xPos = xPos - 1\\\
6417 elseif turtle.dig() or turtle.attack() then\\\
6418 collect()\\\
6419 else\\\
6420 sleep( 0.5 )\\\
6421 end\\\
6422 end\\\
6423 elseif xPos < x then\\\
6424 while xDir ~= 1 do\\\
6425 turnLeft()\\\
6426 end\\\
6427 while xPos < x do\\\
6428 if turtle.forward() then\\\
6429 xPos = xPos + 1\\\
6430 elseif turtle.dig() or turtle.attack() then\\\
6431 collect()\\\
6432 else\\\
6433 sleep( 0.5 )\\\
6434 end\\\
6435 end\\\
6436 end\\\
6437\\\
6438 if zPos > z then\\\
6439 while zDir ~= -1 do\\\
6440 turnLeft()\\\
6441 end\\\
6442 while zPos > z do\\\
6443 if turtle.forward() then\\\
6444 zPos = zPos - 1\\\
6445 elseif turtle.dig() or turtle.attack() then\\\
6446 collect()\\\
6447 else\\\
6448 sleep( 0.5 )\\\
6449 end\\\
6450 end\\\
6451 elseif zPos < z then\\\
6452 while zDir ~= 1 do\\\
6453 turnLeft()\\\
6454 end\\\
6455 while zPos < z do\\\
6456 if turtle.forward() then\\\
6457 zPos = zPos + 1\\\
6458 elseif turtle.dig() or turtle.attack() then\\\
6459 collect()\\\
6460 else\\\
6461 sleep( 0.5 )\\\
6462 end\\\
6463 end\\\
6464 end\\\
6465\\\
6466 while depth < y do\\\
6467 if turtle.down() then\\\
6468 depth = depth + 1\\\
6469 elseif turtle.digDown() or turtle.attackDown() then\\\
6470 collect()\\\
6471 else\\\
6472 sleep( 0.5 )\\\
6473 end\\\
6474 end\\\
6475\\\
6476 while zDir ~= zd or xDir ~= xd do\\\
6477 turnLeft()\\\
6478 end\\\
6479end\\\
6480\\\
6481if not refuel() then\\\
6482 print( \\\"Out of Fuel\\\" )\\\
6483 return\\\
6484end\\\
6485\\\
6486print( \\\"Excavating...\\\" )\\\
6487\\\
6488local reseal = false\\\
6489turtle.select(1)\\\
6490if turtle.digDown() then\\\
6491 reseal = true\\\
6492end\\\
6493\\\
6494local alternate = 0\\\
6495local done = false\\\
6496while not done do\\\
6497 for n=1,size do\\\
6498 for m=1,size-1 do\\\
6499 if not tryForwards() then\\\
6500 done = true\\\
6501 break\\\
6502 end\\\
6503 end\\\
6504 if done then\\\
6505 break\\\
6506 end\\\
6507 if n<size then\\\
6508 if math.fmod(n + alternate,2) == 0 then\\\
6509 turnLeft()\\\
6510 if not tryForwards() then\\\
6511 done = true\\\
6512 break\\\
6513 end\\\
6514 turnLeft()\\\
6515 else\\\
6516 turnRight()\\\
6517 if not tryForwards() then\\\
6518 done = true\\\
6519 break\\\
6520 end\\\
6521 turnRight()\\\
6522 end\\\
6523 end\\\
6524 end\\\
6525 if done then\\\
6526 break\\\
6527 end\\\
6528\\\
6529 if size > 1 then\\\
6530 if math.fmod(size,2) == 0 then\\\
6531 turnRight()\\\
6532 else\\\
6533 if alternate == 0 then\\\
6534 turnLeft()\\\
6535 else\\\
6536 turnRight()\\\
6537 end\\\
6538 alternate = 1 - alternate\\\
6539 end\\\
6540 end\\\
6541\\\
6542 if not tryDown() then\\\
6543 done = true\\\
6544 break\\\
6545 end\\\
6546end\\\
6547\\\
6548print( \\\"Returning to surface...\\\" )\\\
6549\\\
6550-- Return to where we started\\\
6551goTo( 0,0,0,0,-1 )\\\
6552unload( false )\\\
6553goTo( 0,0,0,0,1 )\\\
6554\\\
6555-- Seal the hole\\\
6556if reseal then\\\
6557 turtle.placeDown()\\\
6558end\\\
6559\\\
6560print( \\\"Mined \\\"..(collected + unloaded)..\\\" items total.\\\" )\",\
6561 [ \"programs/turtle/equip.lua\" ] = \"\\\
6562local tArgs = { ... }\\\
6563local function printUsage()\\\
6564 print( \\\"Usage: equip <slot> <side>\\\" )\\\
6565end\\\
6566\\\
6567if #tArgs ~= 2 then\\\
6568 printUsage()\\\
6569 return\\\
6570end\\\
6571\\\
6572local function equip( nSlot, fnEquipFunction )\\\
6573 turtle.select( nSlot )\\\
6574 local nOldCount = turtle.getItemCount( nSlot )\\\
6575 if nOldCount == 0 then\\\
6576 print( \\\"Nothing to equip\\\" )\\\
6577 elseif fnEquipFunction() then\\\
6578 local nNewCount = turtle.getItemCount( nSlot )\\\
6579 if nNewCount > 0 then\\\
6580 print( \\\"Items swapped\\\" )\\\
6581 else\\\
6582 print( \\\"Item equipped\\\" )\\\
6583 end\\\
6584 else\\\
6585 print( \\\"Item not equippable\\\" )\\\
6586 end\\\
6587end\\\
6588\\\
6589local nSlot = tonumber( tArgs[1] )\\\
6590local sSide = tArgs[2]\\\
6591if sSide == \\\"left\\\" then\\\
6592 equip( nSlot, turtle.equipLeft )\\\
6593elseif sSide == \\\"right\\\" then\\\
6594 equip( nSlot, turtle.equipRight )\\\
6595else\\\
6596 printUsage()\\\
6597 return\\\
6598end\",\
6599 [ \"help/whatsnew.txt\" ] = \"New Features in ComputerCraft 1.80:\\\
6600\\\
6601* Added .getResponseHeaders() to HTTP responses.\\\
6602* Return a HTTP response when a HTTP error occurs.\\\
6603* Added a GUI to change ComputerCraft config options.\\\
6604* os.time() and os.day() now accept parameters to give the real world time.\\\
6605* Added os.epoch()\\\
6606* Monitor text now glows in the dark.\\\
6607* Added a \\\"Pocket Computer upgrade API\\\" so mod developers can add their own pocket upgrades.\\\
6608* Added pocket.equipBack()/pocket.unequipBack() to add/remove pocket upgrades.\\\
6609* Added term.setPaletteColor()/term.getPaletteColor() to change/check colors\\\
6610* Added colors.rgb8()/colours.rgb8() \\\
6611* Performance improvements to fs.find\\\
6612* Requires the player to be interacting with the computer when typing\\\
6613* Disk labels are limited to 32 characters\\\
6614* Labels can now only include characters within the printable range ( to ~)\\\
6615* Various model improvements\\\
6616* There is now a configurable file descriptor limit\\\
6617* Threads are now daemon threads\\\
6618* Termination signals are now sent unless the computer is off\\\
6619* Fixed compilation errors\\\
6620* Now handles tile entity changes\\\
6621* GPS coordinates now have to be numbers\\\
6622* Turtle upgrades now act as tools and peripherals\\\
6623* The Filesystem.list result is now sorted\\\
6624* The number of values to unpack can now be manually specified\\\
6625* Small terminal & monitor rendering improvements\\\
6626* General improvements to the documentation\\\
6627* Redstone inputs are no longer reset when adding peripherals\\\
6628* Turtles now use tinting\\\
6629* shell.resolveProgram now picks up on *.lua files\\\
6630* Fixed a handful of bugs in ComputerCraft\\\
6631* Added speaker block, turtle upgrade, pocket upgrade, and peripheral api\\\
6632* Startup can now be a directory containing multiple startup files\\\
6633* Added .getLabel to the computer peripheral\\\
6634\\\
6635Type \\\"help changelog\\\" to see the full version history.\",\
6636 [ \"help/shutdown.txt\" ] = \"shutdown will turn off the computer.\",\
6637 [ \"apis/settings.lua\" ] = \"\\\
6638local tSettings = {}\\\
6639\\\
6640function set( sName, value )\\\
6641 if type( sName ) ~= \\\"string\\\" then error( \\\"bad argument #1 (expected string, got \\\" .. type( sName ) .. \\\")\\\", 2 ) end\\\
6642\\\
6643 local sValueTy = type(value)\\\
6644 if sValueTy ~= \\\"number\\\" and sValueTy ~= \\\"string\\\" and sValueTy ~= \\\"boolean\\\" and sValueTy ~= \\\"table\\\" then\\\
6645 error( \\\"bad argument #2 (expected value, got \\\" .. sValueTy .. \\\")\\\", 2 )\\\
6646 end\\\
6647 if sValueTy == \\\"table\\\" then\\\
6648 -- Ensure value is serializeable\\\
6649 value = textutils.unserialize( textutils.serialize(value) )\\\
6650 end\\\
6651 tSettings[ sName ] = value\\\
6652end\\\
6653\\\
6654local copy\\\
6655function copy( value )\\\
6656 if type(value) == \\\"table\\\" then\\\
6657 local result = {}\\\
6658 for k,v in pairs(value) do\\\
6659 result[k] = copy(v)\\\
6660 end\\\
6661 return result\\\
6662 else\\\
6663 return value\\\
6664 end\\\
6665end\\\
6666\\\
6667function get( sName, default )\\\
6668 if type(sName) ~= \\\"string\\\" then\\\
6669 error( \\\"bad argument #1 (expected string, got \\\" .. type( sName ) .. \\\")\\\", 2 )\\\
6670 end\\\
6671 local result = tSettings[ sName ]\\\
6672 if result ~= nil then\\\
6673 return copy(result)\\\
6674 else\\\
6675 return default\\\
6676 end\\\
6677end\\\
6678\\\
6679function unset( sName )\\\
6680 if type(sName) ~= \\\"string\\\" then\\\
6681 error( \\\"bad argument #1 (expected string, got \\\" .. type( sName ) .. \\\")\\\", 2 )\\\
6682 end\\\
6683 tSettings[ sName ] = nil\\\
6684end\\\
6685\\\
6686function clear()\\\
6687 tSettings = {}\\\
6688end\\\
6689\\\
6690function getNames()\\\
6691 local result = {}\\\
6692 for k,v in pairs( tSettings ) do\\\
6693 result[ #result + 1 ] = k\\\
6694 end\\\
6695 table.sort(result)\\\
6696 return result\\\
6697end\\\
6698\\\
6699function load( sPath )\\\
6700 if type(sPath) ~= \\\"string\\\" then\\\
6701 error( \\\"bad argument #1 (expected string, got \\\" .. type( sPath ) .. \\\")\\\", 2 )\\\
6702 end\\\
6703 local file = fs.open( sPath, \\\"r\\\" )\\\
6704 if not file then\\\
6705 return false\\\
6706 end\\\
6707\\\
6708 local sText = file.readAll()\\\
6709 file.close()\\\
6710\\\
6711 local tFile = textutils.unserialize( sText )\\\
6712 if type(tFile) ~= \\\"table\\\" then\\\
6713 return false\\\
6714 end\\\
6715\\\
6716 for k,v in pairs(tFile) do\\\
6717 if type(k) == \\\"string\\\" and\\\
6718 (type(v) == \\\"string\\\" or type(v) == \\\"number\\\" or type(v) == \\\"boolean\\\" or type(v) == \\\"table\\\") then\\\
6719 set( k, v )\\\
6720 end\\\
6721 end\\\
6722\\\
6723 return true\\\
6724end\\\
6725\\\
6726function save( sPath )\\\
6727 if type(sPath) ~= \\\"string\\\" then\\\
6728 error( \\\"bad argument #1 (expected string, got \\\" .. type( sPath ) .. \\\")\\\", 2 )\\\
6729 end\\\
6730 local file = fs.open( sPath, \\\"w\\\" )\\\
6731 if not file then\\\
6732 return false\\\
6733 end\\\
6734\\\
6735 file.write( textutils.serialize( tSettings ) )\\\
6736 file.close()\\\
6737\\\
6738 return true\\\
6739end\",\
6740 [ \"help/adventure.txt\" ] = \"adventure is a text adventure game for CraftOS. To navigate around the world of adventure, type simple instructions to the interpreter, for example: \\\"go north\\\", \\\"punch tree\\\", \\\"craft planks\\\", \\\"mine coal with pickaxe\\\", \\\"hit creeper with sword\\\"\",\
6741 [ \"help/term.txt\" ] = \"Functions in the Terminal API:\\\
6742term.write( text )\\\
6743term.blit( text, textColor, backgroundColor )\\\
6744term.clear()\\\
6745term.clearLine()\\\
6746term.getCursorPos()\\\
6747term.setCursorPos( x, y )\\\
6748term.setCursorBlink( blink )\\\
6749term.isColor()\\\
6750term.setTextColor( color )\\\
6751term.setBackgroundColor( color )\\\
6752term.getTextColor()\\\
6753term.getBackgroundColor()\\\
6754term.getSize()\\\
6755term.scroll( n )\\\
6756term.redirect( object )\\\
6757term.current()\\\
6758term.setPaletteColor( color, r, g, b )\\\
6759term.getPaletteColor( color )\\\
6760\\\
6761Events emitted by the terminals:\\\
6762\\\"term_resize\\\", when the size of a terminal changes. This can happen in multitasking environments, or when the terminal out is being redirected by the \\\"monitor\\\" program.\",\
6763 [ \"help/exec.txt\" ] = \"On a Command Computer, \\\"exec\\\" will execute a command as if entered on a command block. Use \\\"commands\\\" to list all the available commands.\\\
6764\\\
6765ex:\\\
6766\\\"exec say Hello World\\\"\\\
6767\\\"exec setblock ~0 ~1 ~0 minecraft:dirt\\\"\\\
6768\\\
6769Type \\\"help commandsapi\\\" for help using commands in lua programs.\",\
6770 [ \"programs/turtle/dance.lua\" ] = \"\\\
6771local tMoves = {\\\
6772 function()\\\
6773 turtle.up()\\\
6774 turtle.down()\\\
6775 end,\\\
6776 function()\\\
6777 turtle.up()\\\
6778 turtle.turnLeft()\\\
6779 turtle.turnLeft()\\\
6780 turtle.turnLeft()\\\
6781 turtle.turnLeft()\\\
6782 turtle.down()\\\
6783 end,\\\
6784 function()\\\
6785 turtle.up()\\\
6786 turtle.turnRight()\\\
6787 turtle.turnRight()\\\
6788 turtle.turnRight()\\\
6789 turtle.turnRight()\\\
6790 turtle.down()\\\
6791 end,\\\
6792 function()\\\
6793 turtle.turnLeft()\\\
6794 turtle.turnLeft()\\\
6795 turtle.turnLeft()\\\
6796 turtle.turnLeft()\\\
6797 end,\\\
6798 function()\\\
6799 turtle.turnRight()\\\
6800 turtle.turnRight()\\\
6801 turtle.turnRight()\\\
6802 turtle.turnRight()\\\
6803 end,\\\
6804 function()\\\
6805 turtle.turnLeft()\\\
6806 turtle.back()\\\
6807 turtle.back()\\\
6808 turtle.turnRight()\\\
6809 turtle.turnRight()\\\
6810 turtle.back()\\\
6811 turtle.back()\\\
6812 turtle.turnLeft()\\\
6813 end,\\\
6814 function()\\\
6815 turtle.turnRight()\\\
6816 turtle.back()\\\
6817 turtle.back()\\\
6818 turtle.turnLeft()\\\
6819 turtle.turnLeft()\\\
6820 turtle.back()\\\
6821 turtle.back()\\\
6822 turtle.turnRight()\\\
6823 end,\\\
6824 function()\\\
6825 turtle.back()\\\
6826 turtle.turnLeft()\\\
6827 turtle.back()\\\
6828 turtle.turnLeft()\\\
6829 turtle.back()\\\
6830 turtle.turnLeft()\\\
6831 turtle.back()\\\
6832 turtle.turnLeft()\\\
6833 end,\\\
6834 function()\\\
6835 turtle.back()\\\
6836 turtle.turnRight()\\\
6837 turtle.back()\\\
6838 turtle.turnRight()\\\
6839 turtle.back()\\\
6840 turtle.turnRight()\\\
6841 turtle.back()\\\
6842 turtle.turnRight()\\\
6843 end,\\\
6844}\\\
6845\\\
6846textutils.slowWrite( \\\"Preparing to get down.\\\" )\\\
6847textutils.slowPrint( \\\"..\\\", 0.75 )\\\
6848\\\
6849local sAudio = nil\\\
6850for n,sName in pairs( peripheral.getNames() ) do\\\
6851 if disk.hasAudio( sName ) then\\\
6852 disk.playAudio( sName )\\\
6853 print( \\\"Jamming to \\\"..disk.getAudioTitle( sName ) )\\\
6854 sAudio = sName\\\
6855 break\\\
6856 end\\\
6857end\\\
6858\\\
6859print( \\\"Press any key to stop the groove\\\" )\\\
6860\\\
6861parallel.waitForAny(\\\
6862 function()\\\
6863 while not bEnd do\\\
6864 local event, key = os.pullEvent(\\\"key\\\")\\\
6865 if key ~= keys.escape then\\\
6866 return\\\
6867 end\\\
6868 end\\\
6869 end,\\\
6870 function()\\\
6871 while true do\\\
6872 local fnMove = tMoves[math.random(1,#tMoves)]\\\
6873 fnMove()\\\
6874 end\\\
6875 end\\\
6876)\\\
6877\\\
6878if sAudio then\\\
6879 disk.stopAudio( sAudio )\\\
6880end\",\
6881 [ \"apis/rednet.lua\" ] = \"\\\
6882CHANNEL_BROADCAST = 65535\\\
6883CHANNEL_REPEAT = 65533\\\
6884\\\
6885local tReceivedMessages = {}\\\
6886local tReceivedMessageTimeouts = {}\\\
6887local tHostnames = {}\\\
6888\\\
6889function open( sModem )\\\
6890 if type( sModem ) ~= \\\"string\\\" then\\\
6891 error( \\\"bad argument #1 (expected string, got \\\" .. type( sModem ) .. \\\")\\\", 2 )\\\
6892 end\\\
6893 if peripheral.getType( sModem ) ~= \\\"modem\\\" then\\\
6894 error( \\\"No such modem: \\\"..sModem, 2 )\\\
6895 end\\\
6896 peripheral.call( sModem, \\\"open\\\", os.getComputerID() )\\\
6897 peripheral.call( sModem, \\\"open\\\", CHANNEL_BROADCAST )\\\
6898end\\\
6899\\\
6900function close( sModem )\\\
6901 if sModem then\\\
6902 -- Close a specific modem\\\
6903 if type( sModem ) ~= \\\"string\\\" then\\\
6904 error( \\\"bad argument #1 (expected string, got \\\" .. type( sModem ) .. \\\")\\\", 2 )\\\
6905 end\\\
6906 if peripheral.getType( sModem ) ~= \\\"modem\\\" then\\\
6907 error( \\\"No such modem: \\\"..sModem, 2 )\\\
6908 end\\\
6909 peripheral.call( sModem, \\\"close\\\", os.getComputerID() )\\\
6910 peripheral.call( sModem, \\\"close\\\", CHANNEL_BROADCAST )\\\
6911 else\\\
6912 -- Close all modems\\\
6913 for n,sModem in ipairs( peripheral.getNames() ) do\\\
6914 if isOpen( sModem ) then\\\
6915 close( sModem )\\\
6916 end\\\
6917 end\\\
6918 end\\\
6919end\\\
6920\\\
6921function isOpen( sModem )\\\
6922 if sModem then\\\
6923 -- Check if a specific modem is open\\\
6924 if type( sModem ) ~= \\\"string\\\" then\\\
6925 error( \\\"bad argument #1 (expected string, got \\\" .. type( sModem ) .. \\\")\\\", 2 )\\\
6926 end\\\
6927 if peripheral.getType( sModem ) == \\\"modem\\\" then\\\
6928 return peripheral.call( sModem, \\\"isOpen\\\", os.getComputerID() ) and peripheral.call( sModem, \\\"isOpen\\\", CHANNEL_BROADCAST )\\\
6929 end\\\
6930 else\\\
6931 -- Check if any modem is open\\\
6932 for n,sModem in ipairs( peripheral.getNames() ) do\\\
6933 if isOpen( sModem ) then\\\
6934 return true\\\
6935 end\\\
6936 end\\\
6937 end\\\
6938 return false\\\
6939end\\\
6940\\\
6941function send( nRecipient, message, sProtocol )\\\
6942 if type( nRecipient ) ~= \\\"number\\\" then\\\
6943 error( \\\"bad argument #1 (expected number, got \\\" .. type( nRecipient ) .. \\\")\\\", 2 )\\\
6944 end\\\
6945 if sProtocol ~= nil and type( sProtocol ) ~= \\\"string\\\" then\\\
6946 error( \\\"bad argument #3 (expected string, got \\\" .. type( sProtocol ) .. \\\")\\\", 2 )\\\
6947 end\\\
6948 -- Generate a (probably) unique message ID\\\
6949 -- We could do other things to guarantee uniqueness, but we really don't need to\\\
6950 -- Store it to ensure we don't get our own messages back\\\
6951 local nMessageID = math.random( 1, 2147483647 )\\\
6952 tReceivedMessages[ nMessageID ] = true\\\
6953 tReceivedMessageTimeouts[ os.startTimer( 30 ) ] = nMessageID\\\
6954\\\
6955 -- Create the message\\\
6956 local nReplyChannel = os.getComputerID()\\\
6957 local tMessage = {\\\
6958 nMessageID = nMessageID,\\\
6959 nRecipient = nRecipient,\\\
6960 message = message,\\\
6961 sProtocol = sProtocol,\\\
6962 }\\\
6963\\\
6964 if nRecipient == os.getComputerID() then\\\
6965 -- Loopback to ourselves\\\
6966 os.queueEvent( \\\"rednet_message\\\", nReplyChannel, message, sProtocol )\\\
6967\\\
6968 else\\\
6969 -- Send on all open modems, to the target and to repeaters\\\
6970 local sent = false\\\
6971 for n,sModem in ipairs( peripheral.getNames() ) do\\\
6972 if isOpen( sModem ) then\\\
6973 peripheral.call( sModem, \\\"transmit\\\", nRecipient, nReplyChannel, tMessage );\\\
6974 peripheral.call( sModem, \\\"transmit\\\", CHANNEL_REPEAT, nReplyChannel, tMessage );\\\
6975 sent = true\\\
6976 end\\\
6977 end\\\
6978 end\\\
6979end\\\
6980\\\
6981function broadcast( message, sProtocol )\\\
6982 if sProtocol ~= nil and type( sProtocol ) ~= \\\"string\\\" then\\\
6983 error( \\\"bad argument #2 (expected string, got \\\" .. type( sProtocol ) .. \\\")\\\", 2 )\\\
6984 end\\\
6985 send( CHANNEL_BROADCAST, message, sProtocol )\\\
6986end\\\
6987\\\
6988function receive( sProtocolFilter, nTimeout )\\\
6989 -- The parameters used to be ( nTimeout ), detect this case for backwards compatibility\\\
6990 if type(sProtocolFilter) == \\\"number\\\" and nTimeout == nil then\\\
6991 sProtocolFilter, nTimeout = nil, sProtocolFilter\\\
6992 end\\\
6993 if sProtocolFilter ~= nil and type( sProtocolFilter ) ~= \\\"string\\\" then\\\
6994 error( \\\"bad argument #1 (expected string, got \\\" .. type( sProtocolFilter ) .. \\\")\\\", 2 )\\\
6995 end\\\
6996 if nTimeout ~= nil and type( nTimeout ) ~= \\\"number\\\" then\\\
6997 error( \\\"bad argument #2 (expected number, got \\\" .. type( nTimeout ) .. \\\")\\\", 2 )\\\
6998 end\\\
6999\\\
7000 -- Start the timer\\\
7001 local timer = nil\\\
7002 local sFilter = nil\\\
7003 if nTimeout then\\\
7004 timer = os.startTimer( nTimeout )\\\
7005 sFilter = nil\\\
7006 else\\\
7007 sFilter = \\\"rednet_message\\\"\\\
7008 end\\\
7009\\\
7010 -- Wait for events\\\
7011 while true do\\\
7012 local sEvent, p1, p2, p3 = os.pullEvent( sFilter )\\\
7013 if sEvent == \\\"rednet_message\\\" then\\\
7014 -- Return the first matching rednet_message\\\
7015 local nSenderID, message, sProtocol = p1, p2, p3\\\
7016 if sProtocolFilter == nil or sProtocol == sProtocolFilter then\\\
7017 return nSenderID, message, sProtocol\\\
7018 end\\\
7019 elseif sEvent == \\\"timer\\\" then\\\
7020 -- Return nil if we timeout\\\
7021 if p1 == timer then\\\
7022 return nil\\\
7023 end\\\
7024 end\\\
7025 end\\\
7026end\\\
7027\\\
7028function host( sProtocol, sHostname )\\\
7029 if type( sProtocol ) ~= \\\"string\\\" then\\\
7030 error( \\\"bad argument #1 (expected string, got \\\" .. type( sProtocol ) .. \\\")\\\", 2 )\\\
7031 end\\\
7032 if type( sHostname ) ~= \\\"string\\\" then\\\
7033 error( \\\"bad argument #2 (expected string, got \\\" .. type( sHostname ) .. \\\")\\\", 2 )\\\
7034 end\\\
7035 if sHostname == \\\"localhost\\\" then\\\
7036 error( \\\"Reserved hostname\\\", 2 )\\\
7037 end\\\
7038 if tHostnames[ sProtocol ] ~= sHostname then\\\
7039 if lookup( sProtocol, sHostname ) ~= nil then\\\
7040 error( \\\"Hostname in use\\\", 2 )\\\
7041 end\\\
7042 tHostnames[ sProtocol ] = sHostname\\\
7043 end\\\
7044end\\\
7045\\\
7046function unhost( sProtocol )\\\
7047 if type( sProtocol ) ~= \\\"string\\\" then\\\
7048 error( \\\"bad argument #1 (expected string, got \\\" .. type( sProtocol ) .. \\\")\\\", 2 )\\\
7049 end\\\
7050 tHostnames[ sProtocol ] = nil\\\
7051end\\\
7052\\\
7053function lookup( sProtocol, sHostname )\\\
7054 if type( sProtocol ) ~= \\\"string\\\" then\\\
7055 error( \\\"bad argument #1 (expected string, got \\\" .. type( sProtocol ) .. \\\")\\\", 2 )\\\
7056 end\\\
7057 if sHostname ~= nil and type( sHostname ) ~= \\\"string\\\" then\\\
7058 error( \\\"bad argument #2 (expected string, got \\\" .. type( sHostname ) .. \\\")\\\", 2 )\\\
7059 end\\\
7060\\\
7061 -- Build list of host IDs\\\
7062 local tResults = nil\\\
7063 if sHostname == nil then\\\
7064 tResults = {}\\\
7065 end\\\
7066\\\
7067 -- Check localhost first\\\
7068 if tHostnames[ sProtocol ] then\\\
7069 if sHostname == nil then\\\
7070 table.insert( tResults, os.getComputerID() )\\\
7071 elseif sHostname == \\\"localhost\\\" or sHostname == tHostnames[ sProtocol ] then\\\
7072 return os.getComputerID()\\\
7073 end\\\
7074 end\\\
7075\\\
7076 if not isOpen() then\\\
7077 if tResults then\\\
7078 return table.unpack( tResults )\\\
7079 end\\\
7080 return nil\\\
7081 end\\\
7082\\\
7083 -- Broadcast a lookup packet\\\
7084 broadcast( {\\\
7085 sType = \\\"lookup\\\",\\\
7086 sProtocol = sProtocol,\\\
7087 sHostname = sHostname,\\\
7088 }, \\\"dns\\\" )\\\
7089\\\
7090 -- Start a timer\\\
7091 local timer = os.startTimer( 2 )\\\
7092\\\
7093 -- Wait for events\\\
7094 while true do\\\
7095 local event, p1, p2, p3 = os.pullEvent()\\\
7096 if event == \\\"rednet_message\\\" then\\\
7097 -- Got a rednet message, check if it's the response to our request\\\
7098 local nSenderID, tMessage, sMessageProtocol = p1, p2, p3\\\
7099 if sMessageProtocol == \\\"dns\\\" and type(tMessage) == \\\"table\\\" and tMessage.sType == \\\"lookup response\\\" then\\\
7100 if tMessage.sProtocol == sProtocol then\\\
7101 if sHostname == nil then\\\
7102 table.insert( tResults, nSenderID )\\\
7103 elseif tMessage.sHostname == sHostname then\\\
7104 return nSenderID\\\
7105 end\\\
7106 end\\\
7107 end\\\
7108 else\\\
7109 -- Got a timer event, check it's the end of our timeout\\\
7110 if p1 == timer then\\\
7111 break\\\
7112 end\\\
7113 end\\\
7114 end\\\
7115 if tResults then\\\
7116 return table.unpack( tResults )\\\
7117 end\\\
7118 return nil\\\
7119end\\\
7120\\\
7121local bRunning = false\\\
7122function run()\\\
7123 if bRunning then\\\
7124 error( \\\"rednet is already running\\\", 2 )\\\
7125 end\\\
7126 bRunning = true\\\
7127\\\
7128 while bRunning do\\\
7129 local sEvent, p1, p2, p3, p4 = os.pullEventRaw()\\\
7130 if sEvent == \\\"modem_message\\\" then\\\
7131 -- Got a modem message, process it and add it to the rednet event queue\\\
7132 local sModem, nChannel, nReplyChannel, tMessage = p1, p2, p3, p4\\\
7133 if isOpen( sModem ) and ( nChannel == os.getComputerID() or nChannel == CHANNEL_BROADCAST ) then\\\
7134 if type( tMessage ) == \\\"table\\\" and tMessage.nMessageID then\\\
7135 if not tReceivedMessages[ tMessage.nMessageID ] then\\\
7136 tReceivedMessages[ tMessage.nMessageID ] = true\\\
7137 tReceivedMessageTimeouts[ os.startTimer( 30 ) ] = tMessage.nMessageID\\\
7138 os.queueEvent( \\\"rednet_message\\\", nReplyChannel, tMessage.message, tMessage.sProtocol )\\\
7139 end\\\
7140 end\\\
7141 end\\\
7142\\\
7143 elseif sEvent == \\\"rednet_message\\\" then\\\
7144 -- Got a rednet message (queued from above), respond to dns lookup\\\
7145 local nSenderID, tMessage, sProtocol = p1, p2, p3\\\
7146 if sProtocol == \\\"dns\\\" and type(tMessage) == \\\"table\\\" and tMessage.sType == \\\"lookup\\\" then\\\
7147 local sHostname = tHostnames[ tMessage.sProtocol ]\\\
7148 if sHostname ~= nil and (tMessage.sHostname == nil or tMessage.sHostname == sHostname) then\\\
7149 rednet.send( nSenderID, {\\\
7150 sType = \\\"lookup response\\\",\\\
7151 sHostname = sHostname,\\\
7152 sProtocol = tMessage.sProtocol,\\\
7153 }, \\\"dns\\\" )\\\
7154 end\\\
7155 end\\\
7156\\\
7157 elseif sEvent == \\\"timer\\\" then\\\
7158 -- Got a timer event, use it to clear the event queue\\\
7159 local nTimer = p1\\\
7160 local nMessage = tReceivedMessageTimeouts[ nTimer ]\\\
7161 if nMessage then\\\
7162 tReceivedMessageTimeouts[ nTimer ] = nil\\\
7163 tReceivedMessages[ nMessage ] = nil\\\
7164 end\\\
7165 end\\\
7166 end\\\
7167end\",\
7168 [ \"programs/time.lua\" ] = \"local nTime = os.time()\\\
7169local nDay = os.day()\\\
7170print( \\\"The time is \\\"..textutils.formatTime( nTime, false )..\\\" on Day \\\"..nDay )\",\
7171 [ \"help/clear.txt\" ] = \"clear clears the screen.\",\
7172 [ \"programs/shutdown.lua\" ] = \"if term.isColour() then\\\
7173 term.setTextColour( colours.yellow )\\\
7174end\\\
7175print( \\\"Goodbye\\\" )\\\
7176term.setTextColour( colours.white )\\\
7177\\\
7178sleep( 1 )\\\
7179os.shutdown()\",\
7180 [ \"apis/parallel.lua\" ] = \"\\\
7181local function create( ... )\\\
7182 local tFns = table.pack(...)\\\
7183 local tCos = {}\\\
7184 for i = 1, tFns.n, 1 do\\\
7185 local fn = tFns[i]\\\
7186 if type( fn ) ~= \\\"function\\\" then\\\
7187 error( \\\"bad argument #\\\" .. i .. \\\" (expected function, got \\\" .. type( fn ) .. \\\")\\\", 3 )\\\
7188 end\\\
7189\\\
7190 tCos[i] = coroutine.create(fn)\\\
7191 end\\\
7192\\\
7193 return tCos\\\
7194end\\\
7195\\\
7196local function runUntilLimit( _routines, _limit )\\\
7197 local count = #_routines\\\
7198 local living = count\\\
7199\\\
7200 local tFilters = {}\\\
7201 local eventData = { n = 0 }\\\
7202 while true do\\\
7203 for n=1,count do\\\
7204 local r = _routines[n]\\\
7205 if r then\\\
7206 if tFilters[r] == nil or tFilters[r] == eventData[1] or eventData[1] == \\\"terminate\\\" then\\\
7207 local ok, param = coroutine.resume( r, table.unpack( eventData, 1, eventData.n ) )\\\
7208 if not ok then\\\
7209 error( param, 0 )\\\
7210 else\\\
7211 tFilters[r] = param\\\
7212 end\\\
7213 if coroutine.status( r ) == \\\"dead\\\" then\\\
7214 _routines[n] = nil\\\
7215 living = living - 1\\\
7216 if living <= _limit then\\\
7217 return n\\\
7218 end\\\
7219 end\\\
7220 end\\\
7221 end\\\
7222 end\\\
7223 for n=1,count do\\\
7224 local r = _routines[n]\\\
7225 if r and coroutine.status( r ) == \\\"dead\\\" then\\\
7226 _routines[n] = nil\\\
7227 living = living - 1\\\
7228 if living <= _limit then\\\
7229 return n\\\
7230 end\\\
7231 end\\\
7232 end\\\
7233 eventData = table.pack( os.pullEventRaw() )\\\
7234 end\\\
7235end\\\
7236\\\
7237function waitForAny( ... )\\\
7238 local routines = create( ... )\\\
7239 return runUntilLimit( routines, #routines - 1 )\\\
7240end\\\
7241\\\
7242function waitForAll( ... )\\\
7243 local routines = create( ... )\\\
7244 runUntilLimit( routines, 0 )\\\
7245end\",\
7246 [ \"help/time.txt\" ] = \"time prints the current time of day.\",\
7247 [ \"help/dance.txt\" ] = \"dance is a program for Turtles. Turtles love to get funky.\",\
7248 [ \"programs/shell.lua\" ] = \"\\\
7249local multishell = multishell\\\
7250local parentShell = shell\\\
7251local parentTerm = term.current()\\\
7252\\\
7253if multishell then\\\
7254 multishell.setTitle( multishell.getCurrent(), \\\"shell\\\" )\\\
7255end\\\
7256\\\
7257local bExit = false\\\
7258local sDir = (parentShell and parentShell.dir()) or \\\"\\\"\\\
7259local sPath = (parentShell and parentShell.path()) or \\\".:/rom/programs\\\"\\\
7260local tAliases = (parentShell and parentShell.aliases()) or {}\\\
7261local tCompletionInfo = (parentShell and parentShell.getCompletionInfo()) or {}\\\
7262local tProgramStack = {}\\\
7263\\\
7264local shell = {}\\\
7265local function createShellEnv( sDir )\\\
7266 local tEnv = {}\\\
7267 tEnv[ \\\"shell\\\" ] = shell\\\
7268 tEnv[ \\\"multishell\\\" ] = multishell\\\
7269\\\
7270 local package = {}\\\
7271 package.loaded = {\\\
7272 _G = _G,\\\
7273 bit32 = bit32,\\\
7274 coroutine = coroutine,\\\
7275 math = math,\\\
7276 package = package,\\\
7277 string = string,\\\
7278 table = table,\\\
7279 }\\\
7280 package.path = \\\"?;?.lua;?/init.lua;/rom/modules/main/?;/rom/modules/main/?.lua;/rom/modules/main/?/init.lua\\\"\\\
7281 if turtle then\\\
7282 package.path = package.path..\\\";/rom/modules/turtle/?;/rom/modules/turtle/?.lua;/rom/modules/turtle/?/init.lua\\\"\\\
7283 elseif command then\\\
7284 package.path = package.path..\\\";/rom/modules/command/?;/rom/modules/command/?.lua;/rom/modules/command/?/init.lua\\\"\\\
7285 end\\\
7286 package.config = \\\"/\\\\n;\\\\n?\\\\n!\\\\n-\\\"\\\
7287 package.preload = {}\\\
7288 package.loaders = {\\\
7289 function( name )\\\
7290 if package.preload[name] then\\\
7291 return package.preload[name]\\\
7292 else\\\
7293 return nil, \\\"no field package.preload['\\\" .. name .. \\\"']\\\"\\\
7294 end\\\
7295 end,\\\
7296 function( name )\\\
7297 local fname = string.gsub(name, \\\"%.\\\", \\\"/\\\")\\\
7298 local sError = \\\"\\\"\\\
7299 for pattern in string.gmatch(package.path, \\\"[^;]+\\\") do\\\
7300 local sPath = string.gsub(pattern, \\\"%?\\\", fname)\\\
7301 if sPath:sub(1,1) ~= \\\"/\\\" then\\\
7302 sPath = fs.combine(sDir, sPath)\\\
7303 end\\\
7304 if fs.exists(sPath) and not fs.isDir(sPath) then\\\
7305 local fnFile, sError = loadfile( sPath, tEnv )\\\
7306 if fnFile then\\\
7307 return fnFile, sPath\\\
7308 else\\\
7309 return nil, sError\\\
7310 end\\\
7311 else\\\
7312 if #sError > 0 then\\\
7313 sError = sError .. \\\"\\\\n\\\"\\\
7314 end\\\
7315 sError = sError .. \\\"no file '\\\" .. sPath .. \\\"'\\\"\\\
7316 end\\\
7317 end\\\
7318 return nil, sError\\\
7319 end\\\
7320 }\\\
7321\\\
7322 local sentinel = {}\\\
7323 local function require( name )\\\
7324 if type( name ) ~= \\\"string\\\" then\\\
7325 error( \\\"bad argument #1 (expected string, got \\\" .. type( name ) .. \\\")\\\", 2 )\\\
7326 end\\\
7327 if package.loaded[name] == sentinel then\\\
7328 error(\\\"Loop detected requiring '\\\" .. name .. \\\"'\\\", 0)\\\
7329 end\\\
7330 if package.loaded[name] then\\\
7331 return package.loaded[name]\\\
7332 end\\\
7333\\\
7334 local sError = \\\"Error loading module '\\\" .. name .. \\\"':\\\"\\\
7335 for n,searcher in ipairs(package.loaders) do\\\
7336 local loader, err = searcher(name)\\\
7337 if loader then\\\
7338 package.loaded[name] = sentinel\\\
7339 local result = loader( err )\\\
7340 if result ~= nil then\\\
7341 package.loaded[name] = result\\\
7342 return result\\\
7343 else\\\
7344 package.loaded[name] = true\\\
7345 return true\\\
7346 end\\\
7347 else\\\
7348 sError = sError .. \\\"\\\\n\\\" .. err\\\
7349 end\\\
7350 end\\\
7351 error(sError, 2)\\\
7352 end\\\
7353\\\
7354 tEnv[\\\"package\\\"] = package\\\
7355 tEnv[\\\"require\\\"] = require\\\
7356\\\
7357 return tEnv\\\
7358end\\\
7359\\\
7360-- Colours\\\
7361local promptColour, textColour, bgColour\\\
7362if term.isColour() then\\\
7363 promptColour = colours.yellow\\\
7364 textColour = colours.white\\\
7365 bgColour = colours.black\\\
7366else\\\
7367 promptColour = colours.white\\\
7368 textColour = colours.white\\\
7369 bgColour = colours.black\\\
7370end\\\
7371\\\
7372local function run( _sCommand, ... )\\\
7373 local sPath = shell.resolveProgram( _sCommand )\\\
7374 if sPath ~= nil then\\\
7375 tProgramStack[#tProgramStack + 1] = sPath\\\
7376 if multishell then\\\
7377 local sTitle = fs.getName( sPath )\\\
7378 if sTitle:sub(-4) == \\\".lua\\\" then\\\
7379 sTitle = sTitle:sub(1,-5)\\\
7380 end\\\
7381 multishell.setTitle( multishell.getCurrent(), sTitle )\\\
7382 end\\\
7383 local sDir = fs.getDir( sPath )\\\
7384 local result = os.run( createShellEnv( sDir ), sPath, ... )\\\
7385 tProgramStack[#tProgramStack] = nil\\\
7386 if multishell then\\\
7387 if #tProgramStack > 0 then\\\
7388 local sTitle = fs.getName( tProgramStack[#tProgramStack] )\\\
7389 if sTitle:sub(-4) == \\\".lua\\\" then\\\
7390 sTitle = sTitle:sub(1,-5)\\\
7391 end\\\
7392 multishell.setTitle( multishell.getCurrent(), sTitle )\\\
7393 else\\\
7394 multishell.setTitle( multishell.getCurrent(), \\\"shell\\\" )\\\
7395 end\\\
7396 end\\\
7397 return result\\\
7398 else\\\
7399 printError( \\\"No such program\\\" )\\\
7400 return false\\\
7401 end\\\
7402end\\\
7403\\\
7404local function tokenise( ... )\\\
7405 local sLine = table.concat( { ... }, \\\" \\\" )\\\
7406 local tWords = {}\\\
7407 local bQuoted = false\\\
7408 for match in string.gmatch( sLine .. \\\"\\\\\\\"\\\", \\\"(.-)\\\\\\\"\\\" ) do\\\
7409 if bQuoted then\\\
7410 table.insert( tWords, match )\\\
7411 else\\\
7412 for m in string.gmatch( match, \\\"[^ \\\\t]+\\\" ) do\\\
7413 table.insert( tWords, m )\\\
7414 end\\\
7415 end\\\
7416 bQuoted = not bQuoted\\\
7417 end\\\
7418 return tWords\\\
7419end\\\
7420\\\
7421-- Install shell API\\\
7422function shell.run( ... )\\\
7423 local tWords = tokenise( ... )\\\
7424 local sCommand = tWords[1]\\\
7425 if sCommand then\\\
7426 return run( sCommand, table.unpack( tWords, 2 ) )\\\
7427 end\\\
7428 return false\\\
7429end\\\
7430\\\
7431function shell.exit()\\\
7432 bExit = true\\\
7433end\\\
7434\\\
7435function shell.dir()\\\
7436 return sDir\\\
7437end\\\
7438\\\
7439function shell.setDir( _sDir )\\\
7440 if type( _sDir ) ~= \\\"string\\\" then\\\
7441 error( \\\"bad argument #1 (expected string, got \\\" .. type( _sDir ) .. \\\")\\\", 2 )\\\
7442 end\\\
7443 if not fs.isDir( _sDir ) then\\\
7444 error( \\\"Not a directory\\\", 2 )\\\
7445 end\\\
7446 sDir = _sDir\\\
7447end\\\
7448\\\
7449function shell.path()\\\
7450 return sPath\\\
7451end\\\
7452\\\
7453function shell.setPath( _sPath )\\\
7454 if type( _sPath ) ~= \\\"string\\\" then\\\
7455 error( \\\"bad argument #1 (expected string, got \\\" .. type( _sPath ) .. \\\")\\\", 2 )\\\
7456 end\\\
7457 sPath = _sPath\\\
7458end\\\
7459\\\
7460function shell.resolve( _sPath )\\\
7461 if type( _sPath ) ~= \\\"string\\\" then\\\
7462 error( \\\"bad argument #1 (expected string, got \\\" .. type( _sPath ) .. \\\")\\\", 2 )\\\
7463 end\\\
7464 local sStartChar = string.sub( _sPath, 1, 1 )\\\
7465 if sStartChar == \\\"/\\\" or sStartChar == \\\"\\\\\\\\\\\" then\\\
7466 return fs.combine( \\\"\\\", _sPath )\\\
7467 else\\\
7468 return fs.combine( sDir, _sPath )\\\
7469 end\\\
7470end\\\
7471\\\
7472local function pathWithExtension( _sPath, _sExt )\\\
7473 local nLen = #sPath\\\
7474 local sEndChar = string.sub( _sPath, nLen, nLen )\\\
7475 -- Remove any trailing slashes so we can add an extension to the path safely\\\
7476 if sEndChar == \\\"/\\\" or sEndChar == \\\"\\\\\\\\\\\" then\\\
7477 _sPath = string.sub( _sPath, 1, nLen - 1 )\\\
7478 end\\\
7479 return _sPath .. \\\".\\\" .. _sExt\\\
7480end\\\
7481\\\
7482function shell.resolveProgram( _sCommand )\\\
7483 if type( _sCommand ) ~= \\\"string\\\" then\\\
7484 error( \\\"bad argument #1 (expected string, got \\\" .. type( _sCommand ) .. \\\")\\\", 2 )\\\
7485 end\\\
7486 -- Substitute aliases firsts\\\
7487 if tAliases[ _sCommand ] ~= nil then\\\
7488 _sCommand = tAliases[ _sCommand ]\\\
7489 end\\\
7490\\\
7491 -- If the path is a global path, use it directly\\\
7492 if _sCommand:find(\\\"/\\\") or _sCommand:find(\\\"\\\\\\\\\\\") then\\\
7493 local sPath = shell.resolve( _sCommand )\\\
7494 if fs.exists( sPath ) and not fs.isDir( sPath ) then\\\
7495 return sPath\\\
7496 else\\\
7497 local sPathLua = pathWithExtension( sPath, \\\"lua\\\" )\\\
7498 if fs.exists( sPathLua ) and not fs.isDir( sPathLua ) then\\\
7499 return sPathLua\\\
7500 end\\\
7501 end\\\
7502 return nil\\\
7503 end\\\
7504\\\
7505 -- Otherwise, look on the path variable\\\
7506 for sPath in string.gmatch(sPath, \\\"[^:]+\\\") do\\\
7507 sPath = fs.combine( shell.resolve( sPath ), _sCommand )\\\
7508 if fs.exists( sPath ) and not fs.isDir( sPath ) then\\\
7509 return sPath\\\
7510 else\\\
7511 local sPathLua = pathWithExtension( sPath, \\\"lua\\\" )\\\
7512 if fs.exists( sPathLua ) and not fs.isDir( sPathLua ) then\\\
7513 return sPathLua\\\
7514 end\\\
7515 end\\\
7516 end\\\
7517\\\
7518 -- Not found\\\
7519 return nil\\\
7520end\\\
7521\\\
7522function shell.programs( _bIncludeHidden )\\\
7523 local tItems = {}\\\
7524\\\
7525 -- Add programs from the path\\\
7526 for sPath in string.gmatch(sPath, \\\"[^:]+\\\") do\\\
7527 sPath = shell.resolve( sPath )\\\
7528 if fs.isDir( sPath ) then\\\
7529 local tList = fs.list( sPath )\\\
7530 for n=1,#tList do\\\
7531 local sFile = tList[n]\\\
7532 if not fs.isDir( fs.combine( sPath, sFile ) ) and\\\
7533 (_bIncludeHidden or string.sub( sFile, 1, 1 ) ~= \\\".\\\") then\\\
7534 if #sFile > 4 and sFile:sub(-4) == \\\".lua\\\" then\\\
7535 sFile = sFile:sub(1,-5)\\\
7536 end\\\
7537 tItems[ sFile ] = true\\\
7538 end\\\
7539 end\\\
7540 end\\\
7541 end\\\
7542\\\
7543 -- Sort and return\\\
7544 local tItemList = {}\\\
7545 for sItem, b in pairs( tItems ) do\\\
7546 table.insert( tItemList, sItem )\\\
7547 end\\\
7548 table.sort( tItemList )\\\
7549 return tItemList\\\
7550end\\\
7551\\\
7552local function completeProgram( sLine )\\\
7553 if #sLine > 0 and (sLine:find(\\\"/\\\") or sLine:find(\\\"\\\\\\\\\\\")) then\\\
7554 -- Add programs from the root\\\
7555 return fs.complete( sLine, sDir, true, false )\\\
7556\\\
7557 else\\\
7558 local tResults = {}\\\
7559 local tSeen = {}\\\
7560\\\
7561 -- Add aliases\\\
7562 for sAlias, sCommand in pairs( tAliases ) do\\\
7563 if #sAlias > #sLine and string.sub( sAlias, 1, #sLine ) == sLine then\\\
7564 local sResult = string.sub( sAlias, #sLine + 1 )\\\
7565 if not tSeen[ sResult ] then\\\
7566 table.insert( tResults, sResult )\\\
7567 tSeen[ sResult ] = true\\\
7568 end\\\
7569 end\\\
7570 end\\\
7571\\\
7572 -- Add all subdirectories. We don't include files as they will be added in the block below\\\
7573 local tDirs = fs.complete( sLine, sDir, false, false )\\\
7574 for i = 1, #tDirs do\\\
7575 local sResult = tDirs[i]\\\
7576 if not tSeen[ sResult ] then\\\
7577 table.insert ( tResults, sResult )\\\
7578 tSeen [ sResult ] = true\\\
7579 end\\\
7580 end\\\
7581\\\
7582 -- Add programs from the path\\\
7583 local tPrograms = shell.programs()\\\
7584 for n=1,#tPrograms do\\\
7585 local sProgram = tPrograms[n]\\\
7586 if #sProgram > #sLine and string.sub( sProgram, 1, #sLine ) == sLine then\\\
7587 local sResult = string.sub( sProgram, #sLine + 1 )\\\
7588 if not tSeen[ sResult ] then\\\
7589 table.insert( tResults, sResult )\\\
7590 tSeen[ sResult ] = true\\\
7591 end\\\
7592 end\\\
7593 end\\\
7594\\\
7595 -- Sort and return\\\
7596 table.sort( tResults )\\\
7597 return tResults\\\
7598 end\\\
7599end\\\
7600\\\
7601local function completeProgramArgument( sProgram, nArgument, sPart, tPreviousParts )\\\
7602 local tInfo = tCompletionInfo[ sProgram ]\\\
7603 if tInfo then\\\
7604 return tInfo.fnComplete( shell, nArgument, sPart, tPreviousParts )\\\
7605 end\\\
7606 return nil\\\
7607end\\\
7608\\\
7609function shell.complete( sLine )\\\
7610 if type( sLine ) ~= \\\"string\\\" then\\\
7611 error( \\\"bad argument #1 (expected string, got \\\" .. type( sLine ) .. \\\")\\\", 2 )\\\
7612 end\\\
7613 if #sLine > 0 then\\\
7614 local tWords = tokenise( sLine )\\\
7615 local nIndex = #tWords\\\
7616 if string.sub( sLine, #sLine, #sLine ) == \\\" \\\" then\\\
7617 nIndex = nIndex + 1\\\
7618 end\\\
7619 if nIndex == 1 then\\\
7620 local sBit = tWords[1] or \\\"\\\"\\\
7621 local sPath = shell.resolveProgram( sBit )\\\
7622 if tCompletionInfo[ sPath ] then\\\
7623 return { \\\" \\\" }\\\
7624 else\\\
7625 local tResults = completeProgram( sBit )\\\
7626 for n=1,#tResults do\\\
7627 local sResult = tResults[n]\\\
7628 local sPath = shell.resolveProgram( sBit .. sResult )\\\
7629 if tCompletionInfo[ sPath ] then\\\
7630 tResults[n] = sResult .. \\\" \\\"\\\
7631 end\\\
7632 end\\\
7633 return tResults\\\
7634 end\\\
7635\\\
7636 elseif nIndex > 1 then\\\
7637 local sPath = shell.resolveProgram( tWords[1] )\\\
7638 local sPart = tWords[nIndex] or \\\"\\\"\\\
7639 local tPreviousParts = tWords\\\
7640 tPreviousParts[nIndex] = nil\\\
7641 return completeProgramArgument( sPath , nIndex - 1, sPart, tPreviousParts )\\\
7642\\\
7643 end\\\
7644 end\\\
7645 return nil\\\
7646end\\\
7647\\\
7648function shell.completeProgram( sProgram )\\\
7649 if type( sProgram ) ~= \\\"string\\\" then\\\
7650 error( \\\"bad argument #1 (expected string, got \\\" .. type( sProgram ) .. \\\")\\\", 2 )\\\
7651 end\\\
7652 return completeProgram( sProgram )\\\
7653end\\\
7654\\\
7655function shell.setCompletionFunction( sProgram, fnComplete )\\\
7656 if type( sProgram ) ~= \\\"string\\\" then\\\
7657 error( \\\"bad argument #1 (expected string, got \\\" .. type( sProgram ) .. \\\")\\\", 2 )\\\
7658 end\\\
7659 if type( fnComplete ) ~= \\\"function\\\" then\\\
7660 error( \\\"bad argument #2 (expected function, got \\\" .. type( fnComplete ) .. \\\")\\\", 2 )\\\
7661 end\\\
7662 tCompletionInfo[ sProgram ] = {\\\
7663 fnComplete = fnComplete\\\
7664 }\\\
7665end\\\
7666\\\
7667function shell.getCompletionInfo()\\\
7668 return tCompletionInfo\\\
7669end\\\
7670\\\
7671function shell.getRunningProgram()\\\
7672 if #tProgramStack > 0 then\\\
7673 return tProgramStack[#tProgramStack]\\\
7674 end\\\
7675 return nil\\\
7676end\\\
7677\\\
7678function shell.setAlias( _sCommand, _sProgram )\\\
7679 if type( _sCommand ) ~= \\\"string\\\" then\\\
7680 error( \\\"bad argument #1 (expected string, got \\\" .. type( _sCommand ) .. \\\")\\\", 2 )\\\
7681 end\\\
7682 if type( _sProgram ) ~= \\\"string\\\" then\\\
7683 error( \\\"bad argument #2 (expected string, got \\\" .. type( _sProgram ) .. \\\")\\\", 2 )\\\
7684 end\\\
7685 tAliases[ _sCommand ] = _sProgram\\\
7686end\\\
7687\\\
7688function shell.clearAlias( _sCommand )\\\
7689 if type( _sCommand ) ~= \\\"string\\\" then\\\
7690 error( \\\"bad argument #1 (expected string, got \\\" .. type( _sCommand ) .. \\\")\\\", 2 )\\\
7691 end\\\
7692 tAliases[ _sCommand ] = nil\\\
7693end\\\
7694\\\
7695function shell.aliases()\\\
7696 -- Copy aliases\\\
7697 local tCopy = {}\\\
7698 for sAlias, sCommand in pairs( tAliases ) do\\\
7699 tCopy[sAlias] = sCommand\\\
7700 end\\\
7701 return tCopy\\\
7702end\\\
7703\\\
7704if multishell then\\\
7705 function shell.openTab( ... )\\\
7706 local tWords = tokenise( ... )\\\
7707 local sCommand = tWords[1]\\\
7708 if sCommand then\\\
7709 local sPath = shell.resolveProgram( sCommand )\\\
7710 if sPath == \\\"rom/programs/shell.lua\\\" then\\\
7711 return multishell.launch( createShellEnv( \\\"rom/programs\\\" ), sPath, table.unpack( tWords, 2 ) )\\\
7712 elseif sPath ~= nil then\\\
7713 return multishell.launch( createShellEnv( \\\"rom/programs\\\" ), \\\"rom/programs/shell.lua\\\", sCommand, table.unpack( tWords, 2 ) )\\\
7714 else\\\
7715 printError( \\\"No such program\\\" )\\\
7716 end\\\
7717 end\\\
7718 end\\\
7719\\\
7720 function shell.switchTab( nID )\\\
7721 if type( nID ) ~= \\\"number\\\" then\\\
7722 error( \\\"bad argument #1 (expected number, got \\\" .. type( nID ) .. \\\")\\\", 2 )\\\
7723 end\\\
7724 multishell.setFocus( nID )\\\
7725 end\\\
7726end\\\
7727\\\
7728local tArgs = { ... }\\\
7729if #tArgs > 0 then\\\
7730 -- \\\"shell x y z\\\"\\\
7731 -- Run the program specified on the commandline\\\
7732 shell.run( ... )\\\
7733\\\
7734else\\\
7735 -- \\\"shell\\\"\\\
7736 -- Print the header\\\
7737 term.setBackgroundColor( bgColour )\\\
7738 term.setTextColour( promptColour )\\\
7739 print( os.version() )\\\
7740 term.setTextColour( textColour )\\\
7741\\\
7742 -- Run the startup program\\\
7743 if parentShell == nil then\\\
7744 shell.run( \\\"/rom/startup.lua\\\" )\\\
7745 end\\\
7746\\\
7747 -- Read commands and execute them\\\
7748 local tCommandHistory = {}\\\
7749 while not bExit do\\\
7750 term.redirect( parentTerm )\\\
7751 term.setBackgroundColor( bgColour )\\\
7752 term.setTextColour( promptColour )\\\
7753 write( shell.dir() .. \\\"> \\\" )\\\
7754 term.setTextColour( textColour )\\\
7755\\\
7756\\\
7757 local sLine\\\
7758 if settings.get( \\\"shell.autocomplete\\\" ) then\\\
7759 sLine = read( nil, tCommandHistory, shell.complete )\\\
7760 else\\\
7761 sLine = read( nil, tCommandHistory )\\\
7762 end\\\
7763 if sLine:match(\\\"%S\\\") and tCommandHistory[#tCommandHistory] ~= sLine then\\\
7764 table.insert( tCommandHistory, sLine )\\\
7765 end\\\
7766 shell.run( sLine )\\\
7767 end\\\
7768end\",\
7769 [ \"help/colors.txt\" ] = \"Functions in the colors api\\\
7770(used for redstone.setBundledOutput):\\\
7771colors.combine( color1, color2, color3, ... )\\\
7772colors.subtract( colors, color1, color2, ... )\\\
7773colors.test( colors, color )\\\
7774colors.rgb8( r, g, b )\\\
7775\\\
7776Color constants in the colors api, in ascending bit order:\\\
7777colors.white, colors.orange, colors.magenta, colors.lightBlue, colors.yellow, colors.lime, colors.pink, colors.gray, colors.lightGray, colors.cyan, colors.purple, colors.blue, colors.brown, colors.green, colors.red, colors.black.\",\
7778 [ \"programs/redstone.lua\" ] = \"\\\
7779local tArgs = { ... }\\\
7780\\\
7781local function printUsage()\\\
7782 print( \\\"Usages:\\\" )\\\
7783 print( \\\"redstone probe\\\" )\\\
7784 print( \\\"redstone set <side> <value>\\\" )\\\
7785 print( \\\"redstone set <side> <color> <value>\\\" )\\\
7786 print( \\\"redstone pulse <side> <count> <period>\\\" )\\\
7787end\\\
7788\\\
7789local sCommand = tArgs[1]\\\
7790if sCommand == \\\"probe\\\" then\\\
7791 -- \\\"redstone probe\\\"\\\
7792 -- Regular input\\\
7793 print( \\\"Redstone inputs: \\\" )\\\
7794\\\
7795 local count = 0\\\
7796 local bundledCount = 0\\\
7797 for n,sSide in ipairs( redstone.getSides() ) do\\\
7798 if redstone.getBundledInput( sSide ) > 0 then\\\
7799 bundledCount = bundledCount + 1\\\
7800 end\\\
7801 if redstone.getInput( sSide ) then\\\
7802 if count > 0 then\\\
7803 io.write( \\\", \\\" )\\\
7804 end\\\
7805 io.write( sSide )\\\
7806 count = count + 1\\\
7807 end\\\
7808 end\\\
7809 if count > 0 then\\\
7810 print( \\\".\\\" )\\\
7811 else\\\
7812 print( \\\"None.\\\" )\\\
7813 end\\\
7814\\\
7815 -- Bundled input\\\
7816 if bundledCount > 0 then\\\
7817 print()\\\
7818 print( \\\"Bundled inputs:\\\" )\\\
7819 for i,sSide in ipairs( redstone.getSides() ) do\\\
7820 local nInput = redstone.getBundledInput( sSide )\\\
7821 if nInput ~= 0 then\\\
7822 write( sSide..\\\": \\\" )\\\
7823 local count = 0\\\
7824 for sColour,nColour in pairs( colors ) do\\\
7825 if type( nColour ) == \\\"number\\\" and colors.test( nInput, nColour ) then\\\
7826 if count > 0 then\\\
7827 write( \\\", \\\" )\\\
7828 end\\\
7829 if term.isColour() then\\\
7830 term.setTextColour( nColour )\\\
7831 end\\\
7832 write( sColour )\\\
7833 if term.isColour() then\\\
7834 term.setTextColour( colours.white )\\\
7835 end\\\
7836 count = count + 1\\\
7837 end\\\
7838 end\\\
7839 print( \\\".\\\" )\\\
7840 end\\\
7841 end\\\
7842 end\\\
7843\\\
7844elseif sCommand == \\\"pulse\\\" then\\\
7845 -- \\\"redstone pulse\\\"\\\
7846 local sSide = tArgs[2]\\\
7847 local nCount = tonumber( tArgs[3] ) or 1\\\
7848 local nPeriod = tonumber( tArgs[4] ) or 0.5\\\
7849 for n=1,nCount do\\\
7850 redstone.setOutput( sSide, true )\\\
7851 sleep( nPeriod / 2 )\\\
7852 redstone.setOutput( sSide, false )\\\
7853 sleep( nPeriod / 2 )\\\
7854 end\\\
7855\\\
7856elseif sCommand == \\\"set\\\" then\\\
7857 -- \\\"redstone set\\\"\\\
7858 local sSide = tArgs[2]\\\
7859 if #tArgs > 3 then\\\
7860 -- Bundled cable output\\\
7861 local sColour = tArgs[3]\\\
7862 local nColour = colors[sColour] or colours[sColour]\\\
7863 if type(nColour) ~= \\\"number\\\" then\\\
7864 printError( \\\"No such color\\\" )\\\
7865 return\\\
7866 end\\\
7867\\\
7868 local sValue = tArgs[4]\\\
7869 if sValue == \\\"true\\\" then\\\
7870 rs.setBundledOutput( sSide, colors.combine( rs.getBundledOutput( sSide ), nColour ) )\\\
7871 elseif sValue == \\\"false\\\" then\\\
7872 rs.setBundledOutput( sSide, colors.subtract( rs.getBundledOutput( sSide ), nColour ) )\\\
7873 else\\\
7874 print( \\\"Value must be boolean\\\" )\\\
7875 end\\\
7876 else\\\
7877 -- Regular output\\\
7878 local sValue = tArgs[3]\\\
7879 local nValue = tonumber(sValue)\\\
7880 if sValue == \\\"true\\\" then\\\
7881 rs.setOutput( sSide, true )\\\
7882 elseif sValue == \\\"false\\\" then\\\
7883 rs.setOutput( sSide, false )\\\
7884 elseif nValue and nValue >= 0 and nValue <= 15 then\\\
7885 rs.setAnalogOutput( sSide, nValue )\\\
7886 else\\\
7887 print( \\\"Value must be boolean or 0-15\\\" )\\\
7888 end\\\
7889 end\\\
7890\\\
7891else\\\
7892 -- Something else\\\
7893 printUsage()\\\
7894\\\
7895end\",\
7896 [ \"programs/rednet/repeat.lua\" ] = \"\\\
7897-- Find modems\\\
7898local tModems = {}\\\
7899for n,sModem in ipairs( peripheral.getNames() ) do\\\
7900 if peripheral.getType( sModem ) == \\\"modem\\\" then\\\
7901 table.insert( tModems, sModem )\\\
7902 end\\\
7903end\\\
7904if #tModems == 0 then\\\
7905 print( \\\"No modems found.\\\" )\\\
7906 return\\\
7907elseif #tModems == 1 then\\\
7908 print( \\\"1 modem found.\\\" )\\\
7909else\\\
7910 print( #tModems .. \\\" modems found.\\\" )\\\
7911end\\\
7912\\\
7913local function open( nChannel )\\\
7914 for n=1,#tModems do\\\
7915 local sModem = tModems[n]\\\
7916 peripheral.call( sModem, \\\"open\\\", nChannel )\\\
7917 end\\\
7918end\\\
7919\\\
7920local function close( nChannel )\\\
7921 for n=1,#tModems do\\\
7922 local sModem = tModems[n]\\\
7923 peripheral.call( sModem, \\\"close\\\", nChannel )\\\
7924 end\\\
7925end\\\
7926\\\
7927-- Open channels\\\
7928print( \\\"0 messages repeated.\\\" )\\\
7929open( rednet.CHANNEL_REPEAT )\\\
7930\\\
7931-- Main loop (terminate to break)\\\
7932local ok, error = pcall( function()\\\
7933 local tReceivedMessages = {}\\\
7934 local tReceivedMessageTimeouts = {}\\\
7935 local nTransmittedMessages = 0\\\
7936\\\
7937 while true do\\\
7938 local sEvent, sModem, nChannel, nReplyChannel, tMessage = os.pullEvent()\\\
7939 if sEvent == \\\"modem_message\\\" then\\\
7940 -- Got a modem message, rebroadcast it if it's a rednet thing\\\
7941 if nChannel == rednet.CHANNEL_REPEAT then\\\
7942 if type( tMessage ) == \\\"table\\\" and tMessage.nMessageID and tMessage.nRecipient and type(tMessage.nRecipient) == \\\"number\\\" then\\\
7943 if not tReceivedMessages[ tMessage.nMessageID ] then\\\
7944 -- Ensure we only repeat a message once\\\
7945 tReceivedMessages[ tMessage.nMessageID ] = true\\\
7946 tReceivedMessageTimeouts[ os.startTimer( 30 ) ] = tMessage.nMessageID\\\
7947\\\
7948 -- Send on all other open modems, to the target and to other repeaters\\\
7949 for n=1,#tModems do\\\
7950 local sOtherModem = tModems[n]\\\
7951 peripheral.call( sOtherModem, \\\"transmit\\\", rednet.CHANNEL_REPEAT, nReplyChannel, tMessage )\\\
7952 peripheral.call( sOtherModem, \\\"transmit\\\", tMessage.nRecipient, nReplyChannel, tMessage )\\\
7953 end\\\
7954\\\
7955 -- Log the event\\\
7956 nTransmittedMessages = nTransmittedMessages + 1\\\
7957 local x,y = term.getCursorPos()\\\
7958 term.setCursorPos( 1, y - 1 )\\\
7959 term.clearLine()\\\
7960 if nTransmittedMessages == 1 then\\\
7961 print( nTransmittedMessages .. \\\" message repeated.\\\" )\\\
7962 else\\\
7963 print( nTransmittedMessages .. \\\" messages repeated.\\\" )\\\
7964 end\\\
7965 end\\\
7966 end\\\
7967 end\\\
7968\\\
7969 elseif sEvent == \\\"timer\\\" then\\\
7970 -- Got a timer event, use it to clear the message history\\\
7971 local nTimer = sModem\\\
7972 local nMessageID = tReceivedMessageTimeouts[ nTimer ]\\\
7973 if nMessageID then\\\
7974 tReceivedMessageTimeouts[ nTimer ] = nil\\\
7975 tReceivedMessages[ nMessageID ] = nil\\\
7976 end\\\
7977\\\
7978 end\\\
7979 end\\\
7980end )\\\
7981if not ok then\\\
7982 printError( error )\\\
7983end\\\
7984\\\
7985-- Close channels\\\
7986close( rednet.CHANNEL_REPEAT )\",\
7987 [ \"help/excavate.txt\" ] = \"excavate is a program for Mining Turtles. When excavate is run, the turtle will mine a rectangular shaft into the ground, collecting blocks as it goes, and return to the surface once bedrock is hit.\\\
7988\\\
7989ex:\\\
7990\\\"excavate 3\\\" will mine a 3x3 shaft.\",\
7991 [ \"programs/rednet/chat.lua\" ] = \"\\\
7992local tArgs = { ... }\\\
7993\\\
7994local function printUsage()\\\
7995 print( \\\"Usages:\\\" )\\\
7996 print( \\\"chat host <hostname>\\\" )\\\
7997 print( \\\"chat join <hostname> <nickname>\\\" )\\\
7998end\\\
7999\\\
8000local sOpenedModem = nil\\\
8001local function openModem()\\\
8002 for n,sModem in ipairs( peripheral.getNames() ) do\\\
8003 if peripheral.getType( sModem ) == \\\"modem\\\" then\\\
8004 if not rednet.isOpen( sModem ) then\\\
8005 rednet.open( sModem )\\\
8006 sOpenedModem = sModem\\\
8007 end\\\
8008 return true\\\
8009 end\\\
8010 end\\\
8011 print( \\\"No modems found.\\\" )\\\
8012 return false\\\
8013end\\\
8014\\\
8015local function closeModem()\\\
8016 if sOpenedModem ~= nil then\\\
8017 rednet.close( sOpenedModem )\\\
8018 sOpenedModem = nil\\\
8019 end\\\
8020end\\\
8021\\\
8022-- Colours\\\
8023local highlightColour, textColour\\\
8024if term.isColour() then\\\
8025 textColour = colours.white\\\
8026 highlightColour = colours.yellow\\\
8027else\\\
8028 textColour = colours.white\\\
8029 highlightColour = colours.white\\\
8030end\\\
8031\\\
8032local sCommand = tArgs[1]\\\
8033if sCommand == \\\"host\\\" then\\\
8034 -- \\\"chat host\\\"\\\
8035 -- Get hostname\\\
8036 local sHostname = tArgs[2]\\\
8037 if sHostname == nil then\\\
8038 printUsage()\\\
8039 return\\\
8040 end\\\
8041\\\
8042 -- Host server\\\
8043 if not openModem() then\\\
8044 return\\\
8045 end\\\
8046 rednet.host( \\\"chat\\\", sHostname )\\\
8047 print( \\\"0 users connected.\\\" )\\\
8048\\\
8049 local tUsers = {}\\\
8050 local nUsers = 0\\\
8051 local function send( sText, nUserID )\\\
8052 if nUserID then\\\
8053 local tUser = tUsers[ nUserID ]\\\
8054 if tUser then\\\
8055 rednet.send( tUser.nID, {\\\
8056 sType = \\\"text\\\",\\\
8057 nUserID = nUserID,\\\
8058 sText = sText,\\\
8059 }, \\\"chat\\\" )\\\
8060 end\\\
8061 else\\\
8062 for nUserID, tUser in pairs( tUsers ) do\\\
8063 rednet.send( tUser.nID, {\\\
8064 sType = \\\"text\\\",\\\
8065 nUserID = nUserID,\\\
8066 sText = sText,\\\
8067 }, \\\"chat\\\" )\\\
8068 end\\\
8069 end\\\
8070 end\\\
8071\\\
8072 -- Setup ping pong\\\
8073 local tPingPongTimer = {}\\\
8074 local function ping( nUserID )\\\
8075 local tUser = tUsers[ nUserID ]\\\
8076 rednet.send( tUser.nID, {\\\
8077 sType = \\\"ping to client\\\",\\\
8078 nUserID = nUserID,\\\
8079 }, \\\"chat\\\" )\\\
8080\\\
8081 local timer = os.startTimer( 15 )\\\
8082 tUser.bPingPonged = false\\\
8083 tPingPongTimer[ timer ] = nUserID\\\
8084 end\\\
8085\\\
8086 local function printUsers()\\\
8087 local x,y = term.getCursorPos()\\\
8088 term.setCursorPos( 1, y - 1 )\\\
8089 term.clearLine()\\\
8090 if nUsers == 1 then\\\
8091 print( nUsers .. \\\" user connected.\\\" )\\\
8092 else\\\
8093 print( nUsers .. \\\" users connected.\\\" )\\\
8094 end\\\
8095 end\\\
8096\\\
8097 -- Handle messages\\\
8098 local ok, error = pcall( function()\\\
8099 parallel.waitForAny( function()\\\
8100 while true do\\\
8101 local sEvent, timer = os.pullEvent( \\\"timer\\\" )\\\
8102 local nUserID = tPingPongTimer[ timer ]\\\
8103 if nUserID and tUsers[ nUserID ] then\\\
8104 local tUser = tUsers[ nUserID ]\\\
8105 if tUser then\\\
8106 if not tUser.bPingPonged then\\\
8107 send( \\\"* \\\"..tUser.sUsername..\\\" has timed out\\\" )\\\
8108 tUsers[ nUserID ] = nil\\\
8109 nUsers = nUsers - 1\\\
8110 printUsers()\\\
8111 else\\\
8112 ping( nUserID )\\\
8113 end\\\
8114 end\\\
8115 end\\\
8116 end\\\
8117 end,\\\
8118 function()\\\
8119 while true do\\\
8120 local tCommands\\\
8121 tCommands = {\\\
8122 [\\\"me\\\"] = function( tUser, sContent )\\\
8123 if string.len(sContent) > 0 then\\\
8124 send( \\\"* \\\"..tUser.sUsername..\\\" \\\"..sContent )\\\
8125 else\\\
8126 send( \\\"* Usage: /me [words]\\\", tUser.nUserID )\\\
8127 end\\\
8128 end,\\\
8129 [\\\"nick\\\"] = function( tUser, sContent )\\\
8130 if string.len(sContent) > 0 then\\\
8131 local sOldName = tUser.sUsername\\\
8132 tUser.sUsername = sContent\\\
8133 send( \\\"* \\\"..sOldName..\\\" is now known as \\\"..tUser.sUsername )\\\
8134 else\\\
8135 send( \\\"* Usage: /nick [nickname]\\\", tUser.nUserID )\\\
8136 end\\\
8137 end,\\\
8138 [\\\"users\\\"] = function( tUser, sContent )\\\
8139 send( \\\"* Connected Users:\\\", tUser.nUserID )\\\
8140 local sUsers = \\\"*\\\"\\\
8141 for nUserID, tUser in pairs( tUsers ) do\\\
8142 sUsers = sUsers .. \\\" \\\" .. tUser.sUsername\\\
8143 end\\\
8144 send( sUsers, tUser.nUserID )\\\
8145 end,\\\
8146 [\\\"help\\\"] = function( tUser, sContent )\\\
8147 send( \\\"* Available commands:\\\", tUser.nUserID )\\\
8148 local sCommands = \\\"*\\\"\\\
8149 for sCommand, fnCommand in pairs( tCommands ) do\\\
8150 sCommands = sCommands .. \\\" /\\\" .. sCommand\\\
8151 end\\\
8152 send( sCommands..\\\" /logout\\\", tUser.nUserID )\\\
8153 end,\\\
8154 }\\\
8155\\\
8156 local nSenderID, tMessage = rednet.receive( \\\"chat\\\" )\\\
8157 if type( tMessage ) == \\\"table\\\" then\\\
8158 if tMessage.sType == \\\"login\\\" then\\\
8159 -- Login from new client\\\
8160 local nUserID = tMessage.nUserID\\\
8161 local sUsername = tMessage.sUsername\\\
8162 if nUserID and sUsername then\\\
8163 tUsers[ nUserID ] = {\\\
8164 nID = nSenderID,\\\
8165 nUserID = nUserID,\\\
8166 sUsername = sUsername,\\\
8167 }\\\
8168 nUsers = nUsers + 1\\\
8169 printUsers()\\\
8170 send( \\\"* \\\"..sUsername..\\\" has joined the chat\\\" )\\\
8171 ping( nUserID )\\\
8172 end\\\
8173\\\
8174 else\\\
8175 -- Something else from existing client\\\
8176 local nUserID = tMessage.nUserID\\\
8177 local tUser = tUsers[ nUserID ]\\\
8178 if tUser and tUser.nID == nSenderID then\\\
8179 if tMessage.sType == \\\"logout\\\" then\\\
8180 send( \\\"* \\\"..tUser.sUsername..\\\" has left the chat\\\" )\\\
8181 tUsers[ nUserID ] = nil\\\
8182 nUsers = nUsers - 1\\\
8183 printUsers()\\\
8184\\\
8185 elseif tMessage.sType == \\\"chat\\\" then\\\
8186 local sMessage = tMessage.sText\\\
8187 if sMessage then\\\
8188 local sCommand = string.match( sMessage, \\\"^/([a-z]+)\\\" )\\\
8189 if sCommand then\\\
8190 local fnCommand = tCommands[ sCommand ]\\\
8191 if fnCommand then\\\
8192 local sContent = string.sub( sMessage, string.len(sCommand)+3 )\\\
8193 fnCommand( tUser, sContent )\\\
8194 else\\\
8195 send( \\\"* Unrecognised command: /\\\"..sCommand, tUser.nUserID )\\\
8196 end\\\
8197 else\\\
8198 send( \\\"<\\\"..tUser.sUsername..\\\"> \\\"..tMessage.sText )\\\
8199 end\\\
8200 end\\\
8201\\\
8202 elseif tMessage.sType == \\\"ping to server\\\" then\\\
8203 rednet.send( tUser.nID, {\\\
8204 sType = \\\"pong to client\\\",\\\
8205 nUserID = nUserID,\\\
8206 }, \\\"chat\\\" )\\\
8207\\\
8208 elseif tMessage.sType == \\\"pong to server\\\" then\\\
8209 tUser.bPingPonged = true\\\
8210\\\
8211 end\\\
8212 end\\\
8213 end\\\
8214 end\\\
8215 end\\\
8216 end )\\\
8217 end )\\\
8218 if not ok then\\\
8219 printError( error )\\\
8220 end\\\
8221\\\
8222 -- Unhost server\\\
8223 for nUserID, tUser in pairs( tUsers ) do\\\
8224 rednet.send( tUser.nID, {\\\
8225 sType = \\\"kick\\\",\\\
8226 nUserID = nUserID,\\\
8227 }, \\\"chat\\\" )\\\
8228 end\\\
8229 rednet.unhost( \\\"chat\\\" )\\\
8230 closeModem()\\\
8231\\\
8232elseif sCommand == \\\"join\\\" then\\\
8233 -- \\\"chat join\\\"\\\
8234 -- Get hostname and username\\\
8235 local sHostname = tArgs[2]\\\
8236 local sUsername = tArgs[3]\\\
8237 if sHostname == nil or sUsername == nil then\\\
8238 printUsage()\\\
8239 return\\\
8240 end\\\
8241\\\
8242 -- Connect\\\
8243 if not openModem() then\\\
8244 return\\\
8245 end\\\
8246 write( \\\"Looking up \\\" .. sHostname .. \\\"... \\\" )\\\
8247 local nHostID = rednet.lookup( \\\"chat\\\", sHostname )\\\
8248 if nHostID == nil then\\\
8249 print( \\\"Failed.\\\" )\\\
8250 return\\\
8251 else\\\
8252 print( \\\"Success.\\\" )\\\
8253 end\\\
8254\\\
8255 -- Login\\\
8256 local nUserID = math.random( 1, 2147483647 )\\\
8257 rednet.send( nHostID, {\\\
8258 sType = \\\"login\\\",\\\
8259 nUserID = nUserID,\\\
8260 sUsername = sUsername,\\\
8261 }, \\\"chat\\\" )\\\
8262\\\
8263 -- Setup ping pong\\\
8264 local bPingPonged = true\\\
8265 local pingPongTimer = os.startTimer( 0 )\\\
8266\\\
8267 local function ping()\\\
8268 rednet.send( nHostID, {\\\
8269 sType = \\\"ping to server\\\",\\\
8270 nUserID = nUserID,\\\
8271 }, \\\"chat\\\" )\\\
8272 bPingPonged = false\\\
8273 pingPongTimer = os.startTimer( 15 )\\\
8274 end\\\
8275\\\
8276 -- Handle messages\\\
8277 local w,h = term.getSize()\\\
8278 local parentTerm = term.current()\\\
8279 local titleWindow = window.create( parentTerm, 1, 1, w, 1, true )\\\
8280 local historyWindow = window.create( parentTerm, 1, 2, w, h-2, true )\\\
8281 local promptWindow = window.create( parentTerm, 1, h, w, 1, true )\\\
8282 historyWindow.setCursorPos( 1, h-2 )\\\
8283\\\
8284 term.clear()\\\
8285 term.setTextColour( textColour )\\\
8286 term.redirect( promptWindow )\\\
8287 promptWindow.restoreCursor()\\\
8288\\\
8289 local function drawTitle()\\\
8290 local x,y = titleWindow.getCursorPos()\\\
8291 local w,h = titleWindow.getSize()\\\
8292 local sTitle = sUsername..\\\" on \\\"..sHostname\\\
8293 titleWindow.setTextColour( highlightColour )\\\
8294 titleWindow.setCursorPos( math.floor( w/2 - string.len(sTitle)/2 ), 1 )\\\
8295 titleWindow.clearLine()\\\
8296 titleWindow.write( sTitle )\\\
8297 promptWindow.restoreCursor()\\\
8298 end\\\
8299\\\
8300 local function printMessage( sMessage )\\\
8301 term.redirect( historyWindow )\\\
8302 print()\\\
8303 if string.match( sMessage, \\\"^%*\\\" ) then\\\
8304 -- Information\\\
8305 term.setTextColour( highlightColour )\\\
8306 write( sMessage )\\\
8307 term.setTextColour( textColour )\\\
8308 else\\\
8309 -- Chat\\\
8310 local sUsernameBit = string.match( sMessage, \\\"^<[^>]*>\\\" )\\\
8311 if sUsernameBit then\\\
8312 term.setTextColour( highlightColour )\\\
8313 write( sUsernameBit )\\\
8314 term.setTextColour( textColour )\\\
8315 write( string.sub( sMessage, string.len( sUsernameBit ) + 1 ) )\\\
8316 else\\\
8317 write( sMessage )\\\
8318 end\\\
8319 end\\\
8320 term.redirect( promptWindow )\\\
8321 promptWindow.restoreCursor()\\\
8322 end\\\
8323\\\
8324 drawTitle()\\\
8325\\\
8326 local ok, error = pcall( function()\\\
8327 parallel.waitForAny( function()\\\
8328 while true do\\\
8329 local sEvent, timer = os.pullEvent()\\\
8330 if sEvent == \\\"timer\\\" then\\\
8331 if timer == pingPongTimer then\\\
8332 if not bPingPonged then\\\
8333 printMessage( \\\"Server timeout.\\\" )\\\
8334 return\\\
8335 else\\\
8336 ping()\\\
8337 end\\\
8338 end\\\
8339\\\
8340 elseif sEvent == \\\"term_resize\\\" then\\\
8341 local w,h = parentTerm.getSize()\\\
8342 titleWindow.reposition( 1, 1, w, 1 )\\\
8343 historyWindow.reposition( 1, 2, w, h-2 )\\\
8344 promptWindow.reposition( 1, h, w, 1 )\\\
8345\\\
8346 end\\\
8347 end\\\
8348 end,\\\
8349 function()\\\
8350 while true do\\\
8351 local nSenderID, tMessage = rednet.receive( \\\"chat\\\" )\\\
8352 if nSenderID == nHostID and type( tMessage ) == \\\"table\\\" and tMessage.nUserID == nUserID then\\\
8353 if tMessage.sType == \\\"text\\\" then\\\
8354 local sText = tMessage.sText\\\
8355 if sText then\\\
8356 printMessage( sText )\\\
8357 end\\\
8358\\\
8359 elseif tMessage.sType == \\\"ping to client\\\" then\\\
8360 rednet.send( nSenderID, {\\\
8361 sType = \\\"pong to server\\\",\\\
8362 nUserID = nUserID,\\\
8363 }, \\\"chat\\\" )\\\
8364\\\
8365 elseif tMessage.sType == \\\"pong to client\\\" then\\\
8366 bPingPonged = true\\\
8367\\\
8368 elseif tMessage.sType == \\\"kick\\\" then\\\
8369 return\\\
8370\\\
8371 end\\\
8372 end\\\
8373 end\\\
8374 end,\\\
8375 function()\\\
8376 local tSendHistory = {}\\\
8377 while true do\\\
8378 promptWindow.setCursorPos( 1,1 )\\\
8379 promptWindow.clearLine()\\\
8380 promptWindow.setTextColor( highlightColour )\\\
8381 promptWindow.write( \\\": \\\")\\\
8382 promptWindow.setTextColor( textColour )\\\
8383\\\
8384 local sChat = read( nil, tSendHistory )\\\
8385 if string.match( sChat, \\\"^/logout\\\" ) then\\\
8386 break\\\
8387 else\\\
8388 rednet.send( nHostID, {\\\
8389 sType = \\\"chat\\\",\\\
8390 nUserID = nUserID,\\\
8391 sText = sChat,\\\
8392 }, \\\"chat\\\" )\\\
8393 table.insert( tSendHistory, sChat )\\\
8394 end\\\
8395 end\\\
8396 end )\\\
8397 end )\\\
8398\\\
8399 -- Close the windows\\\
8400 term.redirect( parentTerm )\\\
8401\\\
8402 -- Print error notice\\\
8403 local w,h = term.getSize()\\\
8404 term.setCursorPos( 1, h )\\\
8405 term.clearLine()\\\
8406 term.setCursorBlink( false )\\\
8407 if not ok then\\\
8408 printError( error )\\\
8409 end\\\
8410\\\
8411 -- Logout\\\
8412 rednet.send( nHostID, {\\\
8413 sType = \\\"logout\\\",\\\
8414 nUserID = nUserID,\\\
8415 }, \\\"chat\\\" )\\\
8416 closeModem()\\\
8417\\\
8418 -- Print disconnection notice\\\
8419 print( \\\"Disconnected.\\\" )\\\
8420\\\
8421else\\\
8422 -- \\\"chat somethingelse\\\"\\\
8423 printUsage()\\\
8424\\\
8425end\",\
8426 [ \"programs/reboot.lua\" ] = \"if term.isColour() then\\\
8427 term.setTextColour( colours.yellow )\\\
8428end\\\
8429print( \\\"Goodbye\\\" )\\\
8430term.setTextColour( colours.white )\\\
8431\\\
8432sleep( 1 )\\\
8433os.reboot()\",\
8434 [ \"help/refuel.txt\" ] = \"refuel is a program for Turtles. Refuel will consume items from the inventory as fuel for turtle.\\\
8435\\\
8436ex:\\\
8437\\\"refuel\\\" will refuel with at most one fuel item\\\
8438\\\"refuel 10\\\" will refuel with at most 10 fuel items\\\
8439\\\"refuel all\\\" will refuel with as many fuel items as possible\",\
8440 [ \"programs/programs.lua\" ] = \"\\\
8441local bAll = false\\\
8442local tArgs = { ... }\\\
8443if #tArgs > 0 and tArgs[1] == \\\"all\\\" then\\\
8444 bAll = true\\\
8445end\\\
8446\\\
8447local tPrograms = shell.programs( bAll )\\\
8448textutils.pagedTabulate( tPrograms )\",\
8449 [ \"help/redirection.txt\" ] = \"Redirection ComputerCraft Edition is the CraftOS version of a fun new puzzle game by Dan200, the author of ComputerCraft.\\\
8450Play it on any Advanced Computer, then visit http://www.redirectiongame.com to play the full game!\",\
8451 [ \"programs/pocket/unequip.lua\" ] = \"local ok, err = pcall( pocket.unequipBack )\\\
8452if not ok then\\\
8453 printError( \\\"Nothing to unequip\\\" )\\\
8454else\\\
8455 print( \\\"Item unequipped\\\" )\\\
8456end\",\
8457 [ \"programs/emu.lua\" ] = \"local args = { ... }\\\
8458\\\
8459if ccemux then\\\
8460 local function help()\\\
8461 print(\\\"Usages:\\\")\\\
8462 print(\\\"emu close - close this computer\\\")\\\
8463 print(\\\"emu open [id] - open another computer\\\")\\\
8464 print(\\\"emu data - opens the data folder\\\")\\\
8465 print(\\\"emu config - opens the config editor\\\")\\\
8466 --print(\\\"emu set <setting> <values> - edits a setting\\\")\\\
8467 --print(\\\"emu list settings - list editable settings\\\")\\\
8468 --print(\\\"emu save - saves current settings\\\")\\\
8469 print(\\\"Run 'help emu' for additional information\\\")\\\
8470 end\\\
8471\\\
8472 if #args == 0 then\\\
8473 help()\\\
8474 else\\\
8475 if args[1] == \\\"close\\\" then\\\
8476 ccemux.closeEmu()\\\
8477 elseif args[1] == \\\"open\\\" then\\\
8478 print(\\\"Opened computer ID \\\" .. ccemux.openEmu(tonumber(args[2])))\\\
8479 elseif args[1] == \\\"data\\\" then\\\
8480 if ccemux.openDataDir() then\\\
8481 print(\\\"Opened data folder\\\")\\\
8482 else\\\
8483 print(\\\"Unable to open data folder\\\")\\\
8484 end\\\
8485 elseif args[1] == \\\"config\\\" then\\\
8486 local ok, err = ccemux.openConfig()\\\
8487 if ok then\\\
8488 print(\\\"Opened config editor\\\")\\\
8489 else\\\
8490 print(err)\\\
8491 end\\\
8492 elseif args[1] == \\\"set\\\" then\\\
8493 if #args <= 1 then\\\
8494 help()\\\
8495 else\\\
8496 if args[2] == \\\"resolution\\\" then\\\
8497 if #args == 4 then\\\
8498 ccemux.setResolution(tonumber(args[3]), tonumber(args[4]))\\\
8499 print(\\\"Set resolution to \\\" .. args[3] .. \\\"x\\\" .. args[4])\\\
8500 elseif #args == 3 then\\\
8501 if args[3] == \\\"computer\\\" then\\\
8502 ccemux.setResolution(51, 19)\\\
8503 print(\\\"Set resolution to computer (51x19)\\\")\\\
8504 elseif args[3] == \\\"pocket\\\" then\\\
8505 ccemux.setResolution(26, 20)\\\
8506 print(\\\"Set resolution to pocket (26x20)\\\")\\\
8507 elseif args[3] == \\\"turtle\\\" then\\\
8508 ccemux.setResolution(39, 13)\\\
8509 print(\\\"Set resolution to turtle (39x13)\\\")\\\
8510 end\\\
8511 else\\\
8512 printError(\\\"Usage: emu set resolution <width> <height>\\\")\\\
8513 end\\\
8514 --elseif args[2] == \\\"scale\\\" then\\\
8515\\\
8516 elseif args[2] == \\\"cursor\\\" then\\\
8517 ccemux.setCursorChar(args[3])\\\
8518 print(\\\"Set cursor char to \\\" .. args[3])\\\
8519 else\\\
8520 printError(\\\"Unrecognized setting: \\\" .. args[2])\\\
8521 end\\\
8522 end\\\
8523 elseif args[1] == \\\"list\\\" then\\\
8524 if args[2] == \\\"settings\\\" then\\\
8525 print(\\\"Editable settings:\\\")\\\
8526 print(\\\"resolution <width> <height>\\\")\\\
8527 -- not yet implemented\\\
8528 --print(\\\"scale <pixels>\\\")\\\
8529 print(\\\"cursor <char>\\\")\\\
8530 else\\\
8531 printError(\\\"Unrecognized subcommand: \\\" .. args[2])\\\
8532 end\\\
8533 elseif args[1] == \\\"save\\\" then\\\
8534 ccemux.saveSettings()\\\
8535 print(\\\"Saved settings\\\")\\\
8536 else\\\
8537 printError(\\\"Unrecognized subcommand: \\\" .. args[1])\\\
8538 help()\\\
8539 end\\\
8540 end\\\
8541else\\\
8542 printError(\\\"CCEmuX API is disabled or unavailable.\\\")\\\
8543end\",\
8544 [ \"programs/fun/advanced/levels/10.dat\" ] = \"5\\\
8545 777 77777\\\
8546 727777778837\\\
8547 788888878787\\\
8548 787777888887\\\
854977877778777777\\\
85507e8b7888b888e7\\\
85517787787b777877\\\
8552 777887887887\\\
8553 7487807487\\\
8554 7777777777\",\
8555 [ \"programs/monitor.lua\" ] = \"local function printUsage()\\\
8556 print( \\\"Usage: monitor <name> <program> <arguments>\\\" )\\\
8557 return\\\
8558end\\\
8559\\\
8560local tArgs = { ... }\\\
8561if #tArgs < 2 then\\\
8562 printUsage()\\\
8563 return\\\
8564end\\\
8565\\\
8566local sName = tArgs[1]\\\
8567if peripheral.getType( sName ) ~= \\\"monitor\\\" then\\\
8568 print( \\\"No monitor named \\\".. sName )\\\
8569 return\\\
8570end\\\
8571\\\
8572local sProgram = tArgs[2]\\\
8573local sPath = shell.resolveProgram( sProgram )\\\
8574if sPath == nil then\\\
8575 print( \\\"No such program: \\\"..sProgram )\\\
8576 return\\\
8577end\\\
8578\\\
8579print( \\\"Running \\\"..sProgram..\\\" on monitor \\\"..sName )\\\
8580\\\
8581local monitor = peripheral.wrap( sName )\\\
8582local previousTerm = term.redirect( monitor )\\\
8583\\\
8584local co = coroutine.create( function()\\\
8585 shell.run( sProgram, table.unpack( tArgs, 3 ) )\\\
8586end )\\\
8587\\\
8588local function resume( ... )\\\
8589 local ok, param = coroutine.resume( co, ... )\\\
8590 if not ok then\\\
8591 printError( param )\\\
8592 end\\\
8593 return param\\\
8594end\\\
8595\\\
8596local ok, param = pcall( function()\\\
8597 local sFilter = resume()\\\
8598 while coroutine.status( co ) ~= \\\"dead\\\" do\\\
8599 local tEvent = table.pack( os.pullEventRaw() )\\\
8600 if sFilter == nil or tEvent[1] == sFilter or tEvent[1] == \\\"terminate\\\" then\\\
8601 sFilter = resume( table.unpack( tEvent, 1, tEvent.n ) )\\\
8602 end\\\
8603 if coroutine.status( co ) ~= \\\"dead\\\" and (sFilter == nil or sFilter == \\\"mouse_click\\\") then\\\
8604 if tEvent[1] == \\\"monitor_touch\\\" and tEvent[2] == sName then\\\
8605 sFilter = resume( \\\"mouse_click\\\", 1, table.unpack( tEvent, 3, tEvent.n ) )\\\
8606 end\\\
8607 end\\\
8608 if coroutine.status( co ) ~= \\\"dead\\\" and (sFilter == nil or sFilter == \\\"term_resize\\\") then\\\
8609 if tEvent[1] == \\\"monitor_resize\\\" and tEvent[2] == sName then\\\
8610 sFilter = resume( \\\"term_resize\\\" )\\\
8611 end\\\
8612 end\\\
8613 end\\\
8614end )\\\
8615\\\
8616term.redirect( previousTerm )\\\
8617if not ok then\\\
8618 printError( param )\\\
8619end\",\
8620 [ \"apis/term.lua\" ] = \"\\\
8621local native = (term.native and term.native()) or term\\\
8622local redirectTarget = native\\\
8623\\\
8624local function wrap( _sFunction )\\\
8625 return function( ... )\\\
8626 return redirectTarget[ _sFunction ]( ... )\\\
8627 end\\\
8628end\\\
8629\\\
8630local term = {}\\\
8631\\\
8632term.redirect = function( target )\\\
8633 if type( target ) ~= \\\"table\\\" then\\\
8634 error( \\\"bad argument #1 (expected table, got \\\" .. type( target ) .. \\\")\\\", 2 )\\\
8635 end\\\
8636 if target == term then\\\
8637 error( \\\"term is not a recommended redirect target, try term.current() instead\\\", 2 )\\\
8638 end\\\
8639 for k,v in pairs( native ) do\\\
8640 if type( k ) == \\\"string\\\" and type( v ) == \\\"function\\\" then\\\
8641 if type( target[k] ) ~= \\\"function\\\" then\\\
8642 target[k] = function()\\\
8643 error( \\\"Redirect object is missing method \\\"..k..\\\".\\\", 2 )\\\
8644 end\\\
8645 end\\\
8646 end\\\
8647 end\\\
8648 local oldRedirectTarget = redirectTarget\\\
8649 redirectTarget = target\\\
8650 return oldRedirectTarget\\\
8651end\\\
8652\\\
8653term.current = function()\\\
8654 return redirectTarget\\\
8655end\\\
8656\\\
8657term.native = function()\\\
8658 -- NOTE: please don't use this function unless you have to.\\\
8659 -- If you're running in a redirected or multitasked enviorment, term.native() will NOT be\\\
8660 -- the current terminal when your program starts up. It is far better to use term.current()\\\
8661 return native\\\
8662end\\\
8663\\\
8664for k,v in pairs( native ) do\\\
8665 if type( k ) == \\\"string\\\" and type( v ) == \\\"function\\\" then\\\
8666 if term[k] == nil then\\\
8667 term[k] = wrap( k )\\\
8668 end\\\
8669 end\\\
8670end\\\
8671\\\
8672local env = _ENV\\\
8673for k,v in pairs( term ) do\\\
8674 env[k] = v\\\
8675end\",\
8676 [ \"help/fs.txt\" ] = \"Functions in the Filesystem API:\\\
8677fs.list( path )\\\
8678fs.find( wildcard )\\\
8679fs.exists( path )\\\
8680fs.isDir( path )\\\
8681fs.isReadOnly( path )\\\
8682fs.getDir( path )\\\
8683fs.getName( path )\\\
8684fs.getSize( path )\\\
8685fs.getDrive( path )\\\
8686fs.getFreeSpace( path )\\\
8687fs.makeDir( path )\\\
8688fs.move( path, path )\\\
8689fs.copy( path, path )\\\
8690fs.delete( path )\\\
8691fs.combine( path, localpath )\\\
8692fs.open( path, mode )\\\
8693fs.complete( path, location )\\\
8694Available fs.open() modes are \\\"r\\\", \\\"w\\\", \\\"a\\\", \\\"rb\\\", \\\"wb\\\" and \\\"ab\\\".\\\
8695\\\
8696Functions on files opened with mode \\\"r\\\":\\\
8697readLine()\\\
8698readAll()\\\
8699close()\\\
8700read( number )\\\
8701\\\
8702Functions on files opened with mode \\\"w\\\" or \\\"a\\\":\\\
8703write( string )\\\
8704writeLine( string )\\\
8705flush()\\\
8706close()\\\
8707\\\
8708Functions on files opened with mode \\\"rb\\\":\\\
8709read()\\\
8710close()\\\
8711\\\
8712Functions on files opened with mode \\\"wb\\\" or \\\"ab\\\":\\\
8713write( byte )\\\
8714flush()\\\
8715close()\",\
8716 [ \"programs/lua.lua\" ] = \"\\\
8717local tArgs = { ... }\\\
8718if #tArgs > 0 then\\\
8719 print( \\\"This is an interactive Lua prompt.\\\" )\\\
8720 print( \\\"To run a lua program, just type its name.\\\" )\\\
8721 return\\\
8722end\\\
8723\\\
8724local bRunning = true\\\
8725local tCommandHistory = {}\\\
8726local tEnv = {\\\
8727 [\\\"exit\\\"] = function()\\\
8728 bRunning = false\\\
8729 end,\\\
8730 [\\\"_echo\\\"] = function( ... )\\\
8731 return ...\\\
8732 end,\\\
8733}\\\
8734setmetatable( tEnv, { __index = _ENV } )\\\
8735\\\
8736if term.isColour() then\\\
8737 term.setTextColour( colours.yellow )\\\
8738end\\\
8739print( \\\"Interactive Lua prompt.\\\" )\\\
8740print( \\\"Call exit() to exit.\\\" )\\\
8741term.setTextColour( colours.white )\\\
8742\\\
8743while bRunning do\\\
8744 --if term.isColour() then\\\
8745 -- term.setTextColour( colours.yellow )\\\
8746 --end\\\
8747 write( \\\"lua> \\\" )\\\
8748 --term.setTextColour( colours.white )\\\
8749\\\
8750 local s = read( nil, tCommandHistory, function( sLine )\\\
8751 if settings.get( \\\"lua.autocomplete\\\" ) then\\\
8752 local nStartPos = string.find( sLine, \\\"[a-zA-Z0-9_%.:]+$\\\" )\\\
8753 if nStartPos then\\\
8754 sLine = string.sub( sLine, nStartPos )\\\
8755 end\\\
8756 if #sLine > 0 then\\\
8757 return textutils.complete( sLine, tEnv )\\\
8758 end\\\
8759 end\\\
8760 return nil\\\
8761 end )\\\
8762 if s:match(\\\"%S\\\") and tCommandHistory[#tCommandHistory] ~= s then\\\
8763 table.insert( tCommandHistory, s )\\\
8764 end\\\
8765\\\
8766 local nForcePrint = 0\\\
8767 local func, e = load( s, \\\"lua\\\", \\\"t\\\", tEnv )\\\
8768 local func2, e2 = load( \\\"return _echo(\\\"..s..\\\");\\\", \\\"lua\\\", \\\"t\\\", tEnv )\\\
8769 if not func then\\\
8770 if func2 then\\\
8771 func = func2\\\
8772 e = nil\\\
8773 nForcePrint = 1\\\
8774 end\\\
8775 else\\\
8776 if func2 then\\\
8777 func = func2\\\
8778 end\\\
8779 end\\\
8780\\\
8781 if func then\\\
8782 local tResults = table.pack( pcall( func ) )\\\
8783 if tResults[1] then\\\
8784 local n = 1\\\
8785 while n < tResults.n or (n <= nForcePrint) do\\\
8786 local value = tResults[ n + 1 ]\\\
8787 if type( value ) == \\\"table\\\" then\\\
8788 local metatable = getmetatable( value )\\\
8789 if type(metatable) == \\\"table\\\" and type(metatable.__tostring) == \\\"function\\\" then\\\
8790 print( tostring( value ) )\\\
8791 else\\\
8792 local ok, serialised = pcall( textutils.serialise, value )\\\
8793 if ok then\\\
8794 print( serialised )\\\
8795 else\\\
8796 print( tostring( value ) )\\\
8797 end\\\
8798 end\\\
8799 else\\\
8800 print( tostring( value ) )\\\
8801 end\\\
8802 n = n + 1\\\
8803 end\\\
8804 else\\\
8805 printError( tResults[2] )\\\
8806 end\\\
8807 else\\\
8808 printError( e )\\\
8809 end\\\
8810\\\
8811end\",\
8812 [ \"programs/fun/advanced/levels/11.dat\" ] = \"4\\\
8813 777777777\\\
8814 727872787\\\
8815 787878787\\\
8816777787878787777\\\
88177be888888888be7\\\
8818777787878787777\\\
8819 787878787\\\
8820 787478747\\\
8821 777777777\",\
8822 [ \"help/copy.txt\" ] = \"cp copies a file or directory from one location to another.\\\
8823\\\
8824ex:\\\
8825\\\"cp rom myrom\\\" copies \\\"rom\\\" to \\\"myrom\\\".\\\
8826\\\"cp rom mystuff/rom\\\" copies \\\"rom\\\" to \\\"mystuff/rom\\\".\\\
8827\\\"cp disk/* disk2\\\" copies the contents of one disk to another\",\
8828 [ \"help/delete.txt\" ] = \"rm deletes a file or a directory and its contents.\\\
8829\\\
8830ex:\\\
8831\\\"rm foo\\\" will delete the file foo.\\\
8832\\\"rm disk/*\\\" will delete the contents of a disk.\",\
8833 [ \"programs/advanced/fg.lua\" ] = \"\\\
8834if not shell.openTab then\\\
8835 printError( \\\"Requires multishell\\\" )\\\
8836 return\\\
8837end\\\
8838\\\
8839local tArgs = { ... }\\\
8840if #tArgs > 0 then\\\
8841 local nTask = shell.openTab( table.unpack( tArgs ) )\\\
8842 if nTask then\\\
8843 shell.switchTab( nTask )\\\
8844 end\\\
8845else\\\
8846 local nTask = shell.openTab( \\\"shell\\\" )\\\
8847 if nTask then\\\
8848 shell.switchTab( nTask )\\\
8849 end\\\
8850end\",\
8851 [ \"programs/apis.lua\" ] = \"\\\
8852local tApis = {}\\\
8853for k,v in pairs( _G ) do\\\
8854 if type(k) == \\\"string\\\" and type(v) == \\\"table\\\" and k ~= \\\"_G\\\" then\\\
8855 table.insert( tApis, k )\\\
8856 end\\\
8857end\\\
8858table.insert( tApis, \\\"shell\\\" )\\\
8859table.insert( tApis, \\\"package\\\" )\\\
8860if multishell then\\\
8861 table.insert( tApis, \\\"multishell\\\" )\\\
8862end\\\
8863table.sort( tApis )\\\
8864\\\
8865textutils.pagedTabulate( tApis )\",\
8866 [ \"programs/label.lua\" ] = \"\\\
8867local function printUsage()\\\
8868 print( \\\"Usages:\\\" )\\\
8869 print( \\\"label get\\\" )\\\
8870 print( \\\"label get <drive>\\\" )\\\
8871 print( \\\"label set <text>\\\" )\\\
8872 print( \\\"label set <drive> <text>\\\" )\\\
8873 print( \\\"label clear\\\" )\\\
8874 print( \\\"label clear <drive>\\\" )\\\
8875end\\\
8876\\\
8877local function checkDrive( sDrive )\\\
8878 if peripheral.getType( sDrive ) == \\\"drive\\\" then\\\
8879 -- Check the disk exists\\\
8880 local bData = disk.hasData( sDrive )\\\
8881 if not bData then\\\
8882 print( \\\"No disk in \\\"..sDrive..\\\" drive\\\" )\\\
8883 return false\\\
8884 end\\\
8885 else\\\
8886 print( \\\"No disk drive named \\\"..sDrive )\\\
8887 return false\\\
8888 end\\\
8889 return true\\\
8890end\\\
8891\\\
8892local function get( sDrive )\\\
8893 if sDrive ~= nil then\\\
8894 if checkDrive( sDrive ) then\\\
8895 local sLabel = disk.getLabel( sDrive )\\\
8896 if sLabel then\\\
8897 print( \\\"Disk label is \\\\\\\"\\\"..sLabel..\\\"\\\\\\\"\\\" )\\\
8898 else\\\
8899 print( \\\"No Disk label\\\" )\\\
8900 end\\\
8901 end\\\
8902 else\\\
8903 local sLabel = os.getComputerLabel()\\\
8904 if sLabel then\\\
8905 print( \\\"Computer label is \\\\\\\"\\\"..sLabel..\\\"\\\\\\\"\\\" )\\\
8906 else\\\
8907 print( \\\"No Computer label\\\" )\\\
8908 end\\\
8909 end\\\
8910end\\\
8911\\\
8912local function set( sDrive, sText )\\\
8913 if sDrive ~= nil then\\\
8914 if checkDrive( sDrive ) then\\\
8915 disk.setLabel( sDrive, sText )\\\
8916 local sLabel = disk.getLabel( sDrive )\\\
8917 if sLabel then\\\
8918 print( \\\"Disk label set to \\\\\\\"\\\"..sLabel..\\\"\\\\\\\"\\\" )\\\
8919 else\\\
8920 print( \\\"Disk label cleared\\\" )\\\
8921 end\\\
8922 end\\\
8923 else\\\
8924 os.setComputerLabel( sText )\\\
8925 local sLabel = os.getComputerLabel()\\\
8926 if sLabel then\\\
8927 print( \\\"Computer label set to \\\\\\\"\\\"..sLabel..\\\"\\\\\\\"\\\" )\\\
8928 else\\\
8929 print( \\\"Computer label cleared\\\" )\\\
8930 end\\\
8931 end\\\
8932end\\\
8933\\\
8934local tArgs = { ... }\\\
8935local sCommand = tArgs[1]\\\
8936if sCommand == \\\"get\\\" then\\\
8937 -- Get a label\\\
8938 if #tArgs == 1 then\\\
8939 get( nil )\\\
8940 elseif #tArgs == 2 then\\\
8941 get( tArgs[2] )\\\
8942 else\\\
8943 printUsage()\\\
8944 end\\\
8945elseif sCommand == \\\"set\\\" then\\\
8946 -- Set a label\\\
8947 if #tArgs == 2 then\\\
8948 set( nil, tArgs[2] )\\\
8949 elseif #tArgs == 3 then\\\
8950 set( tArgs[2], tArgs[3] )\\\
8951 else\\\
8952 printUsage()\\\
8953 end\\\
8954elseif sCommand == \\\"clear\\\" then\\\
8955 -- Clear a label\\\
8956 if #tArgs == 1 then\\\
8957 set( nil, nil )\\\
8958 elseif #tArgs == 2 then\\\
8959 set( tArgs[2], nil )\\\
8960 else\\\
8961 printUsage()\\\
8962 end\\\
8963else\\\
8964 printUsage()\\\
8965end\",\
8966 [ \"programs/id.lua\" ] = \"\\\
8967local sDrive = nil\\\
8968local tArgs = { ... }\\\
8969if #tArgs > 0 then\\\
8970 sDrive = tostring( tArgs[1] )\\\
8971end\\\
8972\\\
8973if sDrive == nil then\\\
8974 print( \\\"This is computer #\\\"..os.getComputerID() )\\\
8975\\\
8976 local label = os.getComputerLabel()\\\
8977 if label then\\\
8978 print( \\\"This computer is labelled \\\\\\\"\\\"..label..\\\"\\\\\\\"\\\" )\\\
8979 end\\\
8980\\\
8981else\\\
8982 local bData = disk.hasData( sDrive )\\\
8983 if not bData then\\\
8984 print( \\\"No disk in drive \\\"..sDrive )\\\
8985 return\\\
8986 end\\\
8987\\\
8988 print( \\\"The disk is #\\\"..disk.getID( sDrive ) )\\\
8989\\\
8990 local label = disk.getLabel( sDrive )\\\
8991 if label then\\\
8992 print( \\\"The disk is labelled \\\\\\\"\\\"..label..\\\"\\\\\\\"\\\" )\\\
8993 end\\\
8994end\",\
8995 [ \"programs/http/pastebin.lua\" ] = \"\\\
8996local function printUsage()\\\
8997 print( \\\"Usages:\\\" )\\\
8998 print( \\\"pastebin put <filename>\\\" )\\\
8999 print( \\\"pastebin get <code> <filename>\\\" )\\\
9000 print( \\\"pastebin run <code> <arguments>\\\" )\\\
9001end\\\
9002\\\
9003local tArgs = { ... }\\\
9004if #tArgs < 2 then\\\
9005 printUsage()\\\
9006 return\\\
9007end\\\
9008\\\
9009if not http then\\\
9010 printError( \\\"Pastebin requires http API\\\" )\\\
9011 printError( \\\"Set http_enable to true in ComputerCraft.cfg\\\" )\\\
9012 return\\\
9013end\\\
9014\\\
9015local function get(paste)\\\
9016 write( \\\"Connecting to pastebin.com... \\\" )\\\
9017 local response = http.get(\\\
9018 \\\"https://pastebin.com/raw/\\\"..textutils.urlEncode( paste )\\\
9019 )\\\
9020\\\
9021 if response then\\\
9022 print( \\\"Success.\\\" )\\\
9023\\\
9024 local sResponse = response.readAll()\\\
9025 response.close()\\\
9026 return sResponse\\\
9027 else\\\
9028 print( \\\"Failed.\\\" )\\\
9029 end\\\
9030end\\\
9031\\\
9032local sCommand = tArgs[1]\\\
9033if sCommand == \\\"put\\\" then\\\
9034 -- Upload a file to pastebin.com\\\
9035 -- Determine file to upload\\\
9036 local sFile = tArgs[2]\\\
9037 local sPath = shell.resolve( sFile )\\\
9038 if not fs.exists( sPath ) or fs.isDir( sPath ) then\\\
9039 print( \\\"No such file\\\" )\\\
9040 return\\\
9041 end\\\
9042\\\
9043 -- Read in the file\\\
9044 local sName = fs.getName( sPath )\\\
9045 local file = fs.open( sPath, \\\"r\\\" )\\\
9046 local sText = file.readAll()\\\
9047 file.close()\\\
9048\\\
9049 -- POST the contents to pastebin\\\
9050 write( \\\"Connecting to pastebin.com... \\\" )\\\
9051 local key = \\\"0ec2eb25b6166c0c27a394ae118ad829\\\"\\\
9052 local response = http.post(\\\
9053 \\\"https://pastebin.com/api/api_post.php\\\",\\\
9054 \\\"api_option=paste&\\\"..\\\
9055 \\\"api_dev_key=\\\"..key..\\\"&\\\"..\\\
9056 \\\"api_paste_format=lua&\\\"..\\\
9057 \\\"api_paste_name=\\\"..textutils.urlEncode(sName)..\\\"&\\\"..\\\
9058 \\\"api_paste_code=\\\"..textutils.urlEncode(sText)\\\
9059 )\\\
9060\\\
9061 if response then\\\
9062 print( \\\"Success.\\\" )\\\
9063\\\
9064 local sResponse = response.readAll()\\\
9065 response.close()\\\
9066\\\
9067 local sCode = string.match( sResponse, \\\"[^/]+$\\\" )\\\
9068 print( \\\"Uploaded as \\\"..sResponse )\\\
9069 print( \\\"Run \\\\\\\"pastebin get \\\"..sCode..\\\"\\\\\\\" to download anywhere\\\" )\\\
9070\\\
9071 else\\\
9072 print( \\\"Failed.\\\" )\\\
9073 end\\\
9074\\\
9075elseif sCommand == \\\"get\\\" then\\\
9076 -- Download a file from pastebin.com\\\
9077 if #tArgs < 3 then\\\
9078 printUsage()\\\
9079 return\\\
9080 end\\\
9081\\\
9082 -- Determine file to download\\\
9083 local sCode = tArgs[2]\\\
9084 local sFile = tArgs[3]\\\
9085 local sPath = shell.resolve( sFile )\\\
9086 if fs.exists( sPath ) then\\\
9087 print( \\\"File already exists\\\" )\\\
9088 return\\\
9089 end\\\
9090\\\
9091 -- GET the contents from pastebin\\\
9092 local res = get(sCode)\\\
9093 if res then\\\
9094 local file = fs.open( sPath, \\\"w\\\" )\\\
9095 file.write( res )\\\
9096 file.close()\\\
9097\\\
9098 print( \\\"Downloaded as \\\"..sFile )\\\
9099 end\\\
9100elseif sCommand == \\\"run\\\" then\\\
9101 local sCode = tArgs[2]\\\
9102\\\
9103 local res = get(sCode)\\\
9104 if res then\\\
9105 local func, err = load(res, sCode, \\\"t\\\", _ENV)\\\
9106 if not func then\\\
9107 printError( err )\\\
9108 return\\\
9109 end\\\
9110 local success, msg = pcall(func, select(3, ...))\\\
9111 if not success then\\\
9112 printError( msg )\\\
9113 end\\\
9114 end\\\
9115else\\\
9116 printUsage()\\\
9117 return\\\
9118end\",\
9119 [ \"help/programs.txt\" ] = \"programs lists all the programs on the rom of the computer.\",\
9120 [ \"programs/peripherals.lua\" ] = \"local tPeripherals = peripheral.getNames()\\\
9121print( \\\"Attached Peripherals:\\\" )\\\
9122if #tPeripherals > 0 then\\\
9123 for n=1,#tPeripherals do\\\
9124 local sPeripheral = tPeripherals[n]\\\
9125 print( sPeripheral .. \\\" (\\\" .. peripheral.getType( sPeripheral ) .. \\\")\\\" )\\\
9126 end\\\
9127else\\\
9128 print( \\\"None\\\" )\\\
9129end\",\
9130 [ \"programs/fun/advanced/levels/2.dat\" ] = \"1\\\
9131777777777\\\
91327888888b7\\\
9133787778887\\\
9134787 78777\\\
91357877787\\\
91367888887\\\
91377777787\\\
9138 707\\\
9139 777\",\
9140 [ \"programs/fun/worm.lua\" ] = \"\\\
9141-- Display the start screen\\\
9142local w,h = term.getSize()\\\
9143\\\
9144local titleColour, headingColour, textColour, wormColour, fruitColour\\\
9145if term.isColour() then\\\
9146 titleColour = colours.red\\\
9147 headingColour = colours.yellow\\\
9148 textColour = colours.white\\\
9149 wormColour = colours.green\\\
9150 fruitColour = colours.red\\\
9151else\\\
9152 titleColour = colours.white\\\
9153 headingColour = colours.white\\\
9154 textColour = colours.white\\\
9155 wormColour = colours.white\\\
9156 fruitColour = colours.white\\\
9157end\\\
9158\\\
9159local function printCentred( y, s )\\\
9160 local x = math.floor((w - string.len(s)) / 2)\\\
9161 term.setCursorPos(x,y)\\\
9162 --term.clearLine()\\\
9163 term.write( s )\\\
9164end\\\
9165\\\
9166local xVel,yVel = 1,0\\\
9167local xPos, yPos = math.floor(w/2), math.floor(h/2)\\\
9168local pxVel, pyVel = nil, nil\\\
9169\\\
9170local nLength = 1\\\
9171local nExtraLength = 6\\\
9172local bRunning = true\\\
9173\\\
9174local tailX,tailY = xPos,yPos\\\
9175local nScore = 0\\\
9176local nDifficulty = 2\\\
9177local nSpeed, nInterval\\\
9178\\\
9179-- Setup the screen\\\
9180local screen = {}\\\
9181for x=1,w do\\\
9182 screen[x] = {}\\\
9183 for y=1,h do\\\
9184 screen[x][y] = {}\\\
9185 end\\\
9186end\\\
9187screen[xPos][yPos] = { snake = true }\\\
9188\\\
9189local nFruit = 1\\\
9190local tFruits = {\\\
9191 \\\"A\\\", \\\"B\\\", \\\"C\\\", \\\"D\\\", \\\"E\\\", \\\"F\\\", \\\"G\\\", \\\"H\\\",\\\
9192 \\\"I\\\", \\\"J\\\", \\\"K\\\", \\\"L\\\", \\\"M\\\", \\\"N\\\", \\\"O\\\", \\\"P\\\",\\\
9193 \\\"Q\\\", \\\"R\\\", \\\"S\\\", \\\"T\\\", \\\"U\\\", \\\"V\\\", \\\"W\\\", \\\"X\\\",\\\
9194 \\\"Y\\\", \\\"Z\\\",\\\
9195 \\\"a\\\", \\\"b\\\", \\\"c\\\", \\\"d\\\", \\\"e\\\", \\\"f\\\", \\\"g\\\", \\\"h\\\",\\\
9196 \\\"i\\\", \\\"j\\\", \\\"k\\\", \\\"l\\\", \\\"m\\\", \\\"n\\\", \\\"o\\\", \\\"p\\\",\\\
9197 \\\"q\\\", \\\"r\\\", \\\"s\\\", \\\"t\\\", \\\"u\\\", \\\"v\\\", \\\"w\\\", \\\"x\\\",\\\
9198 \\\"y\\\", \\\"z\\\",\\\
9199 \\\"1\\\", \\\"2\\\", \\\"3\\\", \\\"4\\\", \\\"5\\\", \\\"6\\\", \\\"7\\\", \\\"8\\\", \\\"9\\\", \\\"0\\\",\\\
9200 \\\"@\\\", \\\"$\\\", \\\"%\\\", \\\"#\\\", \\\"&\\\", \\\"!\\\", \\\"?\\\", \\\"+\\\", \\\"*\\\", \\\"~\\\"\\\
9201}\\\
9202\\\
9203local function addFruit()\\\
9204 while true do\\\
9205 local x = math.random(1,w)\\\
9206 local y = math.random(2,h)\\\
9207 local fruit = screen[x][y]\\\
9208 if fruit.snake == nil and fruit.wall == nil and fruit.fruit == nil then\\\
9209 screen[x][y] = { fruit = true }\\\
9210 term.setCursorPos(x,y)\\\
9211 term.setBackgroundColour( fruitColour )\\\
9212 term.write(\\\" \\\")\\\
9213 term.setBackgroundColour( colours.black )\\\
9214 break\\\
9215 end\\\
9216 end\\\
9217\\\
9218 nFruit = nFruit + 1\\\
9219 if nFruit > #tFruits then\\\
9220 nFruit = 1\\\
9221 end\\\
9222end\\\
9223\\\
9224local function drawMenu()\\\
9225 term.setTextColour( headingColour )\\\
9226 term.setCursorPos(1,1)\\\
9227 term.write( \\\"SCORE \\\" )\\\
9228\\\
9229 term.setTextColour( textColour )\\\
9230 term.setCursorPos(7,1)\\\
9231 term.write( tostring(nScore) )\\\
9232\\\
9233 term.setTextColour( headingColour )\\\
9234 term.setCursorPos(w-11,1)\\\
9235 term.write( \\\"DIFFICULTY \\\")\\\
9236\\\
9237 term.setTextColour( textColour )\\\
9238 term.setCursorPos(w,1)\\\
9239 term.write( tostring(nDifficulty or \\\"?\\\") )\\\
9240\\\
9241 term.setTextColour( colours.white )\\\
9242end\\\
9243\\\
9244local function update( )\\\
9245 local x,y = xPos,yPos\\\
9246 if pxVel and pyVel then\\\
9247 xVel, yVel = pxVel, pyVel\\\
9248 pxVel, pyVel = nil, nil\\\
9249 end\\\
9250\\\
9251 -- Remove the tail\\\
9252 if nExtraLength == 0 then\\\
9253 local tail = screen[tailX][tailY]\\\
9254 screen[tailX][tailY] = {}\\\
9255 term.setCursorPos(tailX,tailY)\\\
9256 term.write(\\\" \\\")\\\
9257 tailX = tail.nextX\\\
9258 tailY = tail.nextY\\\
9259 else\\\
9260 nExtraLength = nExtraLength - 1\\\
9261 end\\\
9262\\\
9263 -- Update the head\\\
9264 local head = screen[xPos][yPos]\\\
9265 local newXPos = xPos + xVel\\\
9266 local newYPos = yPos + yVel\\\
9267 if newXPos < 1 then\\\
9268 newXPos = w\\\
9269 elseif newXPos > w then\\\
9270 newXPos = 1\\\
9271 end\\\
9272 if newYPos < 2 then\\\
9273 newYPos = h\\\
9274 elseif newYPos > h then\\\
9275 newYPos = 2\\\
9276 end\\\
9277\\\
9278 local newHead = screen[newXPos][newYPos]\\\
9279 if newHead.snake == true or newHead.wall == true then\\\
9280 bRunning = false\\\
9281\\\
9282 else\\\
9283 if newHead.fruit == true then\\\
9284 nScore = nScore + 10\\\
9285 nExtraLength = nExtraLength + 1\\\
9286 addFruit()\\\
9287 end\\\
9288 xPos = newXPos\\\
9289 yPos = newYPos\\\
9290 head.nextX = newXPos\\\
9291 head.nextY = newYPos\\\
9292 screen[newXPos][newYPos] = { snake = true }\\\
9293\\\
9294 end\\\
9295\\\
9296 term.setCursorPos(xPos,yPos)\\\
9297 term.setBackgroundColour( wormColour )\\\
9298 term.write(\\\" \\\")\\\
9299 term.setBackgroundColour( colours.black )\\\
9300\\\
9301 drawMenu()\\\
9302end\\\
9303\\\
9304-- Display the frontend\\\
9305term.clear()\\\
9306local function drawFrontend()\\\
9307 --term.setTextColour( titleColour )\\\
9308 --printCentred( math.floor(h/2) - 4, \\\" W O R M \\\" )\\\
9309\\\
9310 term.setTextColour( headingColour )\\\
9311 printCentred( math.floor(h/2) - 3, \\\"\\\" )\\\
9312 printCentred( math.floor(h/2) - 2, \\\" SELECT DIFFICULTY \\\" )\\\
9313 printCentred( math.floor(h/2) - 1, \\\"\\\" )\\\
9314\\\
9315 printCentred( math.floor(h/2) + 0, \\\" \\\" )\\\
9316 printCentred( math.floor(h/2) + 1, \\\" \\\" )\\\
9317 printCentred( math.floor(h/2) + 2, \\\" \\\" )\\\
9318 printCentred( math.floor(h/2) - 1 + nDifficulty, \\\" [ ] \\\" )\\\
9319\\\
9320 term.setTextColour( textColour )\\\
9321 printCentred( math.floor(h/2) + 0, \\\"EASY\\\" )\\\
9322 printCentred( math.floor(h/2) + 1, \\\"MEDIUM\\\" )\\\
9323 printCentred( math.floor(h/2) + 2, \\\"HARD\\\" )\\\
9324 printCentred( math.floor(h/2) + 3, \\\"\\\" )\\\
9325\\\
9326 term.setTextColour( colours.white )\\\
9327end\\\
9328\\\
9329drawMenu()\\\
9330drawFrontend()\\\
9331while true do\\\
9332 local e,key = os.pullEvent( \\\"key\\\" )\\\
9333 if key == keys.up or key == keys.w then\\\
9334 -- Up\\\
9335 if nDifficulty > 1 then\\\
9336 nDifficulty = nDifficulty - 1\\\
9337 drawMenu()\\\
9338 drawFrontend()\\\
9339 end\\\
9340 elseif key == keys.down or key == keys.s then\\\
9341 -- Down\\\
9342 if nDifficulty < 3 then\\\
9343 nDifficulty = nDifficulty + 1\\\
9344 drawMenu()\\\
9345 drawFrontend()\\\
9346 end\\\
9347 elseif key == keys.enter then\\\
9348 -- Enter\\\
9349 break\\\
9350 end\\\
9351end\\\
9352\\\
9353local tSpeeds = { 5, 10, 25 }\\\
9354nSpeed = tSpeeds[nDifficulty]\\\
9355nInterval = 1 / nSpeed\\\
9356\\\
9357-- Grow the snake to its intended size\\\
9358term.clear()\\\
9359drawMenu()\\\
9360screen[tailX][tailY].snake = true\\\
9361while nExtraLength > 0 do\\\
9362 update()\\\
9363end\\\
9364addFruit()\\\
9365addFruit()\\\
9366\\\
9367-- Play the game\\\
9368local timer = os.startTimer(0)\\\
9369while bRunning do\\\
9370 local event, p1, p2 = os.pullEvent()\\\
9371 if event == \\\"timer\\\" and p1 == timer then\\\
9372 timer = os.startTimer(nInterval)\\\
9373 update( false )\\\
9374\\\
9375 elseif event == \\\"key\\\" then\\\
9376 local key = p1\\\
9377 if key == keys.up or key == keys.w then\\\
9378 -- Up\\\
9379 if yVel == 0 then\\\
9380 pxVel,pyVel = 0,-1\\\
9381 end\\\
9382 elseif key == keys.down or key == keys.s then\\\
9383 -- Down\\\
9384 if yVel == 0 then\\\
9385 pxVel,pyVel = 0,1\\\
9386 end\\\
9387 elseif key == keys.left or key == keys.a then\\\
9388 -- Left\\\
9389 if xVel == 0 then\\\
9390 pxVel,pyVel = -1,0\\\
9391 end\\\
9392\\\
9393 elseif key == keys.right or key == keys.d then\\\
9394 -- Right\\\
9395 if xVel == 0 then\\\
9396 pxVel,pyVel = 1,0\\\
9397 end\\\
9398\\\
9399 end\\\
9400 end\\\
9401end\\\
9402\\\
9403-- Display the gameover screen\\\
9404term.setTextColour( headingColour )\\\
9405printCentred( math.floor(h/2) - 2, \\\" \\\" )\\\
9406printCentred( math.floor(h/2) - 1, \\\" G A M E O V E R \\\" )\\\
9407\\\
9408term.setTextColour( textColour )\\\
9409printCentred( math.floor(h/2) + 0, \\\" \\\" )\\\
9410printCentred( math.floor(h/2) + 1, \\\" FINAL SCORE \\\"..nScore..\\\" \\\" )\\\
9411printCentred( math.floor(h/2) + 2, \\\" \\\" )\\\
9412term.setTextColour( colours.white )\\\
9413\\\
9414local timer = os.startTimer(2.5)\\\
9415repeat\\\
9416 local e,p = os.pullEvent()\\\
9417 if e == \\\"timer\\\" and p == timer then\\\
9418 term.setTextColour( textColour )\\\
9419 printCentred( math.floor(h/2) + 2, \\\" PRESS ANY KEY \\\" )\\\
9420 printCentred( math.floor(h/2) + 3, \\\" \\\" )\\\
9421 term.setTextColour( colours.white )\\\
9422 end\\\
9423until e == \\\"char\\\"\\\
9424\\\
9425term.clear()\\\
9426term.setCursorPos(1,1)\",\
9427 [ \"programs/fun/hello.lua\" ] = \"if term.isColour() then\\\
9428 term.setTextColour( 2^math.random(0,15) )\\\
9429end\\\
9430textutils.slowPrint( \\\"Hello World!\\\" )\\\
9431term.setTextColour( colours.white )\",\
9432 [ \"programs/fun/dj.lua\" ] = \"local tArgs = { ... }\\\
9433\\\
9434local function printUsage()\\\
9435 print( \\\"Usages:\\\")\\\
9436 print( \\\"dj play\\\" )\\\
9437 print( \\\"dj play <drive>\\\" )\\\
9438 print( \\\"dj stop\\\" )\\\
9439end\\\
9440\\\
9441if #tArgs > 2 then\\\
9442 printUsage()\\\
9443 return\\\
9444end\\\
9445\\\
9446local sCommand = tArgs[1]\\\
9447if sCommand == \\\"stop\\\" then\\\
9448 -- Stop audio\\\
9449 disk.stopAudio()\\\
9450\\\
9451elseif sCommand == \\\"play\\\" or sCommand == nil then\\\
9452 -- Play audio\\\
9453 local sName = tArgs[2]\\\
9454 if sName == nil then\\\
9455 -- No disc specified, pick one at random\\\
9456 local tNames = {}\\\
9457 for n,sName in ipairs( peripheral.getNames() ) do\\\
9458 if disk.isPresent( sName ) and disk.hasAudio( sName ) then\\\
9459 table.insert( tNames, sName )\\\
9460 end\\\
9461 end\\\
9462 if #tNames == 0 then\\\
9463 print( \\\"No Music Discs in attached disk drives\\\" )\\\
9464 return\\\
9465 end\\\
9466 sName = tNames[ math.random(1,#tNames) ]\\\
9467 end\\\
9468\\\
9469 -- Play the disc\\\
9470 if disk.isPresent( sName ) and disk.hasAudio( sName ) then\\\
9471 print( \\\"Playing \\\"..disk.getAudioTitle( sName ) )\\\
9472 disk.playAudio( sName )\\\
9473 else\\\
9474 print( \\\"No Music Disc in disk drive: \\\"..sName )\\\
9475 return\\\
9476 end\\\
9477\\\
9478else\\\
9479 printUsage()\\\
9480\\\
9481end\",\
9482 [ \"help/disk.txt\" ] = \"Functions in the disk API. These functions are for interacting with disk drives:\\\
9483disk.isPresent( drive )\\\
9484disk.setLabel( drive, label )\\\
9485disk.getLabel( drive )\\\
9486disk.hasData( drive )\\\
9487disk.getMountPath( drive )\\\
9488disk.hasAudio( drive )\\\
9489disk.getAudioTitle( drive )\\\
9490disk.playAudio( drive )\\\
9491disk.stopAudio( )\\\
9492disk.eject( drive )\\\
9493disk.getID( drive )\\\
9494\\\
9495Events fired by the disk API:\\\
9496\\\"disk\\\" when a disk or other item is inserted into a disk drive. Argument is the name of the drive\\\
9497\\\"disk_eject\\\" when a disk is removed from a disk drive. Argument is the name of the drive\\\
9498Type \\\"help events\\\" to learn about the event system.\",\
9499 [ \"programs/fun/advanced/levels/5.dat\" ] = \"3\\\
9500777777777\\\
9501788888887\\\
9502787787787\\\
9503787787787\\\
9504788888887\\\
9505787787787\\\
9506787787787\\\
950778e748887\\\
9508777777777\",\
9509 [ \"help/credits.txt\" ] = \"\\\
9510ComputerCraft was created by Daniel \\\"dan200\\\" Ratcliffe, with additional code by Aaron \\\"Cloudy\\\" Mills.\\\
9511Thanks to nitrogenfingers, GopherATL and RamiLego for program contributions.\\\
9512Thanks to Mojang, the Forge team, and the MCP team.\\\
9513Uses LuaJ from http://luaj.sourceforge.net/\\\
9514\\\
9515The ComputerCraft 1.76 update was sponsored by MinecraftU and Deep Space.\\\
9516Visit http://www.minecraftu.org and http://www.deepspace.me/space-cadets to find out more.\\\
9517\\\
9518Join the ComputerCraft community online at http://www.computercraft.info\\\
9519Follow @DanTwoHundred on Twitter!\\\
9520\\\
9521To help contribute to ComputerCraft, browse the source code at https://github.com/dan200/ComputerCraft.\\\
9522\\\
9523GitHub Contributors:\\\
9524apemanzilla\\\
9525Bartek Bok\\\
9526Bomb Bloke\\\
9527CrazedProgrammer\\\
9528Cruor\\\
9529Drew Lemmy\\\
9530gegy1000\\\
9531hugeblank\\\
9532hydraz\\\
9533Jonathan Leitschuh\\\
9534Joseph C. Sible\\\
9535KingofGamesYami\\\
9536Lignum\\\
9537Logan Davis\\\
9538Luca S\\\
9539MineRobber___T\\\
9540Nephi (AKA Lupus590)\\\
9541ObloxCC\\\
9542Oliver Marks\\\
9543Restioson\\\
9544SquidDev\\\
9545Steven Dirth\\\
9546theoriginalbit\\\
9547Tim Ittermann\\\
9548Vexatos\\\
9549Wilma456\\\
9550Wilma456 (Jakob0815)\\\
9551Wojbie\",\
9552 [ \"programs/gps.lua\" ] = \"\\\
9553local function printUsage()\\\
9554 print( \\\"Usages:\\\" )\\\
9555 print( \\\"gps host\\\" )\\\
9556 print( \\\"gps host <x> <y> <z>\\\" )\\\
9557 print( \\\"gps locate\\\" )\\\
9558end\\\
9559\\\
9560local tArgs = { ... }\\\
9561if #tArgs < 1 then\\\
9562 printUsage()\\\
9563 return\\\
9564end\\\
9565\\\
9566 local sCommand = tArgs[1]\\\
9567if sCommand == \\\"locate\\\" then\\\
9568 -- \\\"gps locate\\\"\\\
9569 -- Just locate this computer (this will print the results)\\\
9570 gps.locate( 2, true )\\\
9571\\\
9572elseif sCommand == \\\"host\\\" then\\\
9573 -- \\\"gps host\\\"\\\
9574 -- Act as a GPS host\\\
9575 if pocket then\\\
9576 print( \\\"GPS Hosts must be stationary\\\" )\\\
9577 return\\\
9578 end\\\
9579\\\
9580 -- Find a modem\\\
9581 local sModemSide = nil\\\
9582 for n,sSide in ipairs( rs.getSides() ) do\\\
9583 if peripheral.getType( sSide ) == \\\"modem\\\" and peripheral.call( sSide, \\\"isWireless\\\" ) then\\\
9584 sModemSide = sSide\\\
9585 break\\\
9586 end\\\
9587 end\\\
9588\\\
9589 if sModemSide == nil then\\\
9590 print( \\\"No wireless modems found. 1 required.\\\" )\\\
9591 return\\\
9592 end\\\
9593\\\
9594 -- Determine position\\\
9595 local x,y,z\\\
9596 if #tArgs >= 4 then\\\
9597 -- Position is manually specified\\\
9598 x = tonumber(tArgs[2])\\\
9599 y = tonumber(tArgs[3])\\\
9600 z = tonumber(tArgs[4])\\\
9601 if x == nil or y == nil or z == nil then\\\
9602 printUsage()\\\
9603 return\\\
9604 end\\\
9605 print( \\\"Position is \\\"..x..\\\",\\\"..y..\\\",\\\"..z )\\\
9606 else\\\
9607 -- Position is to be determined using locate\\\
9608 x,y,z = gps.locate( 2, true )\\\
9609 if x == nil then\\\
9610 print( \\\"Run \\\\\\\"gps host <x> <y> <z>\\\\\\\" to set position manually\\\" )\\\
9611 return\\\
9612 end\\\
9613 end\\\
9614\\\
9615 -- Open a channel\\\
9616 local modem = peripheral.wrap( sModemSide )\\\
9617 print( \\\"Opening channel on modem \\\"..sModemSide )\\\
9618 modem.open( gps.CHANNEL_GPS )\\\
9619\\\
9620 -- Serve requests indefinately\\\
9621 local nServed = 0\\\
9622 while true do\\\
9623 local e, p1, p2, p3, p4, p5 = os.pullEvent( \\\"modem_message\\\" )\\\
9624 if e == \\\"modem_message\\\" then\\\
9625 -- We received a message from a modem\\\
9626 local sSide, sChannel, sReplyChannel, sMessage, nDistance = p1, p2, p3, p4, p5\\\
9627 if sSide == sModemSide and sChannel == gps.CHANNEL_GPS and sMessage == \\\"PING\\\" and nDistance then\\\
9628 -- We received a ping message on the GPS channel, send a response\\\
9629 modem.transmit( sReplyChannel, gps.CHANNEL_GPS, { x, y, z } )\\\
9630\\\
9631 -- Print the number of requests handled\\\
9632 nServed = nServed + 1\\\
9633 if nServed > 1 then\\\
9634 local x,y = term.getCursorPos()\\\
9635 term.setCursorPos(1,y-1)\\\
9636 end\\\
9637 print( nServed..\\\" GPS requests served\\\" )\\\
9638 end\\\
9639 end\\\
9640 end\\\
9641else\\\
9642 -- \\\"gps somethingelse\\\"\\\
9643 -- Error\\\
9644 printUsage()\\\
9645end\",\
9646 [ \"programs/fun/advanced/levels/12.dat\" ] = \"6\\\
964777 777 77\\\
964872888888897\\\
9649 8 8 8\\\
9650 8 8b888 8\\\
965178 e8888 87\\\
965278888788887\\\
965378 8888e 87\\\
9654 8 888b8 8\\\
9655 8 8 8\\\
965675888888807\\\
965777 777 77\",\
9658 [ \"programs/help.lua\" ] = \"local tArgs = { ... }\\\
9659local sTopic\\\
9660if #tArgs > 0 then\\\
9661 sTopic = tArgs[1]\\\
9662else\\\
9663 sTopic = \\\"intro\\\"\\\
9664end\\\
9665\\\
9666if sTopic == \\\"index\\\" then\\\
9667 print( \\\"Help topics availiable:\\\" )\\\
9668 local tTopics = help.topics()\\\
9669 textutils.pagedTabulate( tTopics )\\\
9670 return\\\
9671end\\\
9672\\\
9673local sFile = help.lookup( sTopic )\\\
9674local file = ((sFile ~= nil) and io.open( sFile )) or nil\\\
9675if file then\\\
9676 local sContents = file:read(\\\"*a\\\")\\\
9677 file:close()\\\
9678\\\
9679 local _, nHeight = term.getSize()\\\
9680 textutils.pagedPrint( sContents, nHeight - 3 )\\\
9681else\\\
9682 print( \\\"No help available\\\" )\\\
9683end\",\
9684 [ \"help/label.txt\" ] = \"label gets or sets the label of the Computer, or of Floppy Disks in attached disk drives.\\\
9685\\\
9686ex:\\\
9687\\\"label get\\\" prints the label of the computer.\\\
9688\\\"label get left\\\" prints the label of the disk in the left drive.\\\
9689\\\"label set \\\"My Computer\\\"\\\" set the label of the computer to \\\"My Computer\\\".\\\
9690\\\"label set left \\\"My Programs\\\"\\\" - sets the label of the disk in the left drive to \\\"My Programs\\\".\\\
9691\\\"label clear\\\" clears the label of the computer.\\\
9692\\\"label clear left\\\" clears the label of the disk in the left drive.\",\
9693 [ \"programs/pocket/falling.lua\" ] = \"--[[\\\
9694Falling - Based on Tetris by Alexey Pajitnov\\\
9695This version written by Gopher, at the request of Dan200, for\\\
9696ComputerCraft v1.6. No particular rights are reserved.\\\
9697--]]\\\
9698\\\
9699local function colorass(c,bw)\\\
9700 return term.isColor() and c or bw\\\
9701end\\\
9702\\\
9703local block_s1= {\\\
9704 {\\\
9705 { 1,0,0,0, },\\\
9706 { 1,1,0,0, },\\\
9707 { 0,1,0,0, },\\\
9708 { 0,0,0,0, },\\\
9709 },\\\
9710 {\\\
9711 { 0,0,0,0, },\\\
9712 { 0,1,1,0, },\\\
9713 { 1,1,0,0, },\\\
9714 { 0,0,0,0, },\\\
9715 },\\\
9716 ch=colorass(\\\" \\\",\\\"{}\\\"),\\\
9717 fg=colorass(colors.blue,colors.black),\\\
9718 bg=colorass(colors.cyan,colors.white),\\\
9719 }\\\
9720local block_s2= {\\\
9721 {\\\
9722 { 0,1,0,0, },\\\
9723 { 1,1,0,0, },\\\
9724 { 1,0,0,0, },\\\
9725 { 0,0,0,0, },\\\
9726 },\\\
9727 {\\\
9728 { 0,0,0,0, },\\\
9729 { 1,1,0,0, },\\\
9730 { 0,1,1,0, },\\\
9731 { 0,0,0,0, },\\\
9732 },\\\
9733 ch=colorass(\\\" \\\",\\\"{}\\\"),\\\
9734 fg=colorass(colors.green,colors.black),\\\
9735 bg=colorass(colors.lime,colors.white),\\\
9736 }\\\
9737local block_line = {\\\
9738 {\\\
9739 { 0,1,0,0, },\\\
9740 { 0,1,0,0, },\\\
9741 { 0,1,0,0, },\\\
9742 { 0,1,0,0, },\\\
9743 },\\\
9744 {\\\
9745 { 0,0,0,0, },\\\
9746 { 1,1,1,1, },\\\
9747 { 0,0,0,0, },\\\
9748 { 0,0,0,0, },\\\
9749 },\\\
9750 ch=colorass(\\\" \\\",\\\"[]\\\"),\\\
9751 fg=colorass(colors.pink,colors.black),\\\
9752 bg=colorass(colors.red,colors.white),\\\
9753 }\\\
9754local block_square = {\\\
9755 {\\\
9756 { 1,1,0,0, },\\\
9757 { 1,1,0,0, },\\\
9758 { 0,0,0,0, },\\\
9759 { 0,0,0,0, },\\\
9760 },\\\
9761 ch=colorass(\\\" \\\",\\\"[]\\\"),\\\
9762 fg=colorass(colors.lightBlue,colors.black),\\\
9763 bg=colorass(colors.blue,colors.white),\\\
9764 }\\\
9765local block_L1 = {\\\
9766 {\\\
9767 { 1,1,0,0, },\\\
9768 { 0,1,0,0, },\\\
9769 { 0,1,0,0, },\\\
9770 { 0,0,0,0, },\\\
9771 },\\\
9772 {\\\
9773 { 0,0,0,0, },\\\
9774 { 1,1,1,0, },\\\
9775 { 1,0,0,0, },\\\
9776 { 0,0,0,0, },\\\
9777 },\\\
9778 {\\\
9779 { 0,1,0,0, },\\\
9780 { 0,1,0,0, },\\\
9781 { 0,1,1,0, },\\\
9782 { 0,0,0,0, },\\\
9783 },\\\
9784 {\\\
9785 { 0,0,1,0, },\\\
9786 { 1,1,1,0, },\\\
9787 { 0,0,0,0, },\\\
9788 { 0,0,0,0, },\\\
9789 },\\\
9790 ch=colorass(\\\" \\\",\\\"()\\\"),\\\
9791 fg=colorass(colors.orange,colors.black),\\\
9792 bg=colorass(colors.yellow,colors.white),\\\
9793 }\\\
9794local block_L2 = {\\\
9795 {\\\
9796 { 0,1,0,0, },\\\
9797 { 0,1,0,0, },\\\
9798 { 1,1,0,0, },\\\
9799 { 0,0,0,0, },\\\
9800 },\\\
9801 {\\\
9802 { 0,0,0,0, },\\\
9803 { 1,1,1,0, },\\\
9804 { 0,0,1,0, },\\\
9805 { 0,0,0,0, },\\\
9806 },\\\
9807 {\\\
9808 { 0,1,1,0, },\\\
9809 { 0,1,0,0, },\\\
9810 { 0,1,0,0, },\\\
9811 { 0,0,0,0, },\\\
9812 },\\\
9813 {\\\
9814 { 1,0,0,0, },\\\
9815 { 1,1,1,0, },\\\
9816 { 0,0,0,0, },\\\
9817 { 0,0,0,0, },\\\
9818 },\\\
9819 ch=colorass(\\\" \\\",\\\"()\\\"),\\\
9820 fg=colorass(colors.brown,colors.black),\\\
9821 bg=colorass(colors.orange,colors.white),\\\
9822 }\\\
9823local block_T = {\\\
9824 {\\\
9825 { 0,1,0,0, },\\\
9826 { 1,1,0,0, },\\\
9827 { 0,1,0,0, },\\\
9828 { 0,0,0,0, },\\\
9829 },\\\
9830 {\\\
9831 { 0,0,0,0, },\\\
9832 { 1,1,1,0, },\\\
9833 { 0,1,0,0, },\\\
9834 { 0,0,0,0, },\\\
9835 },\\\
9836 {\\\
9837 { 0,1,0,0, },\\\
9838 { 0,1,1,0, },\\\
9839 { 0,1,0,0, },\\\
9840 { 0,0,0,0, },\\\
9841 },\\\
9842 {\\\
9843 { 0,1,0,0, },\\\
9844 { 1,1,1,0, },\\\
9845 { 0,0,0,0, },\\\
9846 { 0,0,0,0, },\\\
9847 },\\\
9848 ch=colorass(\\\" \\\",\\\"<>\\\"),\\\
9849 fg=colorass(colors.cyan,colors.black),\\\
9850 bg=colorass(colors.purple,colors.white),\\\
9851 }\\\
9852\\\
9853local blocks={ block_line, block_square, block_s1, block_s2, block_L1, block_L2, block_T}\\\
9854\\\
9855local points={4,10,30,120}\\\
9856\\\
9857local function lpad(text,amt)\\\
9858 text=tostring(text)\\\
9859 return string.rep(\\\" \\\",amt-#text)..text\\\
9860end\\\
9861\\\
9862local width,height=term.getSize()\\\
9863\\\
9864if height<19 or width<26 then\\\
9865 print(\\\"Your screen is too small to play :(\\\")\\\
9866 return\\\
9867end\\\
9868\\\
9869\\\
9870local speedsByLevel={\\\
9871 1.2,\\\
9872 1.0,\\\
9873 .8,\\\
9874 .65,\\\
9875 .5,\\\
9876 .4,\\\
9877 .3,\\\
9878 .25,\\\
9879 .2,\\\
9880 .15,\\\
9881 .1,\\\
9882 .05,}\\\
9883\\\
9884local level=1\\\
9885\\\
9886local function playGame()\\\
9887 local score=0\\\
9888 local lines=0\\\
9889 local initialLevel=level\\\
9890 local next=blocks[math.random(1,#blocks)]\\\
9891\\\
9892 local pit={}\\\
9893\\\
9894\\\
9895 local heightAdjust=0\\\
9896\\\
9897 if height<=19 then\\\
9898 heightAdjust=1\\\
9899 end\\\
9900\\\
9901\\\
9902\\\
9903 local function drawScreen()\\\
9904 term.setTextColor(colors.white)\\\
9905 term.setBackgroundColor(colors.black)\\\
9906 term.clear()\\\
9907\\\
9908 term.setTextColor(colors.black)\\\
9909 term.setBackgroundColor(colorass(colors.lightGray, colors.white))\\\
9910 term.setCursorPos(22,2)\\\
9911 term.write(\\\"Score\\\") --score\\\
9912 term.setCursorPos(22,5)\\\
9913 term.write(\\\"Level\\\") --level\\\
9914 term.setCursorPos(22,8)\\\
9915 term.write(\\\"Lines\\\") --lines\\\
9916 term.setCursorPos(22,12)\\\
9917 term.write(\\\"Next\\\") --next\\\
9918\\\
9919 term.setCursorPos(21,1)\\\
9920 term.write(\\\" \\\")\\\
9921 term.setCursorPos(21,2)\\\
9922 term.write(\\\" \\\") --score\\\
9923 term.setCursorPos(21,3)\\\
9924 term.write(\\\" \\\")\\\
9925 term.setCursorPos(21,4)\\\
9926 term.write(\\\" \\\")\\\
9927 term.setCursorPos(21,5)\\\
9928 term.write(\\\" \\\") --level\\\
9929 term.setCursorPos(21,6)\\\
9930 term.write(\\\" \\\")\\\
9931 term.setCursorPos(21,7)\\\
9932 term.write(\\\" \\\")\\\
9933 term.setCursorPos(21,8)\\\
9934 term.write(\\\" \\\") --lines\\\
9935 term.setCursorPos(21,9)\\\
9936 term.write(\\\" \\\")\\\
9937 term.setCursorPos(21,10)\\\
9938 term.write(\\\" \\\")\\\
9939 term.setCursorPos(21,11)\\\
9940 term.write(\\\" \\\")\\\
9941 term.setCursorPos(21,12)\\\
9942 term.write(\\\" \\\") --next\\\
9943 term.setCursorPos(26,12)\\\
9944 term.write(\\\" \\\") --next\\\
9945 term.setCursorPos(21,13)\\\
9946 term.write(\\\" \\\")\\\
9947 term.setCursorPos(21,14)\\\
9948 term.write(\\\" \\\")\\\
9949 term.setCursorPos(21,15)\\\
9950 term.write(\\\" \\\")\\\
9951 term.setCursorPos(21,16)\\\
9952 term.write(\\\" \\\")\\\
9953 term.setCursorPos(21,17)\\\
9954 term.write(\\\" \\\")\\\
9955 term.setCursorPos(21,18)\\\
9956 term.write(\\\" \\\")\\\
9957 term.setCursorPos(21,19)\\\
9958 term.write(\\\" \\\")\\\
9959 term.setCursorPos(21,20)\\\
9960 term.write(\\\" \\\")\\\
9961 end\\\
9962\\\
9963 local function updateNumbers()\\\
9964 term.setTextColor(colors.white)\\\
9965 term.setBackgroundColor(colors.black)\\\
9966\\\
9967 term.setCursorPos(22,3)\\\
9968 term.write(lpad(score,5)) --score\\\
9969 term.setCursorPos(22,6)\\\
9970 term.write(lpad(level,5)) --level\\\
9971 term.setCursorPos(22,9)\\\
9972 term.write(lpad(lines,5)) --lines\\\
9973 end\\\
9974\\\
9975 local function drawBlockAt(block,xp,yp,rot)\\\
9976 term.setTextColor(block.fg)\\\
9977 term.setBackgroundColor(block.bg)\\\
9978 for y=1,4 do\\\
9979 for x=1,4 do\\\
9980 if block[rot][y][x]==1 then\\\
9981 term.setCursorPos((xp+x)*2-3,yp+y-1-heightAdjust)\\\
9982 term.write(block.ch)\\\
9983 end\\\
9984 end\\\
9985 end\\\
9986 end\\\
9987\\\
9988 local function eraseBlockAt(block,xp,yp,rot)\\\
9989 term.setTextColor(colors.white)\\\
9990 term.setBackgroundColor(colors.black)\\\
9991 for y=1,4 do\\\
9992 for x=1,4 do\\\
9993 if block[rot][y][x]==1 then\\\
9994 term.setCursorPos((xp+x)*2-3,yp+y-1-heightAdjust)\\\
9995 term.write(\\\" \\\")\\\
9996 end\\\
9997 end\\\
9998 end\\\
9999 end\\\
10000\\\
10001 local function testBlockAt(block,xp,yp,rot)\\\
10002 for y=1,4 do\\\
10003 local ty=yp+y-1\\\
10004 for x=1,4 do\\\
10005 local tx=xp+x-1\\\
10006 if block[rot][y][x]==1 then\\\
10007 if tx>10 or tx<1 or ty>20 or pit[ty][tx]~=0 then\\\
10008 return true\\\
10009 end\\\
10010 end\\\
10011 end\\\
10012 end\\\
10013 end\\\
10014\\\
10015 local function pitBlock(block,xp,yp,rot)\\\
10016 for y=1,4 do\\\
10017 for x=1,4 do\\\
10018 if block[rot][y][x]==1 then\\\
10019 pit[yp+y-1][xp+x-1]=block\\\
10020 end\\\
10021 end\\\
10022 end\\\
10023 end\\\
10024\\\
10025\\\
10026 local function clearPit()\\\
10027 for row=1,20 do\\\
10028 pit[row]={}\\\
10029 for col=1,10 do\\\
10030 pit[row][col]=0\\\
10031 end\\\
10032 end\\\
10033 end\\\
10034\\\
10035\\\
10036\\\
10037 drawScreen()\\\
10038 updateNumbers()\\\
10039\\\
10040 --declare & init the pit\\\
10041 clearPit()\\\
10042\\\
10043\\\
10044\\\
10045 local halt=false\\\
10046 local dropSpeed=speedsByLevel[math.min(level,12)]\\\
10047\\\
10048\\\
10049 local curBlock=next\\\
10050 next=blocks[math.random(1,7)]\\\
10051\\\
10052 local curX, curY, curRot=4, 1, 1\\\
10053 local dropTimer=os.startTimer(dropSpeed)\\\
10054\\\
10055 drawBlockAt(next,11.5,15+heightAdjust,1)\\\
10056 drawBlockAt(curBlock,curX,curY,curRot)\\\
10057\\\
10058 local function redrawPit()\\\
10059 for r=1+heightAdjust,20 do\\\
10060 term.setCursorPos(1,r-heightAdjust)\\\
10061 for c=1,10 do\\\
10062 if pit[r][c]==0 then\\\
10063 term.setTextColor(colors.black)\\\
10064 term.setBackgroundColor(colors.black)\\\
10065 term.write(\\\" \\\")\\\
10066 else\\\
10067 term.setTextColor(pit[r][c].fg)\\\
10068 term.setBackgroundColor(pit[r][c].bg)\\\
10069 term.write(pit[r][c].ch)\\\
10070 end\\\
10071 end\\\
10072 end\\\
10073 end\\\
10074\\\
10075 local function hidePit()\\\
10076 for r=1+heightAdjust,20 do\\\
10077 term.setCursorPos(1,r-heightAdjust)\\\
10078 term.setTextColor(colors.black)\\\
10079 term.setBackgroundColor(colors.black)\\\
10080 term.write(\\\" \\\")\\\
10081 end\\\
10082 end\\\
10083\\\
10084 local function msgBox(message)\\\
10085 local x=math.floor((17-#message)/2)\\\
10086 term.setBackgroundColor(colorass(colors.lightGray,colors.white))\\\
10087 term.setTextColor(colors.black)\\\
10088 term.setCursorPos(x,9)\\\
10089 term.write(\\\"+\\\"..string.rep(\\\"-\\\",#message+2)..\\\"+\\\")\\\
10090 term.setCursorPos(x,10)\\\
10091 term.write(\\\"|\\\")\\\
10092 term.setCursorPos(x+#message+3,10)\\\
10093 term.write(\\\"|\\\")\\\
10094 term.setCursorPos(x,11)\\\
10095 term.write(\\\"+\\\"..string.rep(\\\"-\\\",#message+2)..\\\"+\\\")\\\
10096 term.setTextColor(colors.white)\\\
10097 term.setBackgroundColor(colors.black)\\\
10098 term.setCursorPos(x+1,10)\\\
10099 term.write(\\\" \\\"..message..\\\" \\\")\\\
10100 end\\\
10101\\\
10102 local function clearRows()\\\
10103 local rows={}\\\
10104 for r=1,20 do\\\
10105 local count=0\\\
10106 for c=1,10 do\\\
10107 if pit[r][c]~=0 then\\\
10108 count=count+1\\\
10109 else\\\
10110 break\\\
10111 end\\\
10112 end\\\
10113 if count==10 then\\\
10114 rows[#rows+1]=r\\\
10115 end\\\
10116 end\\\
10117\\\
10118 if #rows>0 then\\\
10119 for i=1,4 do\\\
10120 sleep(.1)\\\
10121 for r=1,#rows do\\\
10122 r=rows[r]\\\
10123 term.setCursorPos(1,r-heightAdjust)\\\
10124 for c=1,10 do\\\
10125 term.setTextColor(pit[r][c].bg)\\\
10126 term.setBackgroundColor(pit[r][c].fg)\\\
10127 term.write(pit[r][c].ch)\\\
10128 end\\\
10129 end\\\
10130 sleep(.1)\\\
10131 for r=1,#rows do\\\
10132 r=rows[r]\\\
10133 term.setCursorPos(1,r-heightAdjust)\\\
10134 for c=1,10 do\\\
10135 term.setTextColor(pit[r][c].fg)\\\
10136 term.setBackgroundColor(pit[r][c].bg)\\\
10137 term.write(pit[r][c].ch)\\\
10138 end\\\
10139 end\\\
10140 end\\\
10141 --now remove the rows and drop everythign else\\\
10142 term.setBackgroundColor(colors.black)\\\
10143 for r=1,#rows do\\\
10144 r=rows[r]\\\
10145 term.setCursorPos(1,r-heightAdjust)\\\
10146 term.write(\\\" \\\")\\\
10147 end\\\
10148 sleep(.25)\\\
10149 for r=1,#rows do\\\
10150 table.remove(pit,rows[r])\\\
10151 table.insert(pit,1,{0,0,0,0,0,0,0,0,0,0})\\\
10152 end\\\
10153 redrawPit()\\\
10154 lines=lines+#rows\\\
10155 score=score+points[#rows]*math.min(level,20)\\\
10156 level=math.floor(lines/10)+initialLevel\\\
10157 dropSpeed=speedsByLevel[math.min(level,12)]\\\
10158 updateNumbers()\\\
10159 end\\\
10160 sleep(.25)\\\
10161 end\\\
10162\\\
10163 local function blockFall()\\\
10164 local result = false\\\
10165 if testBlockAt(curBlock,curX,curY+1,curRot) then\\\
10166 pitBlock(curBlock,curX,curY,curRot)\\\
10167 --detect rows that clear\\\
10168 clearRows()\\\
10169\\\
10170 curBlock=next\\\
10171 curX=4\\\
10172 curY=1\\\
10173 curRot=1\\\
10174 if testBlockAt(curBlock,curX,curY,curRot) then\\\
10175 halt=true\\\
10176 end\\\
10177 drawBlockAt(curBlock,curX,curY,curRot)\\\
10178 eraseBlockAt(next,11.5,15+heightAdjust,1)\\\
10179 next=blocks[math.random(1,7)]\\\
10180 drawBlockAt(next,11.5,15+heightAdjust,1)\\\
10181 return true\\\
10182 else\\\
10183 eraseBlockAt(curBlock,curX,curY,curRot)\\\
10184 curY=curY+1\\\
10185 drawBlockAt(curBlock,curX,curY,curRot)\\\
10186 return false\\\
10187 end\\\
10188 end\\\
10189\\\
10190\\\
10191 while not halt do\\\
10192 local e={os.pullEvent()}\\\
10193 if e[1]==\\\"timer\\\" then\\\
10194 if e[2]==dropTimer then\\\
10195 blockFall()\\\
10196 dropTimer=os.startTimer(dropSpeed)\\\
10197 end\\\
10198 elseif e[1]==\\\"key\\\" then\\\
10199 local key=e[2]\\\
10200 local dx,dy,dr=0,0,0\\\
10201 if key==keys.left or key==keys.a then\\\
10202 dx=-1\\\
10203 elseif key==keys.right or key==keys.d then\\\
10204 dx=1\\\
10205 elseif key==keys.up or key==keys.w then\\\
10206 dr=1\\\
10207 elseif key==keys.down or key==keys.s then\\\
10208 while not blockFall() do end\\\
10209 dropTimer=os.startTimer(dropSpeed)\\\
10210 elseif key==keys.space then\\\
10211 hidePit()\\\
10212 msgBox(\\\"Paused\\\")\\\
10213 while ({os.pullEvent(\\\"key\\\")})[2]~=keys.space do end\\\
10214 redrawPit()\\\
10215 drawBlockAt(curBlock,curX,curY,curRot)\\\
10216 dropTimer=os.startTimer(dropSpeed)\\\
10217 end\\\
10218 if dx+dr~=0 then\\\
10219 if not testBlockAt(curBlock,curX+dx,curY+dy,(dr>0 and curRot%#curBlock+dr or curRot)) then\\\
10220 eraseBlockAt(curBlock,curX,curY,curRot)\\\
10221 curX=curX+dx\\\
10222 curY=curY+dy\\\
10223 curRot=dr==0 and curRot or (curRot%#curBlock+dr)\\\
10224 drawBlockAt(curBlock,curX,curY,curRot)\\\
10225 end\\\
10226 end\\\
10227 elseif e[1]==\\\"term_resize\\\" then\\\
10228 local w,h=term.getSize()\\\
10229 if h==20 then\\\
10230 heightAdjust=0\\\
10231 else\\\
10232 heightAdjust=1\\\
10233 end\\\
10234 redrawPit()\\\
10235 drawBlockAt(curBlock,curX,curY,curRot)\\\
10236 end\\\
10237 end\\\
10238\\\
10239 msgBox(\\\"Game Over!\\\")\\\
10240 while true do\\\
10241 local _,k=os.pullEvent(\\\"key\\\")\\\
10242 if k==keys.space or k==keys.enter then\\\
10243 break\\\
10244 end\\\
10245 end\\\
10246\\\
10247 level = math.min(level,9)\\\
10248end\\\
10249\\\
10250\\\
10251local selected=1\\\
10252local playersDetected=false\\\
10253\\\
10254local function drawMenu()\\\
10255 term.setBackgroundColor(colors.black)\\\
10256 term.setTextColor(colorass(colors.red,colors.white))\\\
10257 term.clear()\\\
10258\\\
10259 local cx,cy=math.floor(width/2),math.floor(height/2)\\\
10260\\\
10261 term.setCursorPos(cx-6,cy-2)\\\
10262 term.write(\\\"F A L L I N G\\\")\\\
10263\\\
10264 if playersDetected then\\\
10265 if selected==0 then\\\
10266 term.setTextColor(colorass(colors.blue,colors.black))\\\
10267 term.setBackgroundColor(colorass(colors.gray,colors.white))\\\
10268 else\\\
10269 term.setTextColor(colorass(colors.lightBlue,colors.white))\\\
10270 term.setBackgroundColor(colors.black)\\\
10271 end\\\
10272 term.setCursorPos(cx-12,cy)\\\
10273 term.write(\\\" Play head-to-head game! \\\")\\\
10274 end\\\
10275\\\
10276 term.setCursorPos(cx-10,cy+1)\\\
10277 if selected==1 then\\\
10278 term.setTextColor(colorass(colors.blue,colors.black))\\\
10279 term.setBackgroundColor(colorass(colors.lightGray,colors.white))\\\
10280 else\\\
10281 term.setTextColor(colorass(colors.lightBlue,colors.white))\\\
10282 term.setBackgroundColor(colors.black)\\\
10283 end\\\
10284 term.write(\\\" Play from level: <\\\" .. level .. \\\"> \\\")\\\
10285\\\
10286 term.setCursorPos(cx-3,cy+3)\\\
10287 if selected==2 then\\\
10288 term.setTextColor(colorass(colors.blue,colors.black))\\\
10289 term.setBackgroundColor(colorass(colors.lightGray,colors.white))\\\
10290 else\\\
10291 term.setTextColor(colorass(colors.lightBlue,colors.white))\\\
10292 term.setBackgroundColor(colors.black)\\\
10293 end\\\
10294 term.write(\\\" Quit \\\")\\\
10295end\\\
10296\\\
10297\\\
10298local function runMenu()\\\
10299 drawMenu()\\\
10300\\\
10301 while true do\\\
10302 local event={os.pullEvent()}\\\
10303 if event[1]==\\\"key\\\" then\\\
10304 local key=event[2]\\\
10305 if key==keys.right or key==keys.d and selected==1 then\\\
10306 level=math.min(level+1,9)\\\
10307 drawMenu()\\\
10308 elseif key==keys.left or key==keys.a and selected==1 then\\\
10309 level=math.max(level-1,1)\\\
10310 drawMenu()\\\
10311 elseif key>=keys.one and key<=keys.nine and selected==1 then\\\
10312 level=(key-keys.one) + 1\\\
10313 drawMenu()\\\
10314 elseif key==keys.up or key==keys.w then\\\
10315 selected=selected-1\\\
10316 if selected==0 then\\\
10317 selected=2\\\
10318 end\\\
10319 drawMenu()\\\
10320 elseif key==keys.down or key==keys.s then\\\
10321 selected=selected%2+1\\\
10322 drawMenu()\\\
10323 elseif key==keys.enter or key==keys.space then\\\
10324 break --begin play!\\\
10325 end\\\
10326 end\\\
10327 end\\\
10328end\\\
10329\\\
10330while true do\\\
10331 runMenu()\\\
10332 if selected==2 then\\\
10333 break\\\
10334 end\\\
10335\\\
10336 playGame()\\\
10337end\\\
10338\\\
10339\\\
10340term.setTextColor(colors.white)\\\
10341term.setBackgroundColor(colors.black)\\\
10342term.clear()\\\
10343term.setCursorPos(1,1)\",\
10344 [ \"programs/delete.lua\" ] = \"\\\
10345local tArgs = { ... }\\\
10346if #tArgs < 1 then\\\
10347 print( \\\"Usage: rm <path>\\\" )\\\
10348 return\\\
10349end\\\
10350\\\
10351local sPath = shell.resolve( tArgs[1] )\\\
10352local tFiles = fs.find( sPath )\\\
10353if #tFiles > 0 then\\\
10354 for n,sFile in ipairs( tFiles ) do\\\
10355 fs.delete( sFile )\\\
10356 end\\\
10357else\\\
10358 printError( \\\"No matching files\\\" )\\\
10359end\",\
10360 [ \"programs/command/exec.lua\" ] = \"\\\
10361local tArgs = { ... }\\\
10362if not commands then\\\
10363 printError( \\\"Requires a Command Computer.\\\" )\\\
10364 return\\\
10365end\\\
10366if #tArgs == 0 then\\\
10367 printError( \\\"Usage: exec <command>\\\" )\\\
10368 return\\\
10369end\\\
10370\\\
10371local function printSuccess( text )\\\
10372 if term.isColor() then\\\
10373 term.setTextColor( colors.green )\\\
10374 end\\\
10375 print( text )\\\
10376 term.setTextColor( colors.white )\\\
10377end\\\
10378\\\
10379local sCommand = string.lower( tArgs[1] )\\\
10380for n=2,#tArgs do\\\
10381 sCommand = sCommand .. \\\" \\\" .. tArgs[n]\\\
10382end\\\
10383\\\
10384local bResult, tOutput = commands.exec( sCommand )\\\
10385if bResult then\\\
10386 printSuccess( \\\"Success\\\" )\\\
10387 if #tOutput > 0 then\\\
10388 for n=1,#tOutput do\\\
10389 print( tOutput[n] )\\\
10390 end\\\
10391 end\\\
10392else\\\
10393 printError( \\\"Failed\\\" )\\\
10394 if #tOutput > 0 then\\\
10395 for n=1,#tOutput do\\\
10396 print( tOutput[n] )\\\
10397 end\\\
10398 end\\\
10399end\",\
10400 [ \"help/helpapi.txt\" ] = \"Functions in the help API:\\\
10401help.setPath( path )\\\
10402help.lookup( topic )\\\
10403help.topics()\\\
10404help.completeTopic( topic )\",\
10405 [ \"programs/cd.lua\" ] = \"\\\
10406local tArgs = { ... }\\\
10407if #tArgs < 1 then\\\
10408 print( \\\"Usage: cd <path>\\\" )\\\
10409 return\\\
10410end\\\
10411\\\
10412local sNewDir = shell.resolve( tArgs[1] )\\\
10413if fs.isDir( sNewDir ) then\\\
10414 shell.setDir( sNewDir )\\\
10415else\\\
10416 print( \\\"Not a directory\\\" )\\\
10417 return\\\
10418end\",\
10419 [ \"programs/alias.lua\" ] = \"\\\
10420local tArgs = { ... }\\\
10421if #tArgs > 2 then\\\
10422 print( \\\"Usage: alias <alias> <program>\\\" )\\\
10423 return\\\
10424end\\\
10425\\\
10426local sAlias = tArgs[1]\\\
10427local sProgram = tArgs[2]\\\
10428\\\
10429if sAlias and sProgram then\\\
10430 -- Set alias\\\
10431 shell.setAlias( sAlias, sProgram )\\\
10432elseif sAlias then\\\
10433 -- Clear alias\\\
10434 shell.clearAlias( sAlias )\\\
10435else\\\
10436 -- List aliases\\\
10437 local tAliases = shell.aliases()\\\
10438 local tList = {}\\\
10439 for sAlias, sCommand in pairs( tAliases ) do\\\
10440 table.insert( tList, sAlias..\\\":\\\"..sCommand )\\\
10441 end\\\
10442 table.sort( tList )\\\
10443 textutils.pagedTabulate( tList )\\\
10444end\",\
10445 [ \"help/apis.txt\" ] = \"apis lists the currently loaded APIs available to programs in CraftOS.\\\
10446\\\
10447Type \\\"help <api>\\\" to see help for a specific api.\\\
10448Call os.loadAPI( path ) to load extra apis.\",\
10449 [ \"programs/list.lua\" ] = \"\\\
10450local tArgs = { ... }\\\
10451\\\
10452-- Get all the files in the directory\\\
10453local sDir = shell.dir()\\\
10454if tArgs[1] ~= nil then\\\
10455 sDir = shell.resolve( tArgs[1] )\\\
10456end\\\
10457\\\
10458if not fs.isDir( sDir ) then\\\
10459 printError( \\\"Not a directory\\\" )\\\
10460 return\\\
10461end\\\
10462\\\
10463-- Sort into dirs/files, and calculate column count\\\
10464local tAll = fs.list( sDir )\\\
10465local tFiles = {}\\\
10466local tDirs = {}\\\
10467\\\
10468local bShowHidden = settings.get( \\\"list.show_hidden\\\" )\\\
10469for n, sItem in pairs( tAll ) do\\\
10470 if bShowHidden or string.sub( sItem, 1, 1 ) ~= \\\".\\\" then\\\
10471 local sPath = fs.combine( sDir, sItem )\\\
10472 if fs.isDir( sPath ) then\\\
10473 table.insert( tDirs, sItem )\\\
10474 else\\\
10475 table.insert( tFiles, sItem )\\\
10476 end\\\
10477 end\\\
10478end\\\
10479table.sort( tDirs )\\\
10480table.sort( tFiles )\\\
10481\\\
10482if term.isColour() then\\\
10483 textutils.pagedTabulate( colors.green, tDirs, colors.white, tFiles )\\\
10484else\\\
10485 textutils.pagedTabulate( tDirs, tFiles )\\\
10486end\",\
10487 [ \"programs/advanced/bg.lua\" ] = \"\\\
10488if not shell.openTab then\\\
10489 printError( \\\"Requires multishell\\\" )\\\
10490 return\\\
10491end\\\
10492\\\
10493local tArgs = { ... }\\\
10494if #tArgs > 0 then\\\
10495 shell.openTab( table.unpack( tArgs ) )\\\
10496else\\\
10497 shell.openTab( \\\"shell\\\" )\\\
10498end\",\
10499 [ \"programs/fun/advanced/levels/6.dat\" ] = \"4\\\
105007777777777\\\
105017288888837\\\
1050278 87\\\
10503788888b 87\\\
10504788888b 87\\\
10505788888b 87\\\
10506788888b 87\\\
1050778 87\\\
105087188888807\\\
105097777777777\",\
10510 [ \"help/printers.txt\" ] = \"The Printer is a peripheral device available for CraftOS. Type \\\"help peripheral\\\" to learn about using the Peripheral API to connect with peripherals. When a Printer is connected, peripheral.getType() will return \\\"printer\\\".\\\
10511\\\
10512Methods exposed by the Printer:\\\
10513getInkLevel()\\\
10514getPaperLevel()\\\
10515newPage()\\\
10516setPageTitle( title )\\\
10517getPageSize()\\\
10518setCursorPos( x, y )\\\
10519getCursorPos()\\\
10520write( text )\\\
10521endPage()\",\
10522 [ \"help/lua.txt\" ] = \"lua is an interactive prompt for the lua programming language. It's a useful tool for learning the language.\",\
10523 [ \"help/changelog.txt\" ] = \"New Features in ComputerCraft 1.80:\\\
10524\\\
10525* Added .getResponseHeaders() to HTTP responses.\\\
10526* Return a HTTP response when a HTTP error occurs.\\\
10527* Added a GUI to change ComputerCraft config options.\\\
10528* os.time() and os.day() now accept parameters to give the real world time.\\\
10529* Added os.epoch()\\\
10530* Monitor text now glows in the dark.\\\
10531* Added a \\\"Pocket Computer upgrade API\\\" so mod developers can add their own pocket upgrades.\\\
10532* Added pocket.equipBack()/pocket.unequipBack() to add/remove pocket upgrades.\\\
10533* Added term.setPaletteColor()/term.getPaletteColor() to change/check colors\\\
10534* Added colors.rgb8()/colours.rgb8() \\\
10535* Performance improvements to fs.find\\\
10536* Requires the player to be interacting with the computer when typing\\\
10537* Disk labels are limited to 32 characters\\\
10538* Labels can now only include characters within the printable range ( to ~)\\\
10539* Various model improvements\\\
10540* There is now a configurable file descriptor limit\\\
10541* Threads are now daemon threads\\\
10542* Termination signals are now sent unless the computer is off\\\
10543* Fixed compilation errors\\\
10544* Now handles tile entity changes\\\
10545* GPS coordinates now have to be numbers\\\
10546* Turtle upgrades now act as tools and peripherals\\\
10547* The Filesystem.list result is now sorted\\\
10548* The number of values to unpack can now be manually specified\\\
10549* Small terminal & monitor rendering improvements\\\
10550* General improvements to the documentation\\\
10551* Redstone inputs are no longer reset when adding peripherals\\\
10552* Turtles now use tinting\\\
10553* shell.resolveProgram now picks up on *.lua files\\\
10554* Fixed a handful of bugs in ComputerCraft\\\
10555* Added speaker block, turtle upgrade, pocket upgrade, and peripheral api\\\
10556* Startup can now be a directory containing multiple startup files\\\
10557* Added .getLabel to the computer peripheral\\\
10558\\\
10559New Features in ComputerCraft 1.79:\\\
10560\\\
10561* Ported ComputerCraftEdu to Minecraft 1.8.9\\\
10562* Fixed a handful of bugs in ComputerCraft\\\
10563\\\
10564New Features in ComputerCraft 1.77:\\\
10565\\\
10566* Ported to Minecraft 1.8.9\\\
10567* Added \\\"settings\\\" API\\\
10568* Added \\\"set\\\" and \\\"wget\\\" programs\\\
10569* Added settings to disable multishell, startup scripts, and tab completion on a per-computer basis. The default values for these settings can be customised in ComputerCraft.cfg\\\
10570* All Computer and Turtle items except Command Computers can now be mounted in Disk Drives\\\
10571\\\
10572New Features in ComputerCraft 1.76:\\\
10573\\\
10574* Ported to Minecraft 1.8\\\
10575* Added Ender Modems for cross-dimensional communication\\\
10576* Fixed handling of 8-bit characters. All the characters in the ISO 8859-1 codepage can now be displayed\\\
10577* Added some extra graphical characters in the unused character positions, including a suite of characters for Teletext style drawing\\\
10578* Added support for the new commands in Minecraft 1.8 to the Command Computer\\\
10579* The return values of turtle.inspect() and commands.getBlockInfo() now include blockstate information\\\
10580* Added commands.getBlockInfos() function for Command Computers\\\
10581* Added new \\\"peripherals\\\" program\\\
10582* Replaced the \\\"_CC_VERSION\\\" and \\\"_MC_VERSION\\\" constants with a new \\\"_HOST\\\" constant\\\
10583* Shortened the length of time that \\\"Ctrl+T\\\", \\\"Ctrl+S\\\" and \\\"Ctrl+R\\\" must be held down for to terminate, shutdown and reboot the computer\\\
10584* textutils.serialiseJSON() now takes an optional parameter allowing it to produce JSON text with unquoted object keys. This is used by all autogenerated methods in the \\\"commands\\\" api except for \\\"title\\\" and \\\"tellraw\\\"\\\
10585* Fixed many bugs\\\
10586\\\
10587New Features in ComputerCraft 1.75:\\\
10588\\\
10589* Fixed monitors sometimes rendering without part of their text.\\\
10590* Fixed a regression in the \\\"bit\\\" API.\\\
10591\\\
10592New Features in ComputerCraft 1.74:\\\
10593\\\
10594* Added tab completion to \\\"edit\\\", \\\"lua\\\" and the shell.\\\
10595* Added textutils.complete(), fs.complete(), shell.complete(), shell.setCompletionFunction() and help.complete().\\\
10596* Added tab completion options to read().\\\
10597* Added \\\"key_up\\\" and \\\"mouse_up\\\" events.\\\
10598* Non-advanced terminals now accept both grey colours.\\\
10599* Added term.getTextColour(), term.getBackgroundColour() and term.blit().\\\
10600* Improved the performance of text rendering on Advanced Computers.\\\
10601* Added a \\\"Run\\\" button to the edit program on Advanced Computers.\\\
10602* Turtles can now push players and entities (configurable).\\\
10603* Turtles now respect server spawn protection (configurable).\\\
10604* Added a turtle permissions API for mod authors.\\\
10605* Implemented a subset of the Lua 5.2 API so programs can be written against it now, ahead of a future Lua version upgrade.\\\
10606* Added a config option to disable parts of the Lua 5.1 API which will be removed when a future Lua version upgrade happens.\\\
10607* Command Computers can no longer be broken by survival players.\\\
10608* Fixed the \\\"pick block\\\" key not working on ComputerCraft items in creative mode.\\\
10609* Fixed the \\\"edit\\\" program being hard to use on certain European keyboards.\\\
10610* Added \\\"_CC_VERSION\\\" and \\\"_MC_VERSION\\\" constants.\\\
10611\\\
10612New Features in ComputerCraft 1.73:\\\
10613\\\
10614* The \\\"exec\\\" program, commands.exec() and all related Command Computer functions now return the console output of the command.\\\
10615* Fixed two multiplayer crash bugs.\\\
10616\\\
10617New Features in ComputerCraft 1.7:\\\
10618\\\
10619* Added Command Computers\\\
10620* Added new API: commands\\\
10621* Added new programs: commands, exec\\\
10622* Added textutils.serializeJSON()\\\
10623* Added ILuaContext.executeMainThreadTask() for peripheral developers\\\
10624* Disk Drives and Printers can now be renamed with Anvils\\\
10625* Fixed various bugs, crashes and exploits\\\
10626* Fixed problems with HD texture packs\\\
10627* Documented the new features in the in-game help\\\
10628\\\
10629New Features in ComputerCraft 1.65:\\\
10630\\\
10631* Fixed a multiplayer-only crash with turtle.place()\\\
10632* Fixed some problems with http.post()\\\
10633* Fixed fs.getDrive() returning incorrect results on remote peripherals\\\
10634\\\
10635New Features in ComputerCraft 1.64:\\\
10636\\\
10637* Ported to Minecraft 1.7.10\\\
10638* New turtle functions: turtle.inspect(), turtle.inspectUp(), turtle.inspectDown(), turtle.getItemDetail()\\\
10639* Lots of bug and crash fixes, a huge stability improvement over previous versions\\\
10640\\\
10641New Features in ComputerCraft 1.63:\\\
10642\\\
10643* Turtles can now be painted with dyes, and cleaned with water buckets\\\
10644* Added a new game: Redirection - ComputerCraft Edition\\\
10645* Turtle label nameplates now only show when the Turtle is moused-over\\\
10646* The HTTP API is now enabled by default, and can be configured with a whitelist of permitted domains\\\
10647* http.get() and http.post() now accept parameters to control the request headers\\\
10648* New fs function: fs.getDir( path )\\\
10649* Fixed some bugs\\\
10650\\\
10651New Features in ComputerCraft 1.62:\\\
10652\\\
10653* Added IRC-style commands to the \\\"chat\\\" program\\\
10654* Fixed some bugs and crashes\\\
10655\\\
10656New Features in ComputerCraft 1.6:\\\
10657\\\
10658* Added Pocket Computers\\\
10659* Added a multi-tasking system for Advanced Computers and Turtles\\\
10660* Turtles can now swap out their tools and peripherals at runtime\\\
10661* Turtles can now carry two tools or peripherals at once in any combination\\\
10662* Turtles and Computers can now be labelled using Name Tags and Anvils\\\
10663* Added a configurable fuel limit for Turtles\\\
10664* Added hostnames, protocols and long distance routing to the rednet API\\\
10665* Added a peer-to-peer chat program to demonstrate new rednet capabilities\\\
10666* Added a new game, only on Pocket Computers: \\\"falling\\\" by GopherATL\\\
10667* File system commands in the shell now accept wildcard arguments\\\
10668* The shell now accepts long arguments in quotes\\\
10669* Terminal redirection now no longer uses a stack-based system. Instead: term.current() gets the current terminal object and term.redirect() replaces it. term.restore() has been removed.\\\
10670* Added a new Windowing API for addressing sub-areas of the terminal\\\
10671* New programs: fg, bg, multishell, chat, repeat, redstone, equip, unequip\\\
10672* Improved programs: copy, move, delete, rename, paint, shell\\\
10673* Removed programs: redset, redprobe, redpulse\\\
10674* New APIs: window, multishell\\\
10675* New turtle functions: turtle.equipLeft() and turtle.equipRight()\\\
10676* New peripheral functions: peripheral.find( [type] )\\\
10677* New rednet functions: rednet.host( protocol, hostname ), rednet.unhost( protocol ), rednet.locate( protocol, [hostname] )\\\
10678* New fs function: fs.find( wildcard )\\\
10679* New shell functions: shell.openTab(), shell.switchTab( [number] )\\\
10680* New event \\\"term_resize\\\" fired when the size of a terminal changes\\\
10681* Improved rednet functions: rednet.send(), rednet.broadcast() and rednet.receive() now take optional protocol parameters\\\
10682* turtle.craft(0) and turtle.refuel(0) now return true if there is a valid recipe or fuel item, but do not craft of refuel anything\\\
10683* turtle.suck( [limit] ) can now be used to limit the number of items picked up\\\
10684* Users of turtle.dig() and turtle.attack() can now specify which side of the turtle to look for a tool to use (by default, both will be considered)\\\
10685* textutils.serialise( text ) now produces human-readable output\\\
10686* Refactored most of the codebase and fixed many old bugs and instabilities, turtles should never ever lose their content now\\\
10687* Fixed the \\\"turtle_inventory\\\" event firing when it shouldn't have\\\
10688* Added error messages to many more turtle functions after they return false\\\
10689* Documented all new programs and API changes in the \\\"help\\\" system\\\
10690\\\
10691New Features in ComputerCraft 1.58:\\\
10692\\\
10693* Fixed a long standing bug where turtles could lose their identify if they travel too far away\\\
10694* Fixed use of deprecated code, ensuring mod compatibility with the latest versions of Minecraft Forge, and world compatibility with future versions of Minecraft\\\
10695\\\
10696New Features in ComputerCraft 1.57:\\\
10697\\\
10698* Ported to Minecraft 1.6.4\\\
10699* Added two new Treasure Disks: Conway's Game of Life by vilsol and Protector by fredthead\\\
10700* Fixed a very nasty item duplication bug\\\
10701\\\
10702New Features in ComputerCraft 1.56:\\\
10703\\\
10704* Added Treasure Disks: Floppy Disks in dungeons which contain interesting community made programs. Find them all!\\\
10705* All turtle functions now return additional error messages when they fail.\\\
10706* Resource Packs with Lua Programs can now be edited when extracted to a folder, for easier editing.\\\
10707\\\
10708New Features in ComputerCraft 1.55:\\\
10709\\\
10710* Ported to Minecraft 1.6.2\\\
10711* Added Advanced Turtles\\\
10712* Added \\\"turtle_inventory\\\" event. Fires when any change is made to the inventory of a turtle\\\
10713* Added missing functions io.close, io.flush, io.input, io.lines, io.output\\\
10714* Tweaked the screen colours used by Advanced Computers, Monitors and Turtles\\\
10715* Added new features for Peripheral authors\\\
10716* Lua programs can now be included in Resource Packs\\\
10717\\\
10718New Features in ComputerCraft 1.52:\\\
10719\\\
10720* Ported to Minecraft 1.5.1\\\
10721\\\
10722New Features in ComputerCraft 1.51:\\\
10723\\\
10724* Ported to Minecraft 1.5\\\
10725* Added Wired Modems\\\
10726* Added Networking Cables\\\
10727* Made Wireless Modems more expensive to craft\\\
10728* New redstone API functions: getAnalogInput(), setAnalogOutput(), getAnalogOutput()\\\
10729* Peripherals can now be controlled remotely over wired networks. New peripheral API function: getNames()\\\
10730* New event: \\\"monitor_resize\\\" when the size of a monitor changes\\\
10731* Except for labelled computers and turtles, ComputerCraft blocks no longer drop items in creative mode\\\
10732* The pick block function works in creative mode now works for all ComputerCraft blocks\\\
10733* All blocks and items now use the IDs numbers assigned by FTB by default\\\
10734* Fixed turtles sometimes placing blocks with incorrect orientations\\\
10735* Fixed Wireless modems being able to send messages to themselves\\\
10736* Fixed turtle.attack() having a very short range\\\
10737* Various bugfixes\\\
10738\\\
10739New Features in ComputerCraft 1.5:\\\
10740\\\
10741* Redesigned Wireless Modems; they can now send and receive on multiple channels, independent of the computer ID. To use these features, interface with modem peripherals directly. The rednet API still functions as before\\\
10742* Floppy Disks can now be dyed with multiple dyes, just like armour\\\
10743* The \\\"excavate\\\" program now retains fuel in it's inventory, so can run unattended\\\
10744* turtle.place() now tries all possible block orientations before failing\\\
10745* turtle.refuel(0) returns true if a fuel item is selected\\\
10746* turtle.craft(0) returns true if the inventory is a valid recipe\\\
10747* The in-game help system now has documentation for all the peripherals and their methods, including the new modem functionality\\\
10748* A romantic surprise\\\
10749\\\
10750New Features in ComputerCraft 1.48:\\\
10751\\\
10752* Ported to Minecraft 1.4.6\\\
10753* Advanced Monitors now emit a \\\"monitor_touch\\\" event when right clicked\\\
10754* Advanced Monitors are now cheaper to craft\\\
10755* Turtles now get slightly less fuel from items\\\
10756* Computers can now interact with Command Blocks (if enabled in ComputerCraft.cfg)\\\
10757* New API function: os.day()\\\
10758* A christmas surprise\\\
10759\\\
10760New Features in ComputerCraft 1.45:\\\
10761\\\
10762* Added Advanced Computers\\\
10763* Added Advanced Monitors\\\
10764* New program: paint by nitrogenfingers\\\
10765* New API: paintutils\\\
10766* New term functions: term.setBackgroundColor, term.setTextColor, term.isColor\\\
10767* New turtle function: turtle.transferTo\\\
10768\\\
10769New Features in ComputerCraft 1.43:\\\
10770\\\
10771* Added Printed Pages\\\
10772* Added Printed Books\\\
10773* Fixed incompatibility with Forge 275 and above\\\
10774* Labelled Turtles now keep their fuel when broken\\\
10775\\\
10776New Features in ComputerCraft 1.42:\\\
10777\\\
10778* Ported to Minecraft 1.3.2\\\
10779* Added Printers\\\
10780* Floppy Disks can be dyed different colours\\\
10781* Wireless Crafty Turtles can now be crafted\\\
10782* New textures\\\
10783* New forge config file\\\
10784* Bug fixes\\\
10785\\\
10786New Features in ComputerCraft 1.4:\\\
10787\\\
10788* Ported to Forge Mod Loader. ComputerCraft can now be ran directly from the .zip without extraction\\\
10789* Added Farming Turtles\\\
10790* Added Felling Turtles\\\
10791* Added Digging Turtles\\\
10792* Added Melee Turtles\\\
10793* Added Crafty Turtles\\\
10794* Added 14 new Turtle Combinations accessible by combining the turtle upgrades above\\\
10795* Labelled computers and turtles can now be crafted into turtles or other turtle types without losing their ID, label and data\\\
10796* Added a \\\"Turtle Upgrade API\\\" for mod developers to create their own tools and peripherals for turtles\\\
10797* Turtles can now attack entities with turtle.attack(), and collect their dropped items\\\
10798* Turtles can now use turtle.place() with any item the player can, and can interact with entities\\\
10799* Turtles can now craft items with turtle.craft()\\\
10800* Turtles can now place items into inventories with turtle.drop()\\\
10801* Changed the behaviour of turtle.place() and turtle.drop() to only consider the currently selected slot\\\
10802* Turtles can now pick up items from the ground, or from inventories, with turtle.suck()\\\
10803* Turtles can now compare items in their inventories\\\
10804* Turtles can place signs with text on them with turtle.place( [signText] )\\\
10805* Turtles now optionally require fuel items to move, and can refuel themselves\\\
10806* The size of the the turtle inventory has been increased to 16\\\
10807* The size of the turtle screen has been increased\\\
10808* New turtle functions: turtle.compareTo( [slotNum] ), turtle.craft(), turtle.attack(), turtle.attackUp(), turtle.attackDown(), turtle.dropUp(), turtle.dropDown(), turtle.getFuelLevel(), turtle.refuel()\\\
10809* New disk function: disk.getID()\\\
10810* New turtle programs: craft, refuel\\\
10811* \\\"excavate\\\" program now much smarter: Will return items to a chest when full, attack mobs, and refuel itself automatically\\\
10812* New API: keys\\\
10813* Added optional Floppy Disk and Hard Drive space limits for computers and turtles\\\
10814* New fs function: fs.getFreeSpace( path ), also fs.getDrive() works again\\\
10815* The send and receive range of wireless modems now increases with altitude, allowing long range networking from high-altitude computers (great for GPS networks)\\\
10816* http.request() now supports https:// URLs\\\
10817* Right clicking a Disk Drive with a Floppy Disk or a Record when sneaking will insert the item into the Disk Drive automatically\\\
10818* The default size of the computer screen has been increased\\\
10819* Several stability and security fixes. LuaJ can now no longer leave dangling threads when a computer is unloaded, turtles can no longer be destroyed by tree leaves or walking off the edge of the loaded map. Computers no longer crash when used with RedPower frames.\\\
10820\\\
10821New Features in ComputerCraft 1.31:\\\
10822\\\
10823* Ported to Minecraft 1.2.3\\\
10824* Added Monitors (thanks to Cloudy)\\\
10825* Updated LuaJ to a newer, less memory hungry version\\\
10826* rednet_message event now has a third parameter, \\\"distance\\\", to support position triangulation.\\\
10827* New programs: gps, monitor, pastebin.\\\
10828* Added a secret program. Use with large monitors!\\\
10829* New apis: gps, vector\\\
10830* New turtle functions: turtle.compare(), turtle.compareUp(), turtle.compareDown(), turtle.drop( quantity )\\\
10831* New http functions: http.post().\\\
10832* New term functions: term.redirect(), term.restore()\\\
10833* New textutils functions: textutils.urlEncode()\\\
10834* New rednet functions: rednet.isOpen()\\\
10835* New config options: modem_range, modem_rangeDuringStorm\\\
10836* Bug fixes, program tweaks, and help updates\\\
10837\\\
10838New Features in ComputerCraft 1.3:\\\
10839\\\
10840* Ported to Minecraft Forge\\\
10841* Added Turtles\\\
10842* Added Wireless Modems\\\
10843* Added Mining Turtles\\\
10844* Added Wireless Turtles\\\
10845* Added Wireless Mining Turtles\\\
10846* Computers and Disk Drives no longer get destroyed by water.\\\
10847* Computers and Turtles can now be labelled with the label program, and labelled devices keep their state when destroyed.\\\
10848* Computers/Turtles can connect to adjacent devices, and turn them on and off\\\
10849* User programs now give line numbers in their error messages\\\
10850* New APIs: turtle, peripheral\\\
10851* New programs for turtles: tunnel, excavate, go, turn, dance\\\
10852* New os functions: os.getComputerLabel(), os.setComputerLabel()\\\
10853* Added \\\"filter\\\" parameter to os.pullEvent()\\\
10854* New shell function: shell.getCurrentProgram()\\\
10855* New textutils functions: textutils.serialize(), textutils.unserialize(), textutils.tabulate(), textutils.pagedTabulate(), textutils.slowWrite()\\\
10856* New io file function: file:lines()\\\
10857* New fs function: fs.getSize()\\\
10858* Disk Drives can now play records from other mods\\\
10859* Bug fixes, program tweaks, and help updates\\\
10860\\\
10861New Features in ComputerCraft 1.2:\\\
10862\\\
10863* Added Disk Drives and Floppy Disks\\\
10864* Added Ctrl+T shortcut to terminate the current program (hold)\\\
10865* Added Ctrl+S shortcut to shutdown the computer (hold)\\\
10866* Added Ctrl+R shortcut to reboot the computer (hold)\\\
10867* New Programs: alias, apis, copy, delete, dj, drive, eject, id, label, list, move, reboot, redset, rename, time, worm.\\\
10868* New APIs: bit, colours, disk, help, rednet, parallel, textutils.\\\
10869* New color functions: colors.combine(), colors.subtract(), colors.test()\\\
10870* New fs functions: fs.getName(), new modes for fs.open()\\\
10871* New os functions: os.loadAPI(), os.unloadAPI(),\\\
10872os.clock(), os.time(), os.setAlarm(),\\\
10873os.reboot(), os.queueEvent()\\\
10874* New redstone function: redstone.getSides()\\\
10875* New shell functions: shell.setPath(), shell.programs(), shell.resolveProgram(), shell.setAlias()\\\
10876* Lots of updates to the help pages\\\
10877* Bug fixes\\\
10878\\\
10879New Features in ComputerCraft 1.1:\\\
10880\\\
10881* Added Multiplayer support throughout.\\\
10882* Added connectivity with RedPower bundled cables\\\
10883* Added HTTP api, enabled via the mod config, to allow computers to access the real world internet\\\
10884* Added command history to the shell.\\\
10885* Programs which spin in an infinite loop without yielding will no longer freeze minecraft\\\
10886* Help updates and bug fixes\\\
10887\\\
10888New Features in ComputerCraft 1.0:\\\
10889\\\
10890* First Release!\",\
10891 [ \"help/emu.txt\" ] = \"USAGE\\\
10892\\\
10893* emu close\\\
10894Closes the current emulated computer, without affecting the others. Can be called from within programs via ccemux.closeEmu().\\\
10895\\\
10896* emu open [id]\\\
10897Opens a new emulated computer, with the given ID (if specified) or with the next ID. Can be called from within programs via ccemux.openEmu() or ccemux.openEmu(id)\\\
10898\\\
10899* emu data\\\
10900This will open the CCEmuX data dir (where config files and computer save folders are stored) in your default file browser. Can be called from within programs via ccemux.openDataDir(). Note that it may fail on some Linux systems (i.e. if you don't have a DE installed)\\\
10901\\\
10902* emu config\\\
10903Opens an interface to edit the CCEmuX configuration. Note that not all rendering backends support this.\\\
10904\\\
10905CREDITS\\\
10906\\\
10907* Lignum - developer\\\
10908* apemanzilla - developer\\\
10909* Lemmmy - contributions to ccemux API and program\\\
10910* SquidDev - CCTweaks support and general help during development\\\
10911* BombBloke - created and allowed us to use the HD font\\\
10912\\\
10913LICENSE INFORMATION\\\
10914\\\
10915CCEmuX is licensed under the MIT license. The complete source code and license for CCEmuX can be found at https://github.com/Lignum/CCEmuX\\\
10916\\\
10917CCEmuX is designed around and includes ComputerCraft, a Minecraft modification by Daniel \\\"dan200\\\" Ratcliffe, which is licensed under the ComputerCraft Public License. The complete source code and license for ComputerCraft can be found at https://github.com/dan200/ComputerCraft\",\
10918 [ \"help/pastebin.txt\" ] = \"pastebin is a program for uploading files to and downloading files from pastebin.com. This is useful for sharing programs with other players.\\\
10919The HTTP API must be enabled in ComputerCraft.cfg to use this program.\\\
10920\\\
10921ex:\\\
10922\\\"pastebin put foo\\\" will upload the file \\\"foo\\\" to pastebin.com, and print the URL.\\\
10923\\\"pastebin get xq5gc7LB foo\\\" will download the file from the URL http://pastebin.com/xq5gc7LB, and save it as \\\"foo\\\".\\\
10924\\\"pastebin run CxaWmPrX\\\" will download the file from the URL http://pastebin.com/CxaWmPrX, and immediately run it.\",\
10925 [ \"help/monitors.txt\" ] = \"The Monitor is a peripheral device available for CraftOS. Type \\\"help peripheral\\\" to learn about using the Peripheral API to connect with peripherals. When a Monitor is connected, peripheral.getType() will return \\\"monitor\\\". A wrapped monitor can be used with term.redirect() to send all terminal output to the monitor.\\\
10926\\\
10927Methods exposed by the Monitor:\\\
10928write( text )\\\
10929blit( text, textColor, backgroundColor )\\\
10930clear()\\\
10931clearLine()\\\
10932getCursorPos()\\\
10933setCursorPos( x, y )\\\
10934setCursorBlink( blink )\\\
10935isColor()\\\
10936setTextColor( color )\\\
10937setBackgroundColor( color )\\\
10938getTextColor()\\\
10939getBackgroundColor()\\\
10940getSize()\\\
10941scroll( n )\\\
10942setPaletteColor( color, r, g, b )\\\
10943getPaletteColor( color )\\\
10944\\\
10945Events fired by the Monitor:\\\
10946\\\"monitor_touch\\\" when an Advanced Monitor is touched by the player. Arguments are name, x, y\\\
10947\\\"monitor_resize\\\" when the size of a Monitor changes. Argument is the name of the monitor.\",\
10948 [ \"modules/command/.ignoreme\" ] = \"--[[\\\
10949Alright then, don't ignore me. This file is to ensure the existence of the \\\"modules/command\\\" folder.\\\
10950You can use this folder to add modules who can be loaded with require() to your Resourcepack.\\\
10951]]\",\
10952 [ \"help/window.txt\" ] = \"Functions in the window API:\\\
10953window.create( parent, x, y, width, height, visible )\\\
10954\\\
10955Windows created with the window API have the following methods:\\\
10956write( text )\\\
10957blit( text, textColor, backgroundColor )\\\
10958clear()\\\
10959clearLine()\\\
10960getCursorPos()\\\
10961setCursorPos( x, y )\\\
10962setCursorBlink( blink )\\\
10963isColor()\\\
10964setTextColor( color )\\\
10965setBackgroundColor( color )\\\
10966getTextColor()\\\
10967getBackgroundColor()\\\
10968getSize()\\\
10969scroll( n )\\\
10970setVisible( bVisible )\\\
10971redraw()\\\
10972restoreCursor()\\\
10973getPosition()\\\
10974reposition( x, y, width, height )\\\
10975getPaletteColor( color )\\\
10976setPaletteColor( color, r, g, b )\",\
10977 [ \"help/commands.txt\" ] = \"On a Command Computer, \\\"commands\\\" will list all the commands available for use. Use \\\"exec\\\" to execute them.\\\
10978Type \\\"help commandsapi\\\" for help using commands in lua programs.\",\
10979 [ \"apis/io.lua\" ] = \"-- Definition for the IO API\\\
10980local typeOf = _G.type\\\
10981\\\
10982--- If we return nil then close the file, as we've reached the end.\\\
10983-- We use this weird wrapper function as we wish to preserve the varargs\\\
10984local function checkResult(handle, ...)\\\
10985 if ... == nil and handle._autoclose and not handle._closed then handle:close() end\\\
10986 return ...\\\
10987end\\\
10988\\\
10989local handleMetatable\\\
10990handleMetatable = {\\\
10991 __name = \\\"FILE*\\\",\\\
10992 __tostring = function(self)\\\
10993 if self._closed then\\\
10994 return \\\"file (closed)\\\"\\\
10995 else\\\
10996 local hash = tostring(self._handle):match(\\\"table: (%x+)\\\")\\\
10997 return \\\"file (\\\" .. hash .. \\\")\\\"\\\
10998 end\\\
10999 end,\\\
11000 __index = {\\\
11001 close = function(self)\\\
11002 if typeOf(self) ~= \\\"table\\\" or getmetatable(self) ~= handleMetatable then\\\
11003 error(\\\"bad argument #1 (FILE expected, got \\\" .. typeOf(self) .. \\\")\\\", 2)\\\
11004 end\\\
11005 if self._closed then error(\\\"attempt to use a closed file\\\", 2) end\\\
11006\\\
11007 local handle = self._handle\\\
11008 if handle.close then\\\
11009 self._closed = true\\\
11010 handle.close()\\\
11011 return true\\\
11012 else\\\
11013 return nil, \\\"attempt to close standard stream\\\"\\\
11014 end\\\
11015 end,\\\
11016 flush = function(self)\\\
11017 if typeOf(self) ~= \\\"table\\\" or getmetatable(self) ~= handleMetatable then\\\
11018 error(\\\"bad argument #1 (FILE expected, got \\\" .. typeOf(self) .. \\\")\\\", 2)\\\
11019 end\\\
11020 if self._closed then error(\\\"attempt to use a closed file\\\", 2) end\\\
11021\\\
11022 local handle = self._handle\\\
11023 if handle.flush then handle.flush() end\\\
11024 end,\\\
11025 lines = function(self, ...)\\\
11026 if typeOf(self) ~= \\\"table\\\" or getmetatable(self) ~= handleMetatable then\\\
11027 error(\\\"bad argument #1 (FILE expected, got \\\" .. typeOf(self) .. \\\")\\\", 2)\\\
11028 end\\\
11029 if self._closed then error(\\\"attempt to use a closed file\\\", 2) end\\\
11030\\\
11031 local handle = self._handle\\\
11032 if not handle.read then return nil, \\\"file is not readable\\\" end\\\
11033\\\
11034 local args = table.pack(...)\\\
11035 return function() return checkResult(self, self:read(table.unpack(args, 1, args.n))) end\\\
11036 end,\\\
11037 read = function(self, ...)\\\
11038 if typeOf(self) ~= \\\"table\\\" or getmetatable(self) ~= handleMetatable then\\\
11039 error(\\\"bad argument #1 (FILE expected, got \\\" .. typeOf(self) .. \\\")\\\", 2)\\\
11040 end\\\
11041 if self._closed then error(\\\"attempt to use a closed file\\\", 2) end\\\
11042\\\
11043 local handle = self._handle\\\
11044 if not handle.read and not handle.readLine then return nil, \\\"Not opened for reading\\\" end\\\
11045\\\
11046 local n = select('#', ...)\\\
11047 local output = {}\\\
11048 for i = 1, n do\\\
11049 local arg = select(i, ...)\\\
11050 local res\\\
11051 if typeOf(arg) == \\\"number\\\" then\\\
11052 if handle.read then res = handle.read(arg) end\\\
11053 elseif typeOf(arg) == \\\"string\\\" then\\\
11054 local format = arg:gsub(\\\"^%*\\\", \\\"\\\"):sub(1, 1)\\\
11055\\\
11056 if format == \\\"l\\\" then\\\
11057 if handle.readLine then res = handle.readLine() end\\\
11058 elseif format == \\\"L\\\" and handle.readLine then\\\
11059 if handle.readLine then res = handle.readLine(true) end\\\
11060 elseif format == \\\"a\\\" then\\\
11061 if handle.readAll then res = handle.readAll() or \\\"\\\" end\\\
11062 elseif format == \\\"n\\\" then\\\
11063 res = nil -- Skip this format as we can't really handle it\\\
11064 else\\\
11065 error(\\\"bad argument #\\\" .. i .. \\\" (invalid format)\\\", 2)\\\
11066 end\\\
11067 else\\\
11068 error(\\\"bad argument #\\\" .. i .. \\\" (expected string, got \\\" .. typeOf(arg) .. \\\")\\\", 2)\\\
11069 end\\\
11070\\\
11071 output[i] = res\\\
11072 if not res then break end\\\
11073 end\\\
11074\\\
11075 -- Default to \\\"l\\\" if possible\\\
11076 if n == 0 and handle.readLine then return handle.readLine() end\\\
11077 return table.unpack(output, 1, n)\\\
11078 end,\\\
11079 seek = function(self, whence, offset)\\\
11080 if typeOf(self) ~= \\\"table\\\" or getmetatable(self) ~= handleMetatable then\\\
11081 error(\\\"bad argument #1 (FILE expected, got \\\" .. typeOf(self) .. \\\")\\\", 2)\\\
11082 end\\\
11083 if self._closed then error(\\\"attempt to use a closed file\\\", 2) end\\\
11084\\\
11085 local handle = self._handle\\\
11086 if not handle.seek then return nil, \\\"file is not seekable\\\" end\\\
11087\\\
11088 -- It's a tail call, so error positions are preserved\\\
11089 return handle.seek(whence, offset)\\\
11090 end,\\\
11091 setvbuf = function(self, mode, size) end,\\\
11092 write = function(self, ...)\\\
11093 if typeOf(self) ~= \\\"table\\\" or getmetatable(self) ~= handleMetatable then\\\
11094 error(\\\"bad argument #1 (FILE expected, got \\\" .. typeOf(self) .. \\\")\\\", 2)\\\
11095 end\\\
11096 if self._closed then error(\\\"attempt to use a closed file\\\", 2) end\\\
11097\\\
11098 local handle = self._handle\\\
11099 if not handle.write then return nil, \\\"file is not writable\\\" end\\\
11100\\\
11101 local n = select(\\\"#\\\", ...)\\\
11102 for i = 1, n do handle.write(select(i, ...)) end\\\
11103 return self\\\
11104 end,\\\
11105 },\\\
11106}\\\
11107\\\
11108local defaultInput = setmetatable({\\\
11109 _handle = { readLine = _G.read }\\\
11110}, handleMetatable)\\\
11111\\\
11112local defaultOutput = setmetatable({\\\
11113 _handle = { write = _G.write }\\\
11114}, handleMetatable)\\\
11115\\\
11116local defaultError = setmetatable({\\\
11117 _handle = {\\\
11118 write = function(...)\\\
11119 local oldColour\\\
11120 if term.isColour() then\\\
11121 oldColour = term.getTextColour()\\\
11122 term.setTextColour(colors.red)\\\
11123 end\\\
11124 _G.write(...)\\\
11125 if term.isColour() then term.setTextColour(oldColour) end\\\
11126 end,\\\
11127 }\\\
11128}, handleMetatable)\\\
11129\\\
11130local currentInput = defaultInput\\\
11131local currentOutput = defaultOutput\\\
11132\\\
11133stdin = defaultInput\\\
11134stdout = defaultOutput\\\
11135stderr = defaultError\\\
11136\\\
11137function close(_file)\\\
11138 if _file == nil then return currentOutput:close() end\\\
11139\\\
11140 if typeOf(_file) ~= \\\"table\\\" or getmetatable(_file) ~= handleMetatable then\\\
11141 error(\\\"bad argument #1 (FILE expected, got \\\" .. typeOf(_file) .. \\\")\\\", 2)\\\
11142 end\\\
11143 return _file:close()\\\
11144end\\\
11145\\\
11146function flush()\\\
11147 return currentOutput:flush()\\\
11148end\\\
11149\\\
11150function input(_arg)\\\
11151 if typeOf(_arg) == \\\"string\\\" then\\\
11152 local res, err = open(_arg, \\\"rb\\\")\\\
11153 if not res then error(err, 2) end\\\
11154 currentInput = res\\\
11155 elseif typeOf(_arg) == \\\"table\\\" and getmetatable(_arg) == handleMetatable then\\\
11156 currentInput = _arg\\\
11157 elseif _arg ~= nil then\\\
11158 error(\\\"bad argument #1 (FILE expected, got \\\" .. typeOf(_arg) .. \\\")\\\", 2)\\\
11159 end\\\
11160\\\
11161 return currentInput\\\
11162end\\\
11163\\\
11164function lines(_sFileName)\\\
11165 if _sFileName ~= nil and typeOf(_sFileName) ~= \\\"string\\\" then\\\
11166 error(\\\"bad argument #1 (expected string, got \\\" .. typeOf(_sFileName) .. \\\")\\\", 2)\\\
11167 end\\\
11168 if _sFileName then\\\
11169 local ok, err = open(_sFileName, \\\"rb\\\")\\\
11170 if not ok then error(err, 2) end\\\
11171\\\
11172 -- We set this magic flag to mark this file as being opened by io.lines and so should be\\\
11173 -- closed automatically\\\
11174 ok._autoclose = true\\\
11175 return ok:lines()\\\
11176 else\\\
11177 return currentInput:lines()\\\
11178 end\\\
11179end\\\
11180\\\
11181function open(_sPath, _sMode)\\\
11182 if typeOf(_sPath) ~= \\\"string\\\" then\\\
11183 error(\\\"bad argument #1 (expected string, got \\\" .. typeOf(_sPath) .. \\\")\\\", 2)\\\
11184 end\\\
11185 if _sMode ~= nil and typeOf(_sMode) ~= \\\"string\\\" then\\\
11186 error(\\\"bad argument #2 (expected string, got \\\" .. typeOf(_sMode) .. \\\")\\\", 2)\\\
11187 end\\\
11188\\\
11189 local sMode = _sMode and _sMode:gsub(\\\"%+\\\", \\\"\\\") or \\\"rb\\\"\\\
11190 local file, err = fs.open(_sPath, sMode)\\\
11191 if not file then return nil, err end\\\
11192\\\
11193 return setmetatable({ _handle = file }, handleMetatable)\\\
11194end\\\
11195\\\
11196function output(_arg)\\\
11197 if typeOf(_arg) == \\\"string\\\" then\\\
11198 local res, err = open(_arg, \\\"w\\\")\\\
11199 if not res then error(err, 2) end\\\
11200 currentOutput = res\\\
11201 elseif typeOf(_arg) == \\\"table\\\" and getmetatable(_arg) == handleMetatable then\\\
11202 currentOutput = _arg\\\
11203 elseif _arg ~= nil then\\\
11204 error(\\\"bad argument #1 (FILE expected, got \\\" .. typeOf(_arg) .. \\\")\\\", 2)\\\
11205 end\\\
11206\\\
11207 return currentOutput\\\
11208end\\\
11209\\\
11210function read(...)\\\
11211 return currentInput:read(...)\\\
11212end\\\
11213\\\
11214function type(handle)\\\
11215 if typeOf(handle) == \\\"table\\\" and getmetatable(handle) == handleMetatable then\\\
11216 if handle._closed then\\\
11217 return \\\"closed file\\\"\\\
11218 else\\\
11219 return \\\"file\\\"\\\
11220 end\\\
11221 end\\\
11222 return nil\\\
11223end\\\
11224\\\
11225function write(...)\\\
11226 return currentOutput:write(...)\\\
11227end\",\
11228 [ \"help/rs.txt\" ] = \"Functions in the Redstone API:\\\
11229rs.getSides( )\\\
11230rs.getInput( side )\\\
11231rs.setOutput( side, boolean )\\\
11232rs.getOutput( side )\\\
11233rs.getAnalogInput( side )\\\
11234rs.setAnalogOutput( side, number )\\\
11235rs.getAnalogOutput( side )\\\
11236\\\
11237Functions in the Redstone API for working with RedPower bundled cables:\\\
11238rs.getBundledInput( side )\\\
11239rs.testBundledInput( side, color )\\\
11240rs.setBundledOutput( side, colors )\\\
11241rs.getBundledOutput( side )\\\
11242Type \\\"help bundled\\\" for usage examples.\\\
11243\\\
11244Events emitted by the redstone API:\\\
11245\\\"redstone\\\", when the state of any redstone input changes. Use getInput() or getBundledInput() to inspect the changes\\\
11246Type \\\"help events\\\" to learn about the event system.\",\
11247 [ \"help/http.txt\" ] = \"Functions in the HTTP API:\\\
11248http.checkURL( url )\\\
11249http.checkURLAsync( url )\\\
11250http.request( url, [postData], [headers] )\\\
11251http.get( url, [headers] )\\\
11252http.post( url, postData, [headers] )\\\
11253\\\
11254The HTTP API may be disabled in ComputerCraft.cfg\\\
11255A period of time after a http.request() call is made, a \\\"http_success\\\" or \\\"http_failure\\\" event will be raised. Arguments are the url and a file handle if successful. Arguments are nil, an error message, and (optionally) a file handle if the request failed. http.get() and http.post() block until this event fires instead.\",\
11256 [ \"help/repeat.txt\" ] = \"repeat is a program for repeating rednet messages across long distances. To use, connect 2 or more modems to a computer and run the \\\"repeat\\\" program; from then on, any rednet message sent from any computer in wireless range or connected by networking cable to either of the modems will be repeated to those on the other side.\",\
11257 [ \"help/bg.txt\" ] = \"bg is a program for Advanced Computers which opens a new tab in the background.\\\
11258\\\
11259ex:\\\
11260\\\"bg\\\" will open a background tab running the shell\\\
11261\\\"bg worm\\\" will open a background tab running the \\\"worm\\\" program\",\
11262 [ \"help/gpsapi.txt\" ] = \"Functions in the GPS API:\\\
11263gps.locate( timeout )\\\
11264\\\
11265The locate function will send a signal to nearby gps servers, and wait for responses before the timeout. If it receives enough responses to determine this computers position then x, y and z co-ordinates will be returned, otherwise it will return nil. If GPS hosts do not have their positions configured correctly, results will be inaccurate.\",\
11266 [ \"help/multishell.txt\" ] = \"multishell is the toplevel program on Advanced Computers which manages background tabs.\\\
11267Type \\\"help shellapi\\\" for information about the shell lua api.\",\
11268 [ \"help/vector.txt\" ] = \"Functions in the 3D Vector Math API:\\\
11269vector.new( x,y,z )\\\
11270\\\
11271Vectors returned by vector.new() have the following fields and methods:\\\
11272vector.x\\\
11273vector.y\\\
11274vector.z\\\
11275vector:add( vector )\\\
11276vector:sub( vector )\\\
11277vector:mul( number )\\\
11278vector:dot( vector )\\\
11279vector:cross( vector )\\\
11280vector:length()\\\
11281vector:normalize()\\\
11282vector:round()\\\
11283vector:tostring()\\\
11284The +, - and * operators can also be used on vectors.\",\
11285 [ \"help/alias.txt\" ] = \"alias assigns shell commands to run other programs.\\\
11286\\\
11287ex:\\\
11288\\\"alias dir ls\\\" will make the \\\"dir\\\" command run the \\\"ls\\\" program\\\
11289\\\"alias dir\\\" will remove the alias set on \\\"dir\\\"\\\
11290\\\"alias\\\" will list all current aliases.\",\
11291 [ \"help/shellapi.txt\" ] = \"Functions in the Shell API:\\\
11292shell.exit()\\\
11293shell.dir()\\\
11294shell.setDir( path )\\\
11295shell.path()\\\
11296shell.setPath( path )\\\
11297shell.resolve( localpath )\\\
11298shell.resolveProgram( name )\\\
11299shell.aliases()\\\
11300shell.setAlias( alias, command )\\\
11301shell.clearAlias( alias )\\\
11302shell.programs()\\\
11303shell.run( program, arguments )\\\
11304shell.getRunningProgram()\\\
11305shell.complete( line )\\\
11306shell.completeProgram( program )\\\
11307shell.setCompletionFunction( program, fnComplete )\\\
11308shell.openTab( program, arguments ) (Advanced Computer required)\\\
11309shell.switchTab( n ) (Advanced Computer required)\",\
11310 [ \"programs/turtle/tunnel.lua\" ] = \"\\\
11311local tArgs = { ... }\\\
11312if #tArgs ~= 1 then\\\
11313 print( \\\"Usage: tunnel <length>\\\" )\\\
11314 return\\\
11315end\\\
11316\\\
11317-- Mine in a quarry pattern until we hit something we can't dig\\\
11318local length = tonumber( tArgs[1] )\\\
11319if length < 1 then\\\
11320 print( \\\"Tunnel length must be positive\\\" )\\\
11321 return\\\
11322end\\\
11323\\\
11324local depth = 0\\\
11325local collected = 0\\\
11326\\\
11327local function collect()\\\
11328 collected = collected + 1\\\
11329 if math.fmod(collected, 25) == 0 then\\\
11330 print( \\\"Mined \\\"..collected..\\\" items.\\\" )\\\
11331 end\\\
11332end\\\
11333\\\
11334local function tryDig()\\\
11335 while turtle.detect() do\\\
11336 if turtle.dig() then\\\
11337 collect()\\\
11338 sleep(0.5)\\\
11339 else\\\
11340 return false\\\
11341 end\\\
11342 end\\\
11343 return true\\\
11344end\\\
11345\\\
11346local function tryDigUp()\\\
11347 while turtle.detectUp() do\\\
11348 if turtle.digUp() then\\\
11349 collect()\\\
11350 sleep(0.5)\\\
11351 else\\\
11352 return false\\\
11353 end\\\
11354 end\\\
11355 return true\\\
11356end\\\
11357\\\
11358local function tryDigDown()\\\
11359 while turtle.detectDown() do\\\
11360 if turtle.digDown() then\\\
11361 collect()\\\
11362 sleep(0.5)\\\
11363 else\\\
11364 return false\\\
11365 end\\\
11366 end\\\
11367 return true\\\
11368end\\\
11369\\\
11370local function refuel()\\\
11371 local fuelLevel = turtle.getFuelLevel()\\\
11372 if fuelLevel == \\\"unlimited\\\" or fuelLevel > 0 then\\\
11373 return\\\
11374 end\\\
11375\\\
11376 local function tryRefuel()\\\
11377 for n=1,16 do\\\
11378 if turtle.getItemCount(n) > 0 then\\\
11379 turtle.select(n)\\\
11380 if turtle.refuel(1) then\\\
11381 turtle.select(1)\\\
11382 return true\\\
11383 end\\\
11384 end\\\
11385 end\\\
11386 turtle.select(1)\\\
11387 return false\\\
11388 end\\\
11389\\\
11390 if not tryRefuel() then\\\
11391 print( \\\"Add more fuel to continue.\\\" )\\\
11392 while not tryRefuel() do\\\
11393 os.pullEvent( \\\"turtle_inventory\\\" )\\\
11394 end\\\
11395 print( \\\"Resuming Tunnel.\\\" )\\\
11396 end\\\
11397end\\\
11398\\\
11399local function tryUp()\\\
11400 refuel()\\\
11401 while not turtle.up() do\\\
11402 if turtle.detectUp() then\\\
11403 if not tryDigUp() then\\\
11404 return false\\\
11405 end\\\
11406 elseif turtle.attackUp() then\\\
11407 collect()\\\
11408 else\\\
11409 sleep( 0.5 )\\\
11410 end\\\
11411 end\\\
11412 return true\\\
11413end\\\
11414\\\
11415local function tryDown()\\\
11416 refuel()\\\
11417 while not turtle.down() do\\\
11418 if turtle.detectDown() then\\\
11419 if not tryDigDown() then\\\
11420 return false\\\
11421 end\\\
11422 elseif turtle.attackDown() then\\\
11423 collect()\\\
11424 else\\\
11425 sleep( 0.5 )\\\
11426 end\\\
11427 end\\\
11428 return true\\\
11429end\\\
11430\\\
11431local function tryForward()\\\
11432 refuel()\\\
11433 while not turtle.forward() do\\\
11434 if turtle.detect() then\\\
11435 if not tryDig() then\\\
11436 return false\\\
11437 end\\\
11438 elseif turtle.attack() then\\\
11439 collect()\\\
11440 else\\\
11441 sleep( 0.5 )\\\
11442 end\\\
11443 end\\\
11444 return true\\\
11445end\\\
11446\\\
11447print( \\\"Tunnelling...\\\" )\\\
11448\\\
11449for n=1,length do\\\
11450 turtle.placeDown()\\\
11451 tryDigUp()\\\
11452 turtle.turnLeft()\\\
11453 tryDig()\\\
11454 tryUp()\\\
11455 tryDig()\\\
11456 turtle.turnRight()\\\
11457 turtle.turnRight()\\\
11458 tryDig()\\\
11459 tryDown()\\\
11460 tryDig()\\\
11461 turtle.turnLeft()\\\
11462\\\
11463 if n<length then\\\
11464 tryDig()\\\
11465 if not tryForward() then\\\
11466 print( \\\"Aborting Tunnel.\\\" )\\\
11467 break\\\
11468 end\\\
11469 else\\\
11470 print( \\\"Tunnel complete.\\\" )\\\
11471 end\\\
11472\\\
11473end\\\
11474\\\
11475--[[\\\
11476print( \\\"Returning to start...\\\" )\\\
11477\\\
11478-- Return to where we started\\\
11479turtle.turnLeft()\\\
11480turtle.turnLeft()\\\
11481while depth > 0 do\\\
11482 if turtle.forward() then\\\
11483 depth = depth - 1\\\
11484 else\\\
11485 turtle.dig()\\\
11486 end\\\
11487end\\\
11488turtle.turnRight()\\\
11489turtle.turnRight()\\\
11490]]\\\
11491\\\
11492print( \\\"Tunnel complete.\\\" )\\\
11493print( \\\"Mined \\\"..collected..\\\" items total.\\\" )\",\
11494 [ \"apis/disk.lua\" ] = \"\\\
11495local function isDrive( name )\\\
11496 if type( name ) ~= \\\"string\\\" then\\\
11497 error( \\\"bad argument #1 (expected string, got \\\" .. type( name ) .. \\\")\\\", 3 )\\\
11498 end\\\
11499 return peripheral.getType( name ) == \\\"drive\\\"\\\
11500end\\\
11501\\\
11502function isPresent( name )\\\
11503 if isDrive( name ) then\\\
11504 return peripheral.call( name, \\\"isDiskPresent\\\" )\\\
11505 end\\\
11506 return false\\\
11507end\\\
11508\\\
11509function getLabel( name )\\\
11510 if isDrive( name ) then\\\
11511 return peripheral.call( name, \\\"getDiskLabel\\\" )\\\
11512 end\\\
11513 return nil\\\
11514end\\\
11515\\\
11516function setLabel( name, label )\\\
11517 if isDrive( name ) then\\\
11518 peripheral.call( name, \\\"setDiskLabel\\\", label )\\\
11519 end\\\
11520end\\\
11521\\\
11522function hasData( name )\\\
11523 if isDrive( name ) then\\\
11524 return peripheral.call( name, \\\"hasData\\\" )\\\
11525 end\\\
11526 return false\\\
11527end\\\
11528\\\
11529function getMountPath( name )\\\
11530 if isDrive( name ) then\\\
11531 return peripheral.call( name, \\\"getMountPath\\\" )\\\
11532 end\\\
11533 return nil\\\
11534end\\\
11535\\\
11536function hasAudio( name )\\\
11537 if isDrive( name ) then\\\
11538 return peripheral.call( name, \\\"hasAudio\\\" )\\\
11539 end\\\
11540 return false\\\
11541end\\\
11542\\\
11543function getAudioTitle( name )\\\
11544 if isDrive( name ) then\\\
11545 return peripheral.call( name, \\\"getAudioTitle\\\" )\\\
11546 end\\\
11547 return nil\\\
11548end\\\
11549\\\
11550function playAudio( name )\\\
11551 if isDrive( name ) then\\\
11552 peripheral.call( name, \\\"playAudio\\\" )\\\
11553 end\\\
11554end\\\
11555\\\
11556function stopAudio( name )\\\
11557 if not name then\\\
11558 for n,sName in ipairs( peripheral.getNames() ) do\\\
11559 stopAudio( sName )\\\
11560 end\\\
11561 else\\\
11562 if isDrive( name ) then\\\
11563 peripheral.call( name, \\\"stopAudio\\\" )\\\
11564 end\\\
11565 end\\\
11566end\\\
11567\\\
11568function eject( name )\\\
11569 if isDrive( name ) then\\\
11570 peripheral.call( name, \\\"ejectDisk\\\" )\\\
11571 end\\\
11572end\\\
11573\\\
11574function getID( name )\\\
11575 if isDrive( name ) then\\\
11576 return peripheral.call( name, \\\"getDiskID\\\" )\\\
11577 end\\\
11578 return nil\\\
11579end\\\
11580\",\
11581 [ \"help/craft.txt\" ] = \"craft is a program for Crafty Turtles. Craft will craft a stack of items using the current inventory.\\\
11582\\\
11583ex:\\\
11584\\\"craft\\\" will craft as many items as possible\\\
11585\\\"craft 5\\\" will craft at most 5 times\",\
11586 [ \"help/redstoneapi.txt\" ] = \"Functions in the Redstone API:\\\
11587redstone.getSides( )\\\
11588redstone.getInput( side )\\\
11589redstone.setOutput( side, boolean )\\\
11590redstone.getOutput( side )\\\
11591redstone.getAnalogInput( side )\\\
11592redstone.setAnalogOutput( side, number )\\\
11593redstone.getAnalogOutput( side )\\\
11594\\\
11595Functions in the Redstone API for working with bundled cables:\\\
11596redstone.getBundledInput( side )\\\
11597redstone.testBundledInput( side, color )\\\
11598redstone.setBundledOutput( side, colors )\\\
11599redstone.getBundledOutput( side )\\\
11600Type \\\"help bundled\\\" for usage examples.\\\
11601\\\
11602Events emitted by the redstone API:\\\
11603\\\"redstone\\\", when the state of any redstone input changes. Use getInput() or getBundledInput() to inspect the changes\\\
11604Type \\\"help events\\\" to learn about the event system.\",\
11605 [ \"help/peripherals.txt\" ] = \"The \\\"peripherals\\\" program will list all of the peripheral devices accessible from this computer.\\\
11606Peripherals are external devices which CraftOS Computers and Turtles can interact with using the peripheral API.\\\
11607Type \\\"help peripheral\\\" to learn about using the peripheral API.\\\
11608Type \\\"help drives\\\" to learn about using Disk Drives.\\\
11609Type \\\"help modems\\\" to learn about using Modems.\\\
11610Type \\\"help monitors\\\" to learn about using Monitors.\\\
11611Type \\\"help printers\\\" to learn about using Printers.\",\
11612 [ \"autorun/.ignoreme\" ] = \"--[[\\\
11613Alright then, don't ignore me. This file is to ensure the existence of the \\\"autorun\\\" folder, files placed in this folder\\\
11614using resource packs will always run when computers startup.\\\
11615]]\",\
11616 [ \"help/earth.txt\" ] = \"Mostly harmless.\",\
11617 [ \"programs/turtle/refuel.lua\" ] = \"\\\
11618local tArgs = { ... }\\\
11619local nLimit = 1\\\
11620if #tArgs > 1 then\\\
11621 print( \\\"Usage: refuel [number]\\\" )\\\
11622 return\\\
11623elseif #tArgs > 0 then\\\
11624 if tArgs[1] == \\\"all\\\" then\\\
11625 nLimit = 64 * 16\\\
11626 else\\\
11627 nLimit = tonumber( tArgs[1] )\\\
11628 end\\\
11629end\\\
11630\\\
11631if turtle.getFuelLevel() ~= \\\"unlimited\\\" then\\\
11632 for n=1,16 do\\\
11633 local nCount = turtle.getItemCount(n)\\\
11634 if nLimit > 0 and nCount > 0 and turtle.getFuelLevel() < turtle.getFuelLimit() then\\\
11635 local nBurn = math.min( nLimit, nCount )\\\
11636 turtle.select( n )\\\
11637 if turtle.refuel( nBurn ) then\\\
11638 local nNewCount = turtle.getItemCount(n)\\\
11639 nLimit = nLimit - (nCount - nNewCount)\\\
11640 end\\\
11641 end\\\
11642 end\\\
11643 print( \\\"Fuel level is \\\"..turtle.getFuelLevel() )\\\
11644 if turtle.getFuelLevel() == turtle.getFuelLimit() then\\\
11645 print( \\\"Fuel limit reached\\\" )\\\
11646 end\\\
11647else\\\
11648 print( \\\"Fuel level is unlimited\\\" )\\\
11649end\",\
11650 [ \"help/paint.txt\" ] = \"paint is a program for creating images on Advanced Computers. Select colors from the color pallette on the right, and click on the canvas to draw. Press Ctrl to access the menu and save your pictures.\\\
11651\\\
11652ex:\\\
11653\\\"edit mario\\\" opens an image called \\\"mario\\\" for editing.\",\
11654 [ \"help/bit.txt\" ] = \"Functions in the bit manipulation API (NOTE: This API will be removed in a future version. Use bit32 instead):\\\
11655bit.bnot(n) -- bitwise not (~n)\\\
11656bit.band(m, n) -- bitwise and (m & n)\\\
11657bit.bor(m, n) -- bitwise or (m | n)\\\
11658bit.bxor(m, n) -- bitwise xor (m ^ n)\\\
11659bit.brshift(n, bits) -- right shift (n >> bits)\\\
11660bit.blshift(n, bits) -- left shift (n << bits)\",\
11661 [ \"help/drive.txt\" ] = \"drive tells you which disk drive the current or specified directory is located in.\\\
11662\\\
11663ex:\\\
11664\\\"drive\\\" tell you the disk drive of the current directory.\\\
11665\\\"drive foo\\\" tells you the disk drive of the subdirectory \\\"foo\\\"\",\
11666 [ \"help/events.txt\" ] = \"The function os.pullEvent() will yield the program until a system event occurs. The first return value is the event name, followed by any arguments.\\\
11667\\\
11668Some events which can occur are:\\\
11669\\\"char\\\" when text is typed on the keyboard. Argument is the character typed.\\\
11670\\\"key\\\" when a key is pressed on the keyboard. Arguments are the keycode and whether the key is a repeat. Compare the keycode to the values in keys API to see which key was pressed.\\\
11671\\\"key_up\\\" when a key is released on the keyboard. Argument is the numerical keycode. Compare to the values in keys API to see which key was released.\\\
11672\\\"paste\\\" when text is pasted from the users keyboard. Argument is the line of text pasted.\\\
11673\\\
11674Events only on advanced computers:\\\
11675\\\"mouse_click\\\" when a user clicks the mouse. Arguments are button, xPos, yPos.\\\
11676\\\"mouse_drag\\\" when a user moves the mouse when held. Arguments are button, xPos, yPos.\\\
11677\\\"mouse_up\\\" when a user releases the mouse button. Arguments are button, xPos, yPos.\\\
11678\\\"mouse_scroll\\\" when a user uses the scrollwheel on the mouse. Arguments are direction, xPos, yPos.\\\
11679\\\
11680Other APIs and peripherals will emit their own events. See their respective help pages for details.\",\
11681 [ \"help/help.txt\" ] = \"help is the help tool you're currently using.\\\
11682Type \\\"help index\\\" to see all help topics.\\\
11683Type \\\"help\\\" to see the help intro.\\\
11684Type \\\"help helpapi\\\" for information on the help Lua API.\",\
11685 [ \"help/modems.txt\" ] = \"Wired and Wireless Modems are peripheral devices available for CraftOS. Type \\\"help peripheral\\\" to learn about using the Peripheral API to connect with peripherals. When a Modem is connected, peripheral.getType() will return \\\"modem\\\".\\\
11686\\\
11687Methods exposed by Modems:\\\
11688open( channel )\\\
11689isOpen( channel )\\\
11690close( channel )\\\
11691closeAll()\\\
11692transmit( channel, replyChannel, message )\\\
11693isWireless()\\\
11694\\\
11695Events fired by Modems:\\\
11696\\\"modem_message\\\" when a message is received on an open channel. Arguments are name, channel, replyChannel, message, distance\",\
11697 [ \"help/keys.txt\" ] = \"The keys API contains constants for all the key codes that can be returned by the \\\"key\\\" event:\\\
11698\\\
11699Example usage:\\\
11700local sEvent, nKey = os.pullEvent()\\\
11701if sEvent == \\\"key\\\" and nKey == keys.enter then\\\
11702 -- Do something \\\
11703end\\\
11704\\\
11705See http://www.minecraftwiki.net/wiki/Key_codes, or the source code, for a complete reference.\",\
11706 [ \"modules/turtle/.ignoreme\" ] = \"--[[\\\
11707Alright then, don't ignore me. This file is to ensure the existence of the \\\"modules/turtle\\\" folder.\\\
11708You can use this folder to add modules who can be loaded with require() to your Resourcepack.\\\
11709]]\",\
11710 [ \"apis/window.lua\" ] = \"\\\
11711local tHex = {\\\
11712 [ colors.white ] = \\\"0\\\",\\\
11713 [ colors.orange ] = \\\"1\\\",\\\
11714 [ colors.magenta ] = \\\"2\\\",\\\
11715 [ colors.lightBlue ] = \\\"3\\\",\\\
11716 [ colors.yellow ] = \\\"4\\\",\\\
11717 [ colors.lime ] = \\\"5\\\",\\\
11718 [ colors.pink ] = \\\"6\\\",\\\
11719 [ colors.gray ] = \\\"7\\\",\\\
11720 [ colors.lightGray ] = \\\"8\\\",\\\
11721 [ colors.cyan ] = \\\"9\\\",\\\
11722 [ colors.purple ] = \\\"a\\\",\\\
11723 [ colors.blue ] = \\\"b\\\",\\\
11724 [ colors.brown ] = \\\"c\\\",\\\
11725 [ colors.green ] = \\\"d\\\",\\\
11726 [ colors.red ] = \\\"e\\\",\\\
11727 [ colors.black ] = \\\"f\\\",\\\
11728}\\\
11729\\\
11730local type = type\\\
11731local string_rep = string.rep\\\
11732local string_sub = string.sub\\\
11733local table_unpack = table.unpack\\\
11734\\\
11735function create( parent, nX, nY, nWidth, nHeight, bStartVisible )\\\
11736 if type( parent ) ~= \\\"table\\\" then error( \\\"bad argument #1 (expected table, got \\\" .. type( parent ) .. \\\")\\\", 2 ) end\\\
11737 if type( nX ) ~= \\\"number\\\" then error( \\\"bad argument #2 (expected number, got \\\" .. type( nX ) .. \\\")\\\", 2 ) end\\\
11738 if type( nY ) ~= \\\"number\\\" then error( \\\"bad argument #3 (expected number, got \\\" .. type( nY ) .. \\\")\\\", 2 ) end\\\
11739 if type( nWidth ) ~= \\\"number\\\" then error( \\\"bad argument #4 (expected number, got \\\" .. type( nWidth ) .. \\\")\\\", 2 ) end\\\
11740 if type( nHeight ) ~= \\\"number\\\" then error( \\\"bad argument #5 (expected number, got \\\" .. type( nHeight ) .. \\\")\\\", 2 ) end\\\
11741 if bStartVisible ~= nil and type( bStartVisible ) ~= \\\"boolean\\\" then error( \\\"bad argument #6 (expected boolean, got \\\" .. type( bStartVisible ) .. \\\")\\\", 2 ) end\\\
11742\\\
11743 if parent == term then\\\
11744 error( \\\"term is not a recommended window parent, try term.current() instead\\\", 2 )\\\
11745 end\\\
11746\\\
11747 local sEmptySpaceLine\\\
11748 local tEmptyColorLines = {}\\\
11749 local function createEmptyLines( nWidth )\\\
11750 sEmptySpaceLine = string_rep( \\\" \\\", nWidth )\\\
11751 for n=0,15 do\\\
11752 local nColor = 2^n\\\
11753 local sHex = tHex[nColor]\\\
11754 tEmptyColorLines[nColor] = string_rep( sHex, nWidth )\\\
11755 end\\\
11756 end\\\
11757\\\
11758 createEmptyLines( nWidth )\\\
11759\\\
11760 -- Setup\\\
11761 local bVisible = (bStartVisible ~= false)\\\
11762 local nCursorX = 1\\\
11763 local nCursorY = 1\\\
11764 local bCursorBlink = false\\\
11765 local nTextColor = colors.white\\\
11766 local nBackgroundColor = colors.black\\\
11767 local tLines = {}\\\
11768 local tPalette = {}\\\
11769 do\\\
11770 local sEmptyText = sEmptySpaceLine\\\
11771 local sEmptyTextColor = tEmptyColorLines[ nTextColor ]\\\
11772 local sEmptyBackgroundColor = tEmptyColorLines[ nBackgroundColor ]\\\
11773 for y=1,nHeight do\\\
11774 tLines[y] = {\\\
11775 text = sEmptyText,\\\
11776 textColor = sEmptyTextColor,\\\
11777 backgroundColor = sEmptyBackgroundColor,\\\
11778 }\\\
11779 end\\\
11780\\\
11781 for i=0,15 do\\\
11782 local c = 2 ^ i\\\
11783 tPalette[c] = { parent.getPaletteColour( c ) }\\\
11784 end\\\
11785 end\\\
11786\\\
11787 -- Helper functions\\\
11788 local function updateCursorPos()\\\
11789 if nCursorX >= 1 and nCursorY >= 1 and\\\
11790 nCursorX <= nWidth and nCursorY <= nHeight then\\\
11791 parent.setCursorPos( nX + nCursorX - 1, nY + nCursorY - 1 )\\\
11792 else\\\
11793 parent.setCursorPos( 0, 0 )\\\
11794 end\\\
11795 end\\\
11796\\\
11797 local function updateCursorBlink()\\\
11798 parent.setCursorBlink( bCursorBlink )\\\
11799 end\\\
11800\\\
11801 local function updateCursorColor()\\\
11802 parent.setTextColor( nTextColor )\\\
11803 end\\\
11804\\\
11805 local function redrawLine( n )\\\
11806 local tLine = tLines[ n ]\\\
11807 parent.setCursorPos( nX, nY + n - 1 )\\\
11808 parent.blit( tLine.text, tLine.textColor, tLine.backgroundColor )\\\
11809 end\\\
11810\\\
11811 local function redraw()\\\
11812 for n=1,nHeight do\\\
11813 redrawLine( n )\\\
11814 end\\\
11815 end\\\
11816\\\
11817 local function updatePalette()\\\
11818 for k,v in pairs( tPalette ) do\\\
11819 parent.setPaletteColour( k, v[1], v[2], v[3] )\\\
11820 end\\\
11821 end\\\
11822\\\
11823 local function internalBlit( sText, sTextColor, sBackgroundColor )\\\
11824 local nStart = nCursorX\\\
11825 local nEnd = nStart + #sText - 1\\\
11826 if nCursorY >= 1 and nCursorY <= nHeight then\\\
11827 if nStart <= nWidth and nEnd >= 1 then\\\
11828 -- Modify line\\\
11829 local tLine = tLines[ nCursorY ]\\\
11830 if nStart == 1 and nEnd == nWidth then\\\
11831 tLine.text = sText\\\
11832 tLine.textColor = sTextColor\\\
11833 tLine.backgroundColor = sBackgroundColor\\\
11834 else\\\
11835 local sClippedText, sClippedTextColor, sClippedBackgroundColor\\\
11836 if nStart < 1 then\\\
11837 local nClipStart = 1 - nStart + 1\\\
11838 local nClipEnd = nWidth - nStart + 1\\\
11839 sClippedText = string_sub( sText, nClipStart, nClipEnd )\\\
11840 sClippedTextColor = string_sub( sTextColor, nClipStart, nClipEnd )\\\
11841 sClippedBackgroundColor = string_sub( sBackgroundColor, nClipStart, nClipEnd )\\\
11842 elseif nEnd > nWidth then\\\
11843 local nClipEnd = nWidth - nStart + 1\\\
11844 sClippedText = string_sub( sText, 1, nClipEnd )\\\
11845 sClippedTextColor = string_sub( sTextColor, 1, nClipEnd )\\\
11846 sClippedBackgroundColor = string_sub( sBackgroundColor, 1, nClipEnd )\\\
11847 else\\\
11848 sClippedText = sText\\\
11849 sClippedTextColor = sTextColor\\\
11850 sClippedBackgroundColor = sBackgroundColor\\\
11851 end\\\
11852\\\
11853 local sOldText = tLine.text\\\
11854 local sOldTextColor = tLine.textColor\\\
11855 local sOldBackgroundColor = tLine.backgroundColor\\\
11856 local sNewText, sNewTextColor, sNewBackgroundColor\\\
11857 if nStart > 1 then\\\
11858 local nOldEnd = nStart - 1\\\
11859 sNewText = string_sub( sOldText, 1, nOldEnd ) .. sClippedText\\\
11860 sNewTextColor = string_sub( sOldTextColor, 1, nOldEnd ) .. sClippedTextColor\\\
11861 sNewBackgroundColor = string_sub( sOldBackgroundColor, 1, nOldEnd ) .. sClippedBackgroundColor\\\
11862 else\\\
11863 sNewText = sClippedText\\\
11864 sNewTextColor = sClippedTextColor\\\
11865 sNewBackgroundColor = sClippedBackgroundColor\\\
11866 end\\\
11867 if nEnd < nWidth then\\\
11868 local nOldStart = nEnd + 1\\\
11869 sNewText = sNewText .. string_sub( sOldText, nOldStart, nWidth )\\\
11870 sNewTextColor = sNewTextColor .. string_sub( sOldTextColor, nOldStart, nWidth )\\\
11871 sNewBackgroundColor = sNewBackgroundColor .. string_sub( sOldBackgroundColor, nOldStart, nWidth )\\\
11872 end\\\
11873\\\
11874 tLine.text = sNewText\\\
11875 tLine.textColor = sNewTextColor\\\
11876 tLine.backgroundColor = sNewBackgroundColor\\\
11877 end\\\
11878\\\
11879 -- Redraw line\\\
11880 if bVisible then\\\
11881 redrawLine( nCursorY )\\\
11882 end\\\
11883 end\\\
11884 end\\\
11885\\\
11886 -- Move and redraw cursor\\\
11887 nCursorX = nEnd + 1\\\
11888 if bVisible then\\\
11889 updateCursorColor()\\\
11890 updateCursorPos()\\\
11891 end\\\
11892 end\\\
11893\\\
11894 -- Terminal implementation\\\
11895 local window = {}\\\
11896\\\
11897 function window.write( sText )\\\
11898 sText = tostring( sText )\\\
11899 internalBlit( sText, string_rep( tHex[ nTextColor ], #sText ), string_rep( tHex[ nBackgroundColor ], #sText ) )\\\
11900 end\\\
11901\\\
11902 function window.blit( sText, sTextColor, sBackgroundColor )\\\
11903 if type( sText ) ~= \\\"string\\\" then error( \\\"bad argument #1 (expected string, got \\\" .. type( sText ) .. \\\")\\\", 2 ) end\\\
11904 if type( sTextColor ) ~= \\\"string\\\" then error( \\\"bad argument #2 (expected string, got \\\" .. type( sTextColor ) .. \\\")\\\", 2 ) end\\\
11905 if type( sBackgroundColor ) ~= \\\"string\\\" then error( \\\"bad argument #3 (expected string, got \\\" .. type( sBackgroundColor ) .. \\\")\\\", 2 ) end\\\
11906 if #sTextColor ~= #sText or #sBackgroundColor ~= #sText then\\\
11907 error( \\\"Arguments must be the same length\\\", 2 )\\\
11908 end\\\
11909 internalBlit( sText, sTextColor, sBackgroundColor )\\\
11910 end\\\
11911\\\
11912 function window.clear()\\\
11913 local sEmptyText = sEmptySpaceLine\\\
11914 local sEmptyTextColor = tEmptyColorLines[ nTextColor ]\\\
11915 local sEmptyBackgroundColor = tEmptyColorLines[ nBackgroundColor ]\\\
11916 for y=1,nHeight do\\\
11917 tLines[y] = {\\\
11918 text = sEmptyText,\\\
11919 textColor = sEmptyTextColor,\\\
11920 backgroundColor = sEmptyBackgroundColor,\\\
11921 }\\\
11922 end\\\
11923 if bVisible then\\\
11924 redraw()\\\
11925 updateCursorColor()\\\
11926 updateCursorPos()\\\
11927 end\\\
11928 end\\\
11929\\\
11930 function window.clearLine()\\\
11931 if nCursorY >= 1 and nCursorY <= nHeight then\\\
11932 local sEmptyText = sEmptySpaceLine\\\
11933 local sEmptyTextColor = tEmptyColorLines[ nTextColor ]\\\
11934 local sEmptyBackgroundColor = tEmptyColorLines[ nBackgroundColor ]\\\
11935 tLines[ nCursorY ] = {\\\
11936 text = sEmptyText,\\\
11937 textColor = sEmptyTextColor,\\\
11938 backgroundColor = sEmptyBackgroundColor,\\\
11939 }\\\
11940 if bVisible then\\\
11941 redrawLine( nCursorY )\\\
11942 updateCursorColor()\\\
11943 updateCursorPos()\\\
11944 end\\\
11945 end\\\
11946 end\\\
11947\\\
11948 function window.getCursorPos()\\\
11949 return nCursorX, nCursorY\\\
11950 end\\\
11951\\\
11952 function window.setCursorPos( x, y )\\\
11953 if type( x ) ~= \\\"number\\\" then error( \\\"bad argument #1 (expected number, got \\\" .. type( x ) .. \\\")\\\", 2 ) end\\\
11954 if type( y ) ~= \\\"number\\\" then error( \\\"bad argument #2 (expected number, got \\\" .. type( y ) .. \\\")\\\", 2 ) end\\\
11955 nCursorX = math.floor( x )\\\
11956 nCursorY = math.floor( y )\\\
11957 if bVisible then\\\
11958 updateCursorPos()\\\
11959 end\\\
11960 end\\\
11961\\\
11962 function window.setCursorBlink( blink )\\\
11963 if type( blink ) ~= \\\"boolean\\\" then error( \\\"bad argument #1 (expected boolean, got \\\" .. type( blink ) .. \\\")\\\", 2 ) end\\\
11964 bCursorBlink = blink\\\
11965 if bVisible then\\\
11966 updateCursorBlink()\\\
11967 end\\\
11968 end\\\
11969\\\
11970 function window.getCursorBlink()\\\
11971 return bCursorBlink\\\
11972 end\\\
11973\\\
11974 local function isColor()\\\
11975 return parent.isColor()\\\
11976 end\\\
11977\\\
11978 function window.isColor()\\\
11979 return isColor()\\\
11980 end\\\
11981\\\
11982 function window.isColour()\\\
11983 return isColor()\\\
11984 end\\\
11985\\\
11986 local function setTextColor( color )\\\
11987 if type( color ) ~= \\\"number\\\" then\\\
11988 error( \\\"bad argument #1 (expected number, got \\\" .. type( color ) .. \\\")\\\", 2 )\\\
11989 elseif tHex[color] == nil then\\\
11990 error( \\\"Invalid color (got \\\" .. color .. \\\")\\\" , 2 )\\\
11991 end\\\
11992 nTextColor = color\\\
11993 if bVisible then\\\
11994 updateCursorColor()\\\
11995 end\\\
11996 end\\\
11997\\\
11998 window.setTextColor = setTextColor\\\
11999 window.setTextColour = setTextColor\\\
12000\\\
12001 function window.setPaletteColour( colour, r, g, b )\\\
12002 if type( colour ) ~= \\\"number\\\" then error( \\\"bad argument #1 (expected number, got \\\" .. type( colour ) .. \\\")\\\", 2 ) end\\\
12003\\\
12004 if tHex[colour] == nil then\\\
12005 error( \\\"Invalid color (got \\\" .. colour .. \\\")\\\" , 2 )\\\
12006 end\\\
12007\\\
12008 local tCol\\\
12009 if type(r) == \\\"number\\\" and g == nil and b == nil then\\\
12010 tCol = { colours.rgb8( r ) }\\\
12011 tPalette[ colour ] = tCol\\\
12012 else\\\
12013 if type( r ) ~= \\\"number\\\" then error( \\\"bad argument #2 (expected number, got \\\" .. type( r ) .. \\\")\\\", 2 ) end\\\
12014 if type( g ) ~= \\\"number\\\" then error( \\\"bad argument #3 (expected number, got \\\" .. type( g ) .. \\\")\\\", 2 ) end\\\
12015 if type( b ) ~= \\\"number\\\" then error( \\\"bad argument #4 (expected number, got \\\" .. type( b ) .. \\\")\\\", 2 ) end\\\
12016\\\
12017 tCol = tPalette[ colour ]\\\
12018 tCol[1] = r\\\
12019 tCol[2] = g\\\
12020 tCol[3] = b\\\
12021 end\\\
12022\\\
12023 if bVisible then\\\
12024 return parent.setPaletteColour( colour, tCol[1], tCol[2], tCol[3] )\\\
12025 end\\\
12026 end\\\
12027\\\
12028 window.setPaletteColor = window.setPaletteColour\\\
12029\\\
12030 function window.getPaletteColour( colour )\\\
12031 if type( colour ) ~= \\\"number\\\" then error( \\\"bad argument #1 (expected number, got \\\" .. type( colour ) .. \\\")\\\", 2 ) end\\\
12032 if tHex[colour] == nil then\\\
12033 error( \\\"Invalid color (got \\\" .. colour .. \\\")\\\" , 2 )\\\
12034 end\\\
12035 local tCol = tPalette[ colour ]\\\
12036 return tCol[1], tCol[2], tCol[3]\\\
12037 end\\\
12038\\\
12039 window.getPaletteColor = window.getPaletteColour\\\
12040\\\
12041 local function setBackgroundColor( color )\\\
12042 if type( color ) ~= \\\"number\\\" then\\\
12043 error( \\\"bad argument #1 (expected number, got \\\" .. type( color ) .. \\\")\\\", 2 )\\\
12044 elseif tHex[color] == nil then\\\
12045 error( \\\"Invalid color (got \\\" .. color .. \\\")\\\", 2 )\\\
12046 end\\\
12047 nBackgroundColor = color\\\
12048 end\\\
12049\\\
12050 window.setBackgroundColor = setBackgroundColor\\\
12051 window.setBackgroundColour = setBackgroundColor\\\
12052\\\
12053 function window.getSize()\\\
12054 return nWidth, nHeight\\\
12055 end\\\
12056\\\
12057 function window.scroll( n )\\\
12058 if type( n ) ~= \\\"number\\\" then error( \\\"bad argument #1 (expected number, got \\\" .. type( n ) .. \\\")\\\", 2 ) end\\\
12059 if n ~= 0 then\\\
12060 local tNewLines = {}\\\
12061 local sEmptyText = sEmptySpaceLine\\\
12062 local sEmptyTextColor = tEmptyColorLines[ nTextColor ]\\\
12063 local sEmptyBackgroundColor = tEmptyColorLines[ nBackgroundColor ]\\\
12064 for newY=1,nHeight do\\\
12065 local y = newY + n\\\
12066 if y >= 1 and y <= nHeight then\\\
12067 tNewLines[newY] = tLines[y]\\\
12068 else\\\
12069 tNewLines[newY] = {\\\
12070 text = sEmptyText,\\\
12071 textColor = sEmptyTextColor,\\\
12072 backgroundColor = sEmptyBackgroundColor,\\\
12073 }\\\
12074 end\\\
12075 end\\\
12076 tLines = tNewLines\\\
12077 if bVisible then\\\
12078 redraw()\\\
12079 updateCursorColor()\\\
12080 updateCursorPos()\\\
12081 end\\\
12082 end\\\
12083 end\\\
12084\\\
12085 function window.getTextColor()\\\
12086 return nTextColor\\\
12087 end\\\
12088\\\
12089 function window.getTextColour()\\\
12090 return nTextColor\\\
12091 end\\\
12092\\\
12093 function window.getBackgroundColor()\\\
12094 return nBackgroundColor\\\
12095 end\\\
12096\\\
12097 function window.getBackgroundColour()\\\
12098 return nBackgroundColor\\\
12099 end\\\
12100\\\
12101 -- Other functions\\\
12102 function window.setVisible( bVis )\\\
12103 if type( bVis ) ~= \\\"boolean\\\" then error( \\\"bad argument #1 (expected boolean, got \\\" .. type( bVis ) .. \\\")\\\", 2 ) end\\\
12104 if bVisible ~= bVis then\\\
12105 bVisible = bVis\\\
12106 if bVisible then\\\
12107 window.redraw()\\\
12108 end\\\
12109 end\\\
12110 end\\\
12111\\\
12112 function window.redraw()\\\
12113 if bVisible then\\\
12114 redraw()\\\
12115 updatePalette()\\\
12116 updateCursorBlink()\\\
12117 updateCursorColor()\\\
12118 updateCursorPos()\\\
12119 end\\\
12120 end\\\
12121\\\
12122 function window.restoreCursor()\\\
12123 if bVisible then\\\
12124 updateCursorBlink()\\\
12125 updateCursorColor()\\\
12126 updateCursorPos()\\\
12127 end\\\
12128 end\\\
12129\\\
12130 function window.getPosition()\\\
12131 return nX, nY\\\
12132 end\\\
12133\\\
12134 function window.reposition( nNewX, nNewY, nNewWidth, nNewHeight )\\\
12135 if type( nNewX ) ~= \\\"number\\\" then error( \\\"bad argument #1 (expected number, got \\\" .. type( nNewX ) .. \\\")\\\", 2 ) end\\\
12136 if type( nNewY ) ~= \\\"number\\\" then error( \\\"bad argument #2 (expected number, got \\\" .. type( nNewY ) .. \\\")\\\", 2 ) end\\\
12137 if nNewWidth ~= nil or nNewHeight ~= nil then\\\
12138 if type( nNewWidth ) ~= \\\"number\\\" then error( \\\"bad argument #3 (expected number, got \\\" .. type( nNewWidth ) .. \\\")\\\", 2 ) end\\\
12139 if type( nNewHeight ) ~= \\\"number\\\" then error( \\\"bad argument #4 (expected number, got \\\" .. type( nNewHeight ) .. \\\")\\\", 2 ) end\\\
12140 end\\\
12141\\\
12142 nX = nNewX\\\
12143 nY = nNewY\\\
12144 if nNewWidth and nNewHeight then\\\
12145 local tNewLines = {}\\\
12146 createEmptyLines( nNewWidth )\\\
12147 local sEmptyText = sEmptySpaceLine\\\
12148 local sEmptyTextColor = tEmptyColorLines[ nTextColor ]\\\
12149 local sEmptyBackgroundColor = tEmptyColorLines[ nBackgroundColor ]\\\
12150 for y=1,nNewHeight do\\\
12151 if y > nHeight then\\\
12152 tNewLines[y] = {\\\
12153 text = sEmptyText,\\\
12154 textColor = sEmptyTextColor,\\\
12155 backgroundColor = sEmptyBackgroundColor\\\
12156 }\\\
12157 else\\\
12158 local tOldLine = tLines[y]\\\
12159 if nNewWidth == nWidth then\\\
12160 tNewLines[y] = tOldLine\\\
12161 elseif nNewWidth < nWidth then\\\
12162 tNewLines[y] = {\\\
12163 text = string_sub( tOldLine.text, 1, nNewWidth ),\\\
12164 textColor = string_sub( tOldLine.textColor, 1, nNewWidth ),\\\
12165 backgroundColor = string_sub( tOldLine.backgroundColor, 1, nNewWidth ),\\\
12166 }\\\
12167 else\\\
12168 tNewLines[y] = {\\\
12169 text = tOldLine.text .. string_sub( sEmptyText, nWidth + 1, nNewWidth ),\\\
12170 textColor = tOldLine.textColor .. string_sub( sEmptyTextColor, nWidth + 1, nNewWidth ),\\\
12171 backgroundColor = tOldLine.backgroundColor .. string_sub( sEmptyBackgroundColor, nWidth + 1, nNewWidth ),\\\
12172 }\\\
12173 end\\\
12174 end\\\
12175 end\\\
12176 nWidth = nNewWidth\\\
12177 nHeight = nNewHeight\\\
12178 tLines = tNewLines\\\
12179 end\\\
12180 if bVisible then\\\
12181 window.redraw()\\\
12182 end\\\
12183 end\\\
12184\\\
12185 if bVisible then\\\
12186 window.redraw()\\\
12187 end\\\
12188 return window\\\
12189end\",\
12190 },\
12191}")
12192if fs.isReadOnly(outputPath) then
12193 error("Output path is read only.")
12194elseif fs.getFreeSpace(outputPath) <= #archive then
12195 error("Insufficient space.")
12196end
12197for name, contents in pairs(archive.data) do
12198 stc(colors.lightGray)
12199 write("'" .. name .. "'...")
12200 if contents == true then -- indicates empty directory
12201 fs.makeDir(fs.combine(outputPath, name))
12202 else
12203 file = fs.open(fs.combine(outputPath, name), "w")
12204 if file then
12205 file.write(contents)
12206 file.close()
12207 end
12208 end
12209 if file then
12210 stc(colors.green)
12211 print("good")
12212 else
12213 stc(colors.red)
12214 print("fail")
12215 end
12216end
12217stc(colors.white)
12218write("Unpacked to '")
12219stc(colors.yellow)
12220write(outputPath .. "/")
12221stc(colors.white)
12222print("'.")