· 10 years ago · Sep 20, 2016, 03:04 AM
1{["archive"]="local tArgs = { ... }\
2\
3function saveFile( file, data )\
4 local f = fs.open( file, \"w\" )\
5 f.write( data )\
6 f.close( )\
7end\
8\
9function readFile( file )\
10 if fs.exists( file ) then\
11 local f = fs.open( file, \"r\" )\
12 local inside = f.readAll( )\
13 f.close()\
14 return inside\
15 end\
16end\
17\
18function tableToFile( t, folder )\
19 if not fs.exists( folder ) then fs.makeDir( folder ) end\
20 \
21 for k, v in pairs( t ) do\
22 if type( v ) == \"table\" then\
23 tableToFile( v, folder..\"/\"..k )\
24 end\
25 if type( v ) == \"string\" then\
26 saveFile( folder..\"/\"..k, v )\
27 end\
28 end\
29end\
30\
31function filelistToTable( folder )\
32 local toReturn = { }\
33 local t = fs.list( folder )\
34 for i = 1, #t do\
35 if fs.isDir( folder..\"/\"..t[i] ) then\
36 toReturn[t[i]] = filelistToTable( folder..\"/\"..t[i] )\
37 else\
38 toReturn[t[i]] = readFile( folder..\"/\"..t[i] )\
39 end\
40 end\
41 return toReturn\
42end\
43\
44function printUsage( )\
45 print \"archive pack <folder> <archive>\"\
46 print \"archive compress <folder> <archive>\"\
47 print \"archive unpack <archive> <folder>\"\
48 print \"archive extract <archive> <folder>\"\
49 print \"archive installer <archive> <installer>\"\
50 print \"archive selfextract <archive> <installer>\"\
51end\
52\
53if tArgs[1] == \"pack\" or tArgs[1] == \"compress\" then\
54 if #tArgs < 3 then printUsage( ) return end\
55 local Archive = { }\
56 \
57 if fs.exists( tArgs[2] ) then\
58 print \"done prepairing, making archive\" \
59 Archive = filelistToTable( tArgs[2] )\
60 print \"done making archive now saving\"\
61 saveFile( tArgs[3], textutils.serialize( Archive ) )\
62 print \"done saving archive\"\
63 else\
64 print \"folder does not exist\"\
65 end\
66 \
67end\
68\
69if tArgs[1] == \"unpack\" or tArgs[1] == \"extract\" then\
70 if #tArgs < 3 then printUsage( ) return end\
71 \
72 print \"unpacking/extracting...\"\
73 tableToFile( textutils.unserialize( readFile( tArgs[2] ) ), tArgs[3] ) \
74 print \"unpacking/extracting complete\" \
75 \
76end\
77\
78if tArgs[1] == \"installer\" or tArgs[1] == \"selfextract\" then\
79 print( \"how is should the archive/program be called?\" )\
80 local name = read( )\
81 \
82 print( \"what is the folder to install extract it in? leave blank if you want to let the user enter one\" )\
83 local instdir = read( )\
84 \
85 print( \"what is the message for installing it?\" )\
86 local msg = read( )\
87 \
88 print( \"what os the message when its done?\")\
89 local msgdone = read( )\
90 \
91 print( \"what program should it execute when its done? leave blank for none\" )\
92 local doneexe = read( )\
93 \
94 local s = [[\
95 local archive = ]]..readFile( tArgs[2] )..[[ \
96 local installfolder = ']]..instdir..[['\
97 local name = ']]..name..[[' \
98 local msg = ']]..msg..[[' \
99 local msgdone = ']]..msgdone..[[' \
100 local doneexe = ']]..doneexe..[[' \
101 \
102 function saveFile( file, data )\
103 local f = fs.open( file, 'w' )\
104 f.write( data )\
105 f.close( )\
106 end\
107 \
108 function tableToFile( t, folder )\
109 if not fs.exists( folder ) then fs.makeDir( folder ) end\
110 for k, v in pairs( t ) do\
111 if type( v ) == 'table' then\
112 tableToFile( v, folder..'/'..k )\
113 end\
114 if type( v ) == 'string' then\
115 saveFile( folder..'/'..k, v )\
116 end\
117 end\
118 end\
119 \
120 if installfolder == '' then\
121 print 'please enter the folder where the archive is going to be installed in'\
122 installfolder = read( )\
123 end\
124 print( msg ) \
125 tableToFile( archive, installfolder )\
126 print( msgdone )\
127 if doneexe ~= \"\" then shell.run( doneexe ) end\
128 ]]\
129 \
130 local handle = io.open( tArgs[3], \"w\" )\
131 handle:write( s )\
132 handle:close( )\
133 print \"done making installer/self extractor\"\
134end",["rom"]={["autorun"]={},["apis"]={["keys"]="\
135-- Minecraft key code bindings\
136-- See http://www.minecraftwiki.net/wiki/Key_codes for more info\
137\
138local nothing = 42\
139local tKeys = {\
140 nil, \"one\", \"two\", \"three\", \"four\", -- 1\
141 \"five\", \"six\", \"seven\", \"eight\", \"nine\", -- 6\
142 \"zero\", \"minus\", \"equals\", \"backspace\",\"tab\", -- 11\
143 \"q\", \"w\", \"e\", \"r\", \"t\", -- 16\
144 \"y\", \"u\", \"i\", \"o\", \"p\", -- 21\
145 \"leftBracket\",\"rightBracket\",\"enter\",\"leftCtrl\",\"a\", -- 26\
146 \"s\", \"d\", \"f\", \"g\", \"h\", -- 31\
147 \"j\", \"k\", \"l\", \"semiColon\",\"apostrophe\", -- 36\
148 \"grave\", \"leftShift\",\"backslash\",\"z\", \"x\", -- 41\
149 \"c\", \"v\", \"b\", \"n\", \"m\", -- 46\
150 \"comma\", \"period\", \"slash\", \"rightShift\",\"multiply\", -- 51\
151 \"leftAlt\", \"space\", \"capsLock\", \"f1\", \"f2\", -- 56\
152 \"f3\", \"f4\", \"f5\", \"f6\", \"f7\", -- 61\
153 \"f8\", \"f9\", \"f10\", \"numLock\", \"scollLock\", -- 66 \
154 \"numPad7\", \"numPad8\", \"numPad9\", \"numPadSubtract\",\"numPad4\", -- 71\
155 \"numPad5\", \"numPad6\", \"numPadAdd\",\"numPad1\", \"numPad2\", -- 76\
156 \"numPad3\", \"numPad0\", \"numPadDecimal\",nil, nil, -- 81\
157 nil, \"f11\", \"f12\", nil, nil, -- 86\
158 nil, nil, nil, nil, nil, -- 91\
159 nil, nil, nil, nil, \"f13\", -- 96\
160 \"f14\", \"f15\", nil, nil, nil, -- 101\
161 nil, nil, nil, nil, nil, -- 106\
162 nil, \"kana\", nil, nil, nil, -- 111\
163 nil, nil, nil, nil, nil, -- 116 \
164 \"convert\", nil, \"noconvert\",nil, \"yen\", -- 121\
165 nil, nil, nil, nil, nil, -- 126\
166 nil, nil, nil, nil, nil, -- 131\
167 nil, nil, nil, nil, nil, -- 136\
168 \"numPadEquals\",nil, nil, \"cimcumflex\",\"at\", -- 141\
169 \"colon\", \"underscore\",\"kanji\", \"stop\", \"ax\", -- 146\
170 nil, \"numPadEnter\",\"rightCtrl\",nil, nil, -- 151\
171 nil, nil, nil, nil, nil, -- 156\
172 nil, nil, nil, nil, nil, -- 161\
173 nil, nil, nil, nil, nil, -- 166\
174 nil, nil, nil, nil, nil, -- 171\
175 nil, nil, nil, \"numPadComma\",nil, -- 176\
176 \"numPadDivide\",nil, nil, \"rightAlt\", nil, -- 181\
177 nil, nil, nil, nil, nil, -- 186\
178 nil, nil, nil, nil, nil, -- 191\
179 nil, \"pause\", nil, \"home\", \"up\", -- 196\
180 \"pageUp\", nil, \"left\", nil, \"right\", -- 201\
181 nil, \"end\", \"down\", \"pageDown\", \"insert\", -- 206\
182 \"delete\" -- 211\
183}\
184\
185local keys = getfenv()\
186for nKey, sKey in pairs( tKeys ) do\
187 keys[sKey] = nKey\
188end\
189keys[\"return\"] = keys.enter\
190\
191function getName( _nKey )\
192 return tKeys[ _nKey ]\
193end",["vector"]="\
194local vector = {\
195 add = function( self, o )\
196 return vector.new(\
197 self.x + o.x,\
198 self.y + o.y,\
199 self.z + o.z\
200 )\
201 end,\
202 sub = function( self, o )\
203 return vector.new(\
204 self.x - o.x,\
205 self.y - o.y,\
206 self.z - o.z\
207 )\
208 end,\
209 mul = function( self, m )\
210 return vector.new(\
211 self.x * m,\
212 self.y * m,\
213 self.z * m\
214 )\
215 end,\
216 dot = function( self, o )\
217 return self.x*o.x + self.y*o.y + self.z*o.z\
218 end,\
219 cross = function( self, o )\
220 return vector.new(\
221 self.y*o.z - self.z*o.y,\
222 self.z*o.x - self.x*o.z,\
223 self.x*o.y - self.y*o.x\
224 )\
225 end,\
226 length = function( self )\
227 return math.sqrt( self.x*self.x + self.y*self.y + self.z*self.z )\
228 end,\
229 normalize = function( self )\
230 return self:mul( 1 / self:length() )\
231 end,\
232 round = function( self )\
233 return vector.new(\
234 math.floor( self.x + 0.5 ),\
235 math.floor( self.y + 0.5 ),\
236 math.floor( self.z + 0.5 )\
237 )\
238 end,\
239 tostring = function( self )\
240 return self.x..\",\"..self.y..\",\"..self.z\
241 end,\
242}\
243\
244local vmetatable = {\
245 __index = vector,\
246 __add = vector.add,\
247 __sub = vector.sub,\
248 __mul = vector.mul,\
249 __unm = function( v ) return v:mul(-1) end,\
250 __tostring = vector.tostring,\
251}\
252\
253function new( x, y, z )\
254 local v = {\
255 x = x or 0,\
256 y = y or 0,\
257 z = z or 0\
258 }\
259 setmetatable( v, vmetatable )\
260 return v\
261end",["rednet"]="\
262CHANNEL_BROADCAST = 65535\
263\
264function open( sModem )\
265 if type( sModem ) ~= \"string\" then\
266 error( \"string expected\" )\
267 end\
268 if peripheral.getType( sModem ) ~= \"modem\" then \
269 error( \"No such modem: \"..sModem )\
270 end\
271 peripheral.call( sModem, \"open\", os.getComputerID() )\
272 peripheral.call( sModem, \"open\", CHANNEL_BROADCAST )\
273end\
274\
275function close( sModem )\
276 if type( sModem ) ~= \"string\" then\
277 error( \"string expected\" )\
278 end\
279 if peripheral.getType( sModem ) ~= \"modem\" then \
280 error( \"No such modem: \"..sModem )\
281 end\
282 peripheral.call( sModem, \"close\", os.getComputerID() )\
283 peripheral.call( sModem, \"close\", CHANNEL_BROADCAST )\
284end\
285\
286function isOpen( sModem )\
287 if type( sModem ) ~= \"string\" then\
288 error( \"string expected\" )\
289 end\
290 if peripheral.getType( sModem ) == \"modem\" then \
291 return peripheral.call( sModem, \"isOpen\", os.getComputerID() ) and peripheral.call( sModem, \"isOpen\", CHANNEL_BROADCAST )\
292 end\
293 return false\
294end\
295\
296function send( nRecipient, sMessage )\
297 for n,sModem in ipairs( peripheral.getNames() ) do\
298 if isOpen( sModem ) then\
299 peripheral.call( sModem, \"transmit\", nRecipient, os.getComputerID(), sMessage )\
300 return true\
301 end\
302 end\
303 error( \"No open sides\" )\
304end\
305\
306function broadcast( sMessage )\
307 send( CHANNEL_BROADCAST, sMessage )\
308end\
309\
310function receive( nTimeout )\
311 local timer = nil\
312 local sFilter = nil\
313 if nTimeout then\
314 timer = os.startTimer( nTimeout )\
315 sFilter = nil\
316 else\
317 sFilter = \"rednet_message\"\
318 end\
319 while true do\
320 local e, p1, p2, p3, p4, p5 = os.pullEvent( sFilter )\
321 if e == \"rednet_message\" then\
322 local nSenderID, sMessage, nDistance = p1, p2, p3\
323 return nSenderID, sMessage, nDistance\
324 elseif e == \"timer\" and p1 == timer then\
325 return nil\
326 end\
327 end\
328end\
329\
330local bRunning = false\
331function run()\
332 if bRunning then\
333 error( \"rednet is already running\" )\
334 end\
335 bRunning = true\
336 \
337 while bRunning do\
338 local sEvent, sModem, nChannel, nReplyChannel, sMessage, nDistance = os.pullEventRaw( \"modem_message\" )\
339 if sEvent == \"modem_message\" and isOpen( sModem ) and (nChannel == os.getComputerID() or nChannel == CHANNEL_BROADCAST) then\
340 os.queueEvent( \"rednet_message\", nReplyChannel, sMessage, nDistance )\
341 end\
342 end\
343end",["peripheral"]="local native = peripheral\
344\
345function getNames()\
346 local tResults = {}\
347 for n,sSide in ipairs( rs.getSides() ) do\
348 if native.isPresent( sSide ) then\
349 table.insert( tResults, sSide )\
350 if native.getType( sSide ) == \"modem\" and not native.call( sSide, \"isWireless\" ) then\
351 local tRemote = native.call( sSide, \"getNamesRemote\" )\
352 for n,sName in ipairs( tRemote ) do\
353 table.insert( tResults, sName )\
354 end\
355 end\
356 end\
357 end\
358 return tResults\
359end\
360\
361function isPresent( _sSide )\
362 if native.isPresent( _sSide ) then\
363 return true\
364 end\
365 for n,sSide in ipairs( rs.getSides() ) do\
366 if native.getType( sSide ) == \"modem\" and not native.call( sSide, \"isWireless\" ) then\
367 if native.call( sSide, \"isPresentRemote\", _sSide ) then\
368 return true\
369 end\
370 end\
371 end\
372 return false\
373end\
374\
375function getType( _sSide )\
376 if native.isPresent( _sSide ) then\
377 return native.getType( _sSide )\
378 end\
379 for n,sSide in ipairs( rs.getSides() ) do\
380 if native.getType( sSide ) == \"modem\" and not native.call( sSide, \"isWireless\" ) then\
381 if native.call( sSide, \"isPresentRemote\", _sSide ) then\
382 return native.call( sSide, \"getTypeRemote\", _sSide ) \
383 end\
384 end\
385 end\
386 return nil\
387end\
388\
389function getMethods( _sSide )\
390 if native.isPresent( _sSide ) then\
391 return native.getMethods( _sSide )\
392 end\
393 for n,sSide in ipairs( rs.getSides() ) do\
394 if native.getType( sSide ) == \"modem\" and not native.call( sSide, \"isWireless\" ) then\
395 if native.call( sSide, \"isPresentRemote\", _sSide ) then\
396 return native.call( sSide, \"getMethodsRemote\", _sSide ) \
397 end\
398 end\
399 end\
400 return nil\
401end\
402\
403function call( _sSide, _sMethod, ... )\
404 if native.isPresent( _sSide ) then\
405 return native.call( _sSide, _sMethod, ... )\
406 end\
407 for n,sSide in ipairs( rs.getSides() ) do\
408 if native.getType( sSide ) == \"modem\" and not native.call( sSide, \"isWireless\" ) then\
409 if native.call( sSide, \"isPresentRemote\", _sSide ) then\
410 return native.call( sSide, \"callRemote\", _sSide, _sMethod, ... ) \
411 end\
412 end\
413 end\
414 return nil\
415end\
416\
417function wrap( _sSide )\
418 if peripheral.isPresent( _sSide ) then\
419 local tMethods = peripheral.getMethods( _sSide )\
420 local tResult = {}\
421 for n,sMethod in ipairs( tMethods ) do\
422 tResult[sMethod] = function( ... )\
423 return peripheral.call( _sSide, sMethod, ... )\
424 end\
425 end\
426 return tResult\
427 end\
428 return nil\
429end",["parallel"]="\
430local function create( first, ... )\
431 if first ~= nil then\
432 return coroutine.create(first), create( ... )\
433 end\
434 return nil\
435end\
436\
437local function runUntilLimit( _routines, _limit )\
438 local count = #_routines\
439 local living = count\
440 \
441 local tFilters = {}\
442 local eventData = {}\
443 while true do\
444 for n=1,count do\
445 local r = _routines[n]\
446 if r then\
447 if tFilters[r] == nil or tFilters[r] == eventData[1] or eventData[1] == \"terminate\" then\
448 local ok, param = coroutine.resume( r, unpack(eventData) )\
449 if not ok then\
450 error( param )\
451 else\
452 tFilters[r] = param\
453 end\
454 if coroutine.status( r ) == \"dead\" then\
455 _routines[n] = nil\
456 living = living - 1\
457 if living <= _limit then\
458 return n\
459 end\
460 end\
461 end\
462 end\
463 end\
464 for n=1,count do\
465 local r = _routines[n]\
466 if r and coroutine.status( r ) == \"dead\" then\
467 _routines[n] = nil\
468 living = living - 1\
469 if living <= _limit then\
470 return n\
471 end\
472 end\
473 end\
474 eventData = { os.pullEventRaw() }\
475 end\
476end\
477\
478function waitForAny( ... )\
479 local routines = { create( ... ) }\
480 return runUntilLimit( routines, #routines - 1 )\
481end\
482\
483function waitForAll( ... )\
484 local routines = { create( ... ) }\
485 runUntilLimit( routines, 0 )\
486end",["turtle"]={["turtle"]="\
487if not turtle then\
488 error( \"Cannot load turtle API on computer\" )\
489end\
490\
491native = turtle.native or turtle\
492\
493local function waitForResponse( _id )\
494 local event, responseID, success\
495 while event ~= \"turtle_response\" or responseID ~= _id do\
496 event, responseID, success, error = os.pullEvent( \"turtle_response\" )\
497 end\
498 if success then\
499 return true\
500 else\
501 return false, error\
502 end\
503end\
504\
505local function wrap( _sCommand )\
506 return function( ... )\
507 local id = native[_sCommand]( ... )\
508 if id == -1 then\
509 return false\
510 end\
511 return waitForResponse( id )\
512 end\
513end\
514\
515-- Wrap standard commands\
516local turtle = {}\
517turtle[\"getItemCount\"] = native.getItemCount\
518turtle[\"getItemSpace\"] = native.getItemSpace\
519turtle[\"getFuelLevel\"] = native.getFuelLevel\
520\
521for k,v in pairs( native ) do\
522 if type( k ) == \"string\" and type( v ) == \"function\" then\
523 if turtle[k] == nil then\
524 turtle[k] = wrap( k )\
525 end\
526 end\
527end\
528\
529-- Wrap peripheral commands\
530if peripheral.getType(\"left\") == \"workbench\" then\
531 turtle[\"craft\"] = function( ... )\
532 local id = peripheral.call( \"left\", \"craft\", ... )\
533 return waitForResponse( id )\
534 end\
535elseif peripheral.getType(\"right\") == \"workbench\" then\
536 turtle[\"craft\"] = function( ... )\
537 local id = peripheral.call( \"right\", \"craft\", ... )\
538 return waitForResponse( id )\
539 end\
540end\
541\
542-- Put commands into environment table\
543local env = getfenv()\
544for k,v in pairs( turtle ) do\
545 env[k] = v\
546end",},["colors"]="-- Colors\
547white = 1\
548orange = 2\
549magenta = 4\
550lightBlue = 8\
551yellow = 16\
552lime = 32\
553pink = 64\
554gray = 128\
555lightGray = 256\
556cyan = 512\
557purple = 1024\
558blue = 2048\
559brown = 4096\
560green = 8192\
561red = 16384\
562black = 32768\
563\
564function combine( ... )\
565 local r = 0\
566 for n,c in ipairs( { ... } ) do\
567 r = bit.bor(r,c)\
568 end\
569 return r\
570end\
571\
572function subtract( colors, ... )\
573 local r = colors\
574 for n,c in ipairs( { ... } ) do\
575 r = bit.band(r, bit.bnot(c))\
576 end\
577 return r\
578end\
579\
580function test( colors, color )\
581 return ((bit.band(colors, color)) == color)\
582end",["term"]="\
583native = term.native or term\
584\
585local redirectTarget = native\
586local tRedirectStack = {}\
587\
588local function wrap( _sFunction )\
589 return function( ... )\
590 return redirectTarget[ _sFunction ]( ... )\
591 end\
592end\
593\
594local term = {}\
595term.redirect = function( _object )\
596 if _object == nil or type( _object ) ~= \"table\" then\
597 error( \"Invalid redirect object\" )\
598 end\
599 for k,v in pairs( native ) do\
600 if type( k ) == \"string\" and type( v ) == \"function\" then\
601 if type( _object[k] ) ~= \"function\" then\
602 _object[k] = function() \
603 term.restore()\
604 error( \"Redirect object is missing method \"..k..\". Restoring.\")\
605 end\
606 end\
607 end\
608 end\
609\
610 tRedirectStack[#tRedirectStack + 1] = redirectTarget\
611 redirectTarget = _object\
612end\
613term.restore = function()\
614 if #tRedirectStack > 0 then\
615 redirectTarget = tRedirectStack[#tRedirectStack] \
616 tRedirectStack[#tRedirectStack] = nil\
617 end\
618end\
619for k,v in pairs( native ) do\
620 if type( k ) == \"string\" and type( v ) == \"function\" then\
621 if term[k] == nil then\
622 term[k] = wrap( k )\
623 end\
624 end\
625end\
626 \
627local env = getfenv()\
628for k,v in pairs( term ) do\
629 env[k] = v\
630end",["io"]="-- Definition for the IO API\
631\
632local g_defaultInput = {\
633 bFileHandle = true,\
634 bClosed = false,\
635 close = function( self )\
636 end,\
637 read = function( self, _sFormat )\
638 if _sFormat and _sFormat ~= \"*l\" then\
639 error( \"Unsupported format\" )\
640 end\
641 return _G.read()\
642 end,\
643 lines = function( self )\
644 return function()\
645 return _G.read()\
646 end\
647 end,\
648}\
649\
650local g_defaultOutput = {\
651 bFileHandle = true,\
652 bClosed = false,\
653 close = function( self )\
654 end,\
655 write = function( self, _sText )\
656 _G.write( _sText )\
657 end,\
658 flush = function( self )\
659 end,\
660}\
661\
662local g_currentInput = g_defaultInput\
663local g_currentOutput = g_defaultOutput\
664\
665function close( _file )\
666 (_file or g_currentOutput):close()\
667end\
668\
669function flush()\
670 g_currentOutput:flush()\
671end\
672\
673function input( _arg )\
674 if _G.type( _arg ) == \"string\" then\
675 g_currentInput = open( _arg, \"r\" )\
676 elseif _G.type( _arg ) == \"table\" then\
677 g_currentInput = _arg\
678 elseif _G.type( _arg ) == \"nil\" then\
679 return g_currentInput\
680 else\
681 error( \"Expected file name or file handle\" )\
682 end\
683end\
684\
685function lines( _sFileName )\
686 if _sFileName then\
687 return open( _sFileName, \"r\" ):lines()\
688 else\
689 return g_currentInput:lines()\
690 end\
691end\
692\
693function open( _sPath, _sMode )\
694 local sMode = _sMode or \"r\"\
695 local file = fs.open( _sPath, sMode )\
696 if not file then\
697 return nil\
698 end\
699 \
700 if sMode == \"r\"then\
701 return {\
702 bFileHandle = true,\
703 bClosed = false, \
704 close = function( self )\
705 file.close()\
706 self.bClosed = true\
707 end,\
708 read = function( self, _sFormat )\
709 local sFormat = _sFormat or \"*l\"\
710 if sFormat == \"*l\" then\
711 return file.readLine()\
712 elseif sFormat == \"*a\" then\
713 return file.readAll()\
714 else\
715 error( \"Unsupported format\" )\
716 end\
717 return nil\
718 end,\
719 lines = function( self )\
720 return function()\
721 local sLine = file.readLine()\
722 if sLine == nil then\
723 file.close()\
724 self.bClosed = true\
725 end\
726 return sLine\
727 end\
728 end,\
729 }\
730 elseif sMode == \"w\" or sMode == \"a\" then\
731 return {\
732 bFileHandle = true,\
733 bClosed = false, \
734 close = function( self )\
735 file.close()\
736 self.bClosed = true\
737 end,\
738 write = function( self, _sText )\
739 file.write( _sText )\
740 end,\
741 flush = function( self )\
742 file.flush()\
743 end,\
744 }\
745 \
746 elseif sMode == \"rb\" then\
747 return {\
748 bFileHandle = true,\
749 bClosed = false, \
750 close = function( self )\
751 file.close()\
752 self.bClosed = true\
753 end,\
754 read = function( self )\
755 return file.read()\
756 end,\
757 }\
758 \
759 elseif sMode == \"wb\" or sMode == \"ab\" then\
760 return {\
761 bFileHandle = true,\
762 bClosed = false, \
763 close = function( self )\
764 file.close()\
765 self.bClosed = true\
766 end,\
767 write = function( self, _number )\
768 file.write( _number )\
769 end,\
770 flush = function( self )\
771 file.flush()\
772 end,\
773 }\
774 \
775 else\
776 file.close()\
777 error( \"Unsupported mode\" )\
778 \
779 end\
780end\
781\
782function output( _arg )\
783 if _G.type( _arg ) == \"string\" then\
784 g_currentOutput = open( _arg, \"w\" )\
785 elseif _G.type( _arg ) == \"table\" then\
786 g_currentOutput = _arg\
787 elseif _G.type( _arg ) == \"nil\" then\
788 return g_currentOutput\
789 else\
790 error( \"Expected file name or file handle\" )\
791 end\
792end\
793\
794function read( ... )\
795 return input():read( ... )\
796end\
797\
798function type( _handle )\
799 if _G.type( _handle ) == \"table\" and _handle.bFileHandle == true then\
800 if _handle.bClosed then\
801 return \"closed file\"\
802 else\
803 return \"file\"\
804 end\
805 end\
806 return nil\
807end\
808\
809function write( ... )\
810 return output():write( ... )\
811end",["colours"]="-- Colours (for lovers of british spelling)\
812local fnFile, err = loadfile(\"/rom/apis/colors\")\
813if not fnFile then\
814 error( err )\
815end\
816\
817local tColors = {}\
818setmetatable( tColors, { __index = _G } )\
819setfenv( fnFile, tColors )\
820fnFile( tColors )\
821\
822local tColours = getfenv()\
823for k,v in pairs( tColors ) do\
824 tColours[k] = v\
825end\
826\
827tColours.gray = nil\
828tColours.grey = tColors.gray\
829\
830tColours.lightGray = nil\
831tColours.lightGrey = tColors.lightGray",["textutils"]="\
832function slowWrite( sText, nRate )\
833 nRate = nRate or 20\
834 if nRate < 0 then\
835 error( \"rate must be positive\" )\
836 end\
837 local nSleep = 1 / nRate\
838 \
839 sText = tostring( sText )\
840 local x,y = term.getCursorPos(x,y)\
841 local len = string.len( sText )\
842 \
843 for n=1,len do\
844 term.setCursorPos( x, y )\
845 sleep( nSleep )\
846 local nLines = write( string.sub( sText, 1, n ) )\
847 local newX, newY = term.getCursorPos()\
848 y = newY - nLines\
849 end\
850end\
851\
852function slowPrint( sText, nRate )\
853 slowWrite( sText, nRate)\
854 print()\
855end\
856\
857function formatTime( nTime, bTwentyFourHour )\
858 local sTOD = nil\
859 if not bTwentyFourHour then\
860 if nTime >= 12 then\
861 sTOD = \"PM\"\
862 else\
863 sTOD = \"AM\"\
864 end\
865 if nTime >= 13 then\
866 nTime = nTime - 12\
867 end\
868 end\
869\
870 local nHour = math.floor(nTime)\
871 local nMinute = math.floor((nTime - nHour)*60)\
872 if sTOD then\
873 return string.format( \"%d:%02d %s\", nHour, nMinute, sTOD )\
874 else\
875 return string.format( \"%d:%02d\", nHour, nMinute )\
876 end\
877end\
878\
879local function makePagedScroll( _term, _nFreeLines )\
880 local nativeScroll = _term.scroll\
881 local nFreeLines = _nFreeLines or 0\
882 return function( _n )\
883 for n=1,_n do\
884 nativeScroll( 1 )\
885 \
886 if nFreeLines <= 0 then\
887 local w,h = _term.getSize()\
888 _term.setCursorPos( 1, h )\
889 _term.write( \"Press any key to continue\" )\
890 os.pullEvent( \"key\" )\
891 _term.clearLine()\
892 _term.setCursorPos( 1, h )\
893 else\
894 nFreeLines = nFreeLines - 1\
895 end\
896 end\
897 end\
898end\
899\
900function pagedPrint( _sText, _nFreeLines )\
901 local nativeScroll = term.scroll\
902 term.scroll = makePagedScroll( term, _nFreeLines )\
903 local result\
904 local ok, err = pcall( function()\
905 result = print( _sText )\
906 end )\
907 term.scroll = nativeScroll\
908 if not ok then\
909 error( err )\
910 end\
911 return result\
912end\
913\
914local function tabulateCommon( bPaged, ... )\
915 local tAll = { ... }\
916 \
917 local w,h = term.getSize()\
918 local nMaxLen = w / 8\
919 for n, t in ipairs( tAll ) do\
920 if type(t) == \"table\" then\
921 for n, sItem in pairs(t) do\
922 nMaxLen = math.max( string.len( sItem ) + 1, nMaxLen )\
923 end\
924 end\
925 end\
926 local nCols = math.floor( w / nMaxLen )\
927\
928 local nLines = 0\
929 local function newLine()\
930 if bPaged and nLines >= (h-3) then\
931 pagedPrint()\
932 else\
933 print()\
934 end\
935 nLines = nLines + 1\
936 end\
937 \
938 local function drawCols( _t )\
939 local nCol = 1\
940 for n, s in ipairs( _t ) do\
941 if nCol > nCols then\
942 nCol = 1\
943 newLine()\
944 end\
945\
946 local cx,cy = term.getCursorPos()\
947 cx = 1 + (nCol - 1) * (w / nCols)\
948 term.setCursorPos( cx, cy )\
949 term.write( s )\
950\
951 nCol = nCol + 1 \
952 end\
953 print()\
954 end\
955 for n, t in ipairs( tAll ) do\
956 if type(t) == \"table\" then\
957 if #t > 0 then\
958 drawCols( t )\
959 end\
960 elseif type(t) == \"number\" then\
961 term.setTextColor( t )\
962 end\
963 end \
964end\
965\
966function tabulate( ... )\
967 tabulateCommon( false, ... )\
968end\
969\
970function pagedTabulate( ... )\
971 tabulateCommon( true, ... )\
972end\
973\
974local function serializeImpl( t, tTracking ) \
975 local sType = type(t)\
976 if sType == \"table\" then\
977 if tTracking[t] ~= nil then\
978 error( \"Cannot serialize table with recursive entries\" )\
979 end\
980 tTracking[t] = true\
981 \
982 local result = \"{\"\
983 for k,v in pairs(t) do\
984 result = result..(\"[\"..serializeImpl(k, tTracking)..\"]=\"..serializeImpl(v, tTracking)..\",\")\
985 end\
986 result = result..\"}\"\
987 return result\
988 \
989 elseif sType == \"string\" then\
990 return string.format( \"%q\", t )\
991 \
992 elseif sType == \"number\" or sType == \"boolean\" or sType == \"nil\" then\
993 return tostring(t)\
994 \
995 else\
996 error( \"Cannot serialize type \"..sType )\
997 \
998 end\
999end\
1000\
1001function serialize( t )\
1002 local tTracking = {}\
1003 return serializeImpl( t, tTracking )\
1004end\
1005\
1006function unserialize( s )\
1007 local func, e = loadstring( \"return \"..s, \"serialize\" )\
1008 if not func then\
1009 return s\
1010 else\
1011 setfenv( func, {} )\
1012 return func()\
1013 end\
1014end\
1015\
1016function urlEncode( str )\
1017 if str then\
1018 str = string.gsub (str, \"\\n\", \"\\r\\n\")\
1019 str = string.gsub (str, \"([^%w ])\",\
1020 function (c)\
1021 return string.format (\"%%%02X\", string.byte(c))\
1022 end)\
1023 str = string.gsub (str, \" \", \"+\")\
1024 end\
1025 return str \
1026end\
1027",["disk"]="\
1028local function isDrive( side )\
1029 return peripheral.getType( side ) == \"drive\"\
1030end\
1031\
1032function isPresent( side )\
1033 if isDrive( side ) then\
1034 return peripheral.call( side, \"isDiskPresent\" )\
1035 end\
1036 return false\
1037end\
1038\
1039function getLabel( side )\
1040 if isDrive( side ) then\
1041 return peripheral.call( side, \"getDiskLabel\" )\
1042 end\
1043 return nil\
1044end\
1045\
1046function setLabel( side, label )\
1047 if isDrive( side ) then\
1048 peripheral.call( side, \"setDiskLabel\", label )\
1049 end\
1050end\
1051\
1052function hasData( side )\
1053 if isDrive( side ) then\
1054 return peripheral.call( side, \"hasData\" )\
1055 end\
1056 return false\
1057end\
1058\
1059function getMountPath( side )\
1060 if isDrive( side ) then\
1061 return peripheral.call( side, \"getMountPath\" )\
1062 end\
1063 return nil\
1064end\
1065\
1066function hasAudio( side )\
1067 if isDrive( side ) then\
1068 return peripheral.call( side, \"hasAudio\" )\
1069 end\
1070 return false\
1071end\
1072\
1073function getAudioTitle( side )\
1074 if isDrive( side ) then\
1075 return peripheral.call( side, \"getAudioTitle\" )\
1076 end\
1077 return nil\
1078end\
1079\
1080function playAudio( side )\
1081 if isDrive( side ) then\
1082 peripheral.call( side, \"playAudio\" )\
1083 end\
1084end\
1085\
1086function stopAudio( side )\
1087 if not side then\
1088 for n,sSide in ipairs( peripheral.getNames() ) do\
1089 stopAudio( sSide )\
1090 end\
1091 else\
1092 if isDrive( side ) then\
1093 peripheral.call( side, \"stopAudio\" )\
1094 end\
1095 end\
1096end\
1097\
1098function eject( side )\
1099 if isDrive( side ) then\
1100 peripheral.call( side, \"ejectDisk\" )\
1101 end\
1102end\
1103\
1104function getID( side )\
1105 if isDrive( side ) then\
1106 return peripheral.call( side, \"getDiskID\" )\
1107 end\
1108 return nil\
1109end\
1110",["paintutils"]="\
1111local function drawPixelInternal( xPos, yPos )\
1112 term.setCursorPos(xPos, yPos)\
1113 term.write(\" \")\
1114end\
1115\
1116local tColourLookup = {}\
1117for n=1,16 do\
1118 tColourLookup[ string.byte( \"0123456789abcdef\",n,n ) ] = 2^(n-1)\
1119end\
1120\
1121function loadImage( sPath )\
1122 local tImage = {}\
1123 if fs.exists( sPath ) then\
1124 local file = io.open(sPath, \"r\" )\
1125 local sLine = file:read()\
1126 while sLine do\
1127 local tLine = {}\
1128 for x=1,sLine:len() do\
1129 tLine[x] = tColourLookup[ string.byte(sLine,x,x) ] or 0\
1130 end\
1131 table.insert( tImage, tLine )\
1132 sLine = file:read()\
1133 end\
1134 file:close()\
1135 return tImage\
1136 end\
1137 return nil\
1138end\
1139\
1140function drawPixel( xPos, yPos, nColour )\
1141 if nColour then\
1142 term.setBackgroundColor( nColour )\
1143 end\
1144 drawPixelInternal( xPos, yPos )\
1145end\
1146\
1147function drawLine( startX, startY, endX, endY, nColour )\
1148 if nColour then\
1149 term.setBackgroundColor( nColour )\
1150 end\
1151 \
1152 startX = math.floor(startX)\
1153 startY = math.floor(startY)\
1154 endX = math.floor(endX)\
1155 endY = math.floor(endY)\
1156 \
1157 if startX == endX and startY == endY then\
1158 drawPixelInternal( startX, startY )\
1159 return\
1160 end\
1161 \
1162 local minX = math.min( startX, endX )\
1163 if minX == startX then\
1164 minY = startY\
1165 maxX = endX\
1166 maxY = endY\
1167 else\
1168 minY = endY\
1169 maxX = startX\
1170 maxY = startY\
1171 end\
1172 \
1173 local xDiff = maxX - minX\
1174 local yDiff = maxY - minY\
1175 \
1176 if xDiff > math.abs(yDiff) then\
1177 local y = minY\
1178 local dy = yDiff / xDiff\
1179 for x=minX,maxX do\
1180 drawPixelInternal( x, math.floor( y + 0.5 ) )\
1181 y = y + dy\
1182 end\
1183 else\
1184 local x = minX\
1185 local dx = xDiff / yDiff\
1186 if maxY >= minY then\
1187 for y=minY,maxY do\
1188 drawPixelInternal( math.floor( x + 0.5 ), y )\
1189 x = x + dx\
1190 end\
1191 else\
1192 for y=minY,maxY,-1 do\
1193 drawPixelInternal( math.floor( x + 0.5 ), y )\
1194 x = x - dx\
1195 end\
1196 end\
1197 end\
1198end\
1199\
1200function drawImage( tImage, xPos, yPos )\
1201 for y=1,#tImage do\
1202 local tLine = tImage[y]\
1203 for x=1,#tLine do\
1204 if tLine[x] > 0 then\
1205 term.setBackgroundColor( tLine[x] )\
1206 drawPixelInternal( x + xPos - 1, y + yPos - 1 )\
1207 end\
1208 end\
1209 end\
1210end",["gps"]="\
1211CHANNEL_GPS = 65534\
1212\
1213local function trilaterate( A, B, C )\
1214 local a2b = B.position - A.position\
1215 local a2c = C.position - A.position\
1216 \
1217 if math.abs( a2b:normalize():dot( a2c:normalize() ) ) > 0.999 then\
1218 return nil\
1219 end\
1220 \
1221 local d = a2b:length()\
1222 local ex = a2b:normalize( )\
1223 local i = ex:dot( a2c )\
1224 local ey = (a2c - (ex * i)):normalize()\
1225 local j = ey:dot( a2c )\
1226 local ez = ex:cross( ey )\
1227\
1228 local r1 = A.distance\
1229 local r2 = B.distance\
1230 local r3 = C.distance\
1231 \
1232 local x = (r1*r1 - r2*r2 + d*d) / (2*d)\
1233 local y = (r1*r1 - r3*r3 - x*x + (x-i)*(x-i) + j*j) / (2*j)\
1234 \
1235 local result = A.position + (ex * x) + (ey * y)\
1236\
1237 local zSquared = r1*r1 - x*x - y*y\
1238 if zSquared > 0 then\
1239 local z = math.sqrt( zSquared )\
1240 local result1 = result + (ez * z)\
1241 local result2 = result - (ez * z)\
1242 \
1243 local rounded1, rounded2 = result1:round(), result2:round()\
1244 if rounded1.x ~= rounded2.x or rounded1.y ~= rounded2.y or rounded1.z ~= rounded2.z then\
1245 return rounded1, rounded2\
1246 else\
1247 return rounded1\
1248 end\
1249 end\
1250 return result:round()\
1251 \
1252end\
1253\
1254local function narrow( p1, p2, fix )\
1255 local dist1 = math.abs( (p1 - fix.position):length() - fix.distance )\
1256 local dist2 = math.abs( (p2 - fix.position):length() - fix.distance )\
1257 \
1258 if math.abs(dist1 - dist2) < 0.05 then\
1259 return p1, p2\
1260 elseif dist1 < dist2 then\
1261 return p1:round()\
1262 else\
1263 return p2:round()\
1264 end\
1265end\
1266\
1267function locate( _nTimeout, _bDebug )\
1268\
1269 -- Find a modem\
1270 local sModemSide = nil\
1271 for n,sSide in ipairs( rs.getSides() ) do\
1272 if peripheral.getType( sSide ) == \"modem\" and peripheral.call( sSide, \"isWireless\" ) then \
1273 sModemSide = sSide\
1274 break\
1275 end\
1276 end\
1277\
1278 if sModemSide == nil then\
1279 if _bDebug then\
1280 print( \"No wireless modem attached\" )\
1281 end\
1282 return nil\
1283 end\
1284 \
1285 if _bDebug then\
1286 print( \"Finding position...\" )\
1287 end\
1288 \
1289 -- Open a channel\
1290 local modem = peripheral.wrap( sModemSide )\
1291 local bCloseChannel = false\
1292 if not modem.isOpen( os.getComputerID() ) then\
1293 modem.open( os.getComputerID() )\
1294 bCloseChannel = true\
1295 end\
1296 \
1297 -- Send a ping to listening GPS hosts\
1298 modem.transmit( CHANNEL_GPS, os.getComputerID(), \"PING\" )\
1299 \
1300 -- Wait for the responses\
1301 local tFixes = {}\
1302 local pos1, pos2 = nil\
1303 local timeout = os.startTimer( _nTimeout or 2 )\
1304 while true do\
1305 local e, p1, p2, p3, p4, p5 = os.pullEvent()\
1306 if e == \"modem_message\" then\
1307 -- We received a message from a modem\
1308 local sSide, sChannel, sReplyChannel, sMessage, nDistance = p1, p2, p3, p4, p5\
1309 if sSide == sModemSide and sChannel == os.getComputerID() and sReplyChannel == CHANNEL_GPS then\
1310 -- Received the correct message from the correct modem: use it to determine position\
1311 local tResult = textutils.unserialize( sMessage )\
1312 if type(tResult) == \"table\" and #tResult == 3 then\
1313 local tFix = { position = vector.new( tResult[1], tResult[2], tResult[3] ), distance = nDistance }\
1314 if _bDebug then\
1315 print( tFix.distance..\" metres from \"..tostring( tFix.position ) )\
1316 end\
1317 table.insert( tFixes, tFix )\
1318 if #tFixes >= 3 then\
1319 if not pos1 then\
1320 pos1, pos2 = trilaterate( tFixes[1], tFixes[2], tFixes[#tFixes] )\
1321 else\
1322 pos1, pos2 = narrow( pos1, pos2, tFixes[#tFixes] )\
1323 end\
1324 end\
1325 \
1326 if pos1 and not pos2 then\
1327 break\
1328 end\
1329 end\
1330 end\
1331 \
1332 elseif e == \"timer\" then\
1333 -- We received a timeout\
1334 local timer = p1\
1335 if timer == timeout then\
1336 break\
1337 end\
1338 \
1339 end \
1340 end\
1341 \
1342 -- Close the channel, if we opened one\
1343 if bCloseChannel then\
1344 modem.close( os.getComputerID() )\
1345 end\
1346 \
1347 -- Return the response\
1348 if pos1 and pos2 then\
1349 if _bDebug then\
1350 print( \"Ambiguous position\" )\
1351 print( \"Could be \"..pos1.x..\",\"..pos1.y..\",\"..pos1.z..\" or \"..pos2.x..\",\"..pos2.y..\",\"..pos2.z )\
1352 end\
1353 return nil\
1354 elseif pos1 then\
1355 if _bDebug then\
1356 print( \"Position is \"..pos1.x..\",\"..pos1.y..\",\"..pos1.z )\
1357 end\
1358 return pos1.x, pos1.y, pos1.z\
1359 else\
1360 if _bDebug then\
1361 print( \"Could not determine position\" )\
1362 end\
1363 return nil\
1364 end\
1365end",["help"]="\
1366local sPath = \"/rom/help\"\
1367\
1368function path()\
1369 return sPath\
1370end\
1371\
1372function setPath( _sPath )\
1373 sPath = _sPath\
1374end\
1375\
1376function lookup( _sTopic )\
1377 -- Look on the path variable\
1378 for sPath in string.gmatch(sPath, \"[^:]+\") do\
1379 sPath = fs.combine( sPath, _sTopic )\
1380 if fs.exists( sPath ) and not fs.isDir( sPath ) then\
1381 return sPath\
1382 end\
1383 end\
1384 \
1385 -- Not found\
1386 return nil\
1387end\
1388\
1389function topics()\
1390 local tItems = {}\
1391 \
1392 -- Add topics from the path\
1393 for sPath in string.gmatch(sPath, \"[^:]+\") do\
1394 if fs.isDir( sPath ) then\
1395 local tList = fs.list( sPath )\
1396 for n,sFile in pairs( tList ) do\
1397 if string.sub( sFile, 1, 1 ) ~= \".\" then\
1398 if not fs.isDir( fs.combine( sPath, sFile ) ) then\
1399 tItems[ sFile ] = true\
1400 end\
1401 end\
1402 end\
1403 end\
1404 end \
1405\
1406 -- Sort and return\
1407 local tItemList = {}\
1408 for sItem, b in pairs( tItems ) do\
1409 table.insert( tItemList, sItem )\
1410 end\
1411 table.sort( tItemList )\
1412 return tItemList\
1413end",},["help"]={["copy"]="cp copies a file or directory from one location to another.\
1414\
1415ex:\
1416\"cp rom myrom\" copies \"rom\" to \"myrom\".\
1417\"cp rom mystuff/rom\" copies \"rom\" to \"mystuff/rom\".",["textutils"]="Functions in the Text Utilities API:\
1418textutils.slowPrint( text )\
1419textutils.tabulate( table, table2, ... )\
1420textutils.pagedTabulate( table, table2, ... )\
1421textutils.formatTime( time, bTwentyFourHour )\
1422textutils.serialize( table )\
1423textutils.unserialize( string )\
1424textutils.urlEncode( string )",["alias"]="alias assigns shell commands to run other programs.\
1425\
1426ex:\
1427\"alias dir ls\" will make the \"dir\" command run the \"ls\" program\
1428\"alias dir\" will remove the alias set on \"dir\"\
1429\"alias\" will list all current aliases.",["drive"]="drive tells you which disk drive the current or specified directory is located in.\
1430\
1431ex:\
1432\"drive\" tell you the disk drive of the current directory.\
1433\"drive foo\" tells you the disk drive of the subdirectory \"foo\"",["refuel"]="refuel is a program for Turtles. Refuel will consume items from the inventory as fuel for turtle.\
1434\
1435ex:\
1436\"refuel\" will refuel with at most one fuel item\
1437\"refuel 10\" will refuel with at most 10 fuel items\
1438\"refuel all\" will refuel with as many fuel items as possible",["helpapi"]="Functions in the help API:\
1439help.setPath( path )\
1440help.lookup( topic )\
1441help.topics()",["rednet"]="The rednet API provides a simple computer networking model using modems.\
1442\
1443Functions in the rednet API:\
1444rednet.open( side )\
1445rednet.close( side )\
1446rednet.isOpen( side )\
1447rednet.send( receiverID, message ) -- Send to a specific computer\
1448rednet.broadcast( message ) -- Send to all computers\
1449rednet.receive( timeout ) -- Returns: senderID, message\
1450\
1451Events fired by the rednet API:\
1452\"rednet_message\" when a message is received. Arguments are senderID, message\
1453Type \"help events\" to learn about the event system.\
1454\
1455Rednet 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 more control.",["peripheral"]="The peripheral API is for interacting with external peripheral devices. Type \"help peripherals\" to learn about the peripherals available.\
1456\
1457Functions in the peripheral API:\
1458peripheral.getNames()\
1459peripheral.isPresent( name )\
1460peripheral.getType( name )\
1461peripheral.getMethods( name )\
1462peripheral.call( name, methodName, param1, param2, etc )\
1463peripheral.wrap( name )\
1464\
1465Events fired by the peripheral API:\
1466\"peripheral\" when a new peripheral is attached. Argument is the side.\
1467\"peripheral_detach\" when a peripheral is removed. Argument is the side.\
1468Type \"help events\" to learn about the event system.",["clear"]="clear clears the screen.",["term"]="Functions in the Terminal API:\
1469term.write( text )\
1470term.clear()\
1471term.clearLine()\
1472term.getCursorPos()\
1473term.setCursorPos( x, y )\
1474term.setCursorBlink( blink )\
1475term.isColor()\
1476term.setTextColor( color )\
1477term.setBackgroundColor( color )\
1478term.getSize()\
1479term.scroll( n )\
1480term.redirect( object )\
1481term.restore()",["turn"]="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.\
1482\
1483ex:\
1484\"turn left\" turns the turtle 90 degrees left.\
1485\"turn right 2\" turns the turtle 180 degrees right.\
1486\"turn left 2 right\" turns left 180 degrees, then right 90 degrees.",["dance"]="dance is a program for Turtles. Turtles love to get funky.",["tunnel"]="tunnel is a program for Mining Turtles. Tunnel will mine a 3x2 tunnel of the depth specified.\
1487\
1488ex:\
1489\"tunnel 20\" will tunnel a tunnel 20 blocks long.",["shell"]="shell is the program which interprets commands and runs program.\
1490Type \"help shellapi\" for information about the shell lua api.",["label"]="label gets or sets the label of the Computer, or of Floppy Disks in attached disk drives.\
1491\
1492ex:\
1493\"label get\" prints the label of the computer.\
1494\"label set My Computer\" set the label of the computer to \"My Computer\".\
1495\"label get left\" prints the label of the disk in the left drive.\
1496\"label set left My Programs\" sets the label of the disk in the left drive to \"My Programs\".\
1497\"label clear left\" clears the label.",["vector"]="Functions in the 3D Vector Math API:\
1498vector.new( x,y,z )\
1499\
1500Vectors returned by vector.new() have the following fields and methods:\
1501vector.x\
1502vector.y\
1503vector.z\
1504vector:add( vector )\
1505vector:sub( vector )\
1506vector:mul( number )\
1507vector:dot( vector )\
1508vector:cross( vector )\
1509vector:length()\
1510vector:normalize()\
1511vector:round()\
1512vector:tostring()\
1513The +, - and * operators can also be used on vectors.",["adventure"]="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\"",["io"]="io is a standard Lua5.1 API, reimplemented for CraftOS. Not all the features are availiable.\
1514Refer to http://www.lua.org/manual/5.1/ for more information.",["printers"]="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\".\
1515\
1516Methods exposed by the Printer:\
1517getInkLevel()\
1518getPaperLevel()\
1519newPage()\
1520setPageTitle( title )\
1521getPageSize()\
1522setCursorPos( x, y )\
1523getCursorPos()\
1524write( text )\
1525endPage()",["disk"]="Functions in the disk API. These functions are for interacting with disk drives:\
1526disk.isPresent( side )\
1527disk.setLabel( side, label )\
1528disk.getLabel( side )\
1529disk.hasData( side )\
1530disk.getMountPath( side )\
1531disk.hasAudio( side )\
1532disk.getAudioTitle( side )\
1533disk.playAudio( side )\
1534disk.stopAudio( )\
1535disk.eject( side )\
1536disk.getID( side )\
1537\
1538Events fired by the disk API:\
1539\"disk\" when a disk or other item is inserted into a disk drive. Argument is the side\
1540\"disk_eject\" when a disk is removed from a disk drive. Argument is the side\
1541Type \"help events\" to learn about the event system.",["keys"]="The keys API contains constants for all the key codes that can be returned by the \"key\" event:\
1542\
1543Example usage:\
1544local sEvent, nKey = os.pullEvent()\
1545if sEvent == \"key\" and nKey == keys.enter then\
1546 -- Do something \
1547end\
1548\
1549See http://www.minecraftwiki.net/wiki/Key_codes, or the source code, for a complete reference.",["go"]="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.\
1550\
1551ex:\
1552\"go forward\" moves the turtle 1 space forward.\
1553\"go forward 3\" moves the turtle 3 spaces forward.\
1554\"go forward 3 up left 2\" moves the turtle 3 spaces forward, 1 spaces up, then left 180 degrees.",["redprobe"]="redprobe lists all the sides of the computer which are being powered by redstone signals.",["shellapi"]="Functions in the Shell API:\
1555shell.exit()\
1556shell.dir()\
1557shell.setDir( path )\
1558shell.path()\
1559shell.setPath( path )\
1560shell.resolve( localpath )\
1561shell.resolveProgram( name )\
1562shell.aliases()\
1563shell.setAlias( alias, command )\
1564shell.clearAlias( alias )\
1565shell.programs()\
1566shell.run( program, arguments )\
1567shell.getRunningProgram()",["earth"]="Mostly harmless.",["programming"]="To learn the lua programming language, visit http://lua-users.org/wiki/TutorialDirectory.\
1568\
1569To experiment with lua in CraftOS, run the \"lua\" program and start typing code.\
1570To 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.\
1571\
1572To terminate a program stuck in a loop, hold Ctrl+T for 1 second.\
1573To quickly shutdown a computer, hold Ctrl+S for 1 second.\
1574To quickly reboot a computer, hold Ctrl+R for 1 second.\
1575\
1576To learn about the programming APIs availiable, type \"apis\" or \"help apis\".\
1577If you get stuck, visit the forums at http://www.computercraft.info/ for advice and tutorials.",["redstone"]="Functions in the Redstone API:\
1578redstone.getSides( )\
1579redstone.getInput( side )\
1580redstone.setOutput( side, boolean )\
1581redstone.getOutput( side )\
1582redstone.getAnalogInput( side )\
1583redstone.setAnalogOutput( side, number )\
1584redstone.getAnalogOutput( side )\
1585\
1586Functions in the Redstone API for working with RedPower bundled cables:\
1587redstone.getBundledInput( side )\
1588redstone.testBundledInput( side, color )\
1589redstone.setBundledOutput( side, colors )\
1590redstone.getBundledOutput( side )\
1591Type \"help redpower\" for usage examples.\
1592\
1593Events emitted by the redstone API:\
1594\"redstone\", when the state of any redstone input changes. Use getInput() or getBundledInput() to inspect the changes\
1595Type \"help events\" to learn about the event system.",["redset"]="redset sets the state of the redstone signal from a specific side of the computer.\
1596\
1597ex:\
1598\"redset left true\" turns on the left redstone output.\
1599\"redset right blue false\" turns off the blue wire in the bundled cable on the right redstone output.\
1600\"redset back 42\" sets the wires in the bundled cable on the back redstone output to the binary value 42.",["licenses"]={["luaj"]="Copyright (c) 2007 LuaJ. All rights reserved.\
1601\
1602Permission is hereby granted, free of charge, to any person obtaining a copy\
1603of this software and associated documentation files (the \"Software\"), to deal\
1604in the Software without restriction, including without limitation the rights\
1605to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\
1606copies of the Software, and to permit persons to whom the Software is\
1607furnished to do so, subject to the following conditions:\
1608\
1609The above copyright notice and this permission notice shall be included in\
1610all copies or substantial portions of the Software.\
1611\
1612THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\
1613IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\
1614FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\
1615AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\
1616LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\
1617OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\
1618THE SOFTWARE.",},["mkdir"]="mkdir creates a directory in the current location.\
1619\
1620ex:\
1621\"mkdir foo\" creates a directory named \"foo\".\
1622\"mkdir ../foo\" creates a directory named \"foo\" in the directory above the current directory.",["apis"]="apis lists the currently loaded APIs available to programs in CraftOS.\
1623\
1624Type \"help <api>\" to see help for a specific api.\
1625Call os.loadAPI( path ) to load extra apis.",["gpsapi"]="Functions in the GPS API:\
1626gps.locate( timeout )\
1627\
1628The 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.",["intro"]="Welcome to CraftOS!\
1629Type \"programs\" to see the programs you can run.\
1630Type \"help <program>\" to see help for a specific program.\
1631Type \"help programming\" to learn about programming.\
1632Type \"help whatsnew\" to find out about new features.\
1633Type \"help credits\" to learn who made all this.\
1634Type \"help index\" to see all help topics.",["programs"]="programs lists all the programs on the rom of the computer.",["help"]="help is the help tool you're currently using.\
1635Type \"help index\" to see all help topics.\
1636Type \"help\" to see the help intro.\
1637Type \"help helpapi\" for information on the help Lua API.",["sleep"]="sleep makes the computer idle for a specific number of seconds.\
1638\
1639ex:\
1640\"sleep 10\" puts the computer to sleep for 10 seconds",["edit"]="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.\
1641\
1642ex:\
1643\"edit hello\" opens a file called \"hello\" for editing.",["redpulse"]="redpulse outputs a pulsing redstone signal from a specific side of the computer.\
1644\
1645ex:\
1646\"redpulse left 5\" sends 5 1-second pulses from the left side of the computer.\
1647\"redpulse right 50 0.1\" sends 50 0.1-second pulses from the right side of the computer.",["colours"]="Functions in the colours api\
1648(used for redstone.setBundledOutput):\
1649colours.combine( colour1, colour2, colour3, ...)\
1650colours.subtract( colours, colour1, colour2, ...)\
1651colours.test( colours, colour )\
1652\
1653Colour constants in the colours api, in ascending bit order:\
1654colours.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.",["type"]="type determines the type of a file or directory. Prints \"file\", \"directory\" or \"does not exist\".",["modems"]="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\".\
1655\
1656Methods exposed by Modems:\
1657open( channel )\
1658isOpen( channel )\
1659close( channel )\
1660closeAll()\
1661transmit( channel, replyChannel, message )\
1662isWireless()\
1663\
1664Events fired by Modems:\
1665\"modem_message\" when a message is received on an open channel. Arguments are side, channel, replyChannel, message, distance",["paint"]="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.\
1666\
1667ex:\
1668\"edit mario\" opens an image called \"mario\" for editing.",["paintutils"]="Functions in the Paint Utilities API:\
1669paintutils.drawPixel( x, y, [color] )\
1670paintutils.drawLine( startX, startY, [color] )\
1671paintutils.loadImage( path )\
1672paintutils.drawImage( image, x, y )",["parallel"]="Functions in the Parallel API:\
1673parallel.waitForAny( function1, function2, ... )\
1674parallel.waitForAll( function1, function2, ... )\
1675These methods provide an easy way to run multiple lua functions simultaneously.",["string"]="string is a standard Lua5.1 API.\
1676Refer to http://www.lua.org/manual/5.1/ for more information.",["colors"]="Functions in the colors api\
1677(used for redstone.setBundledOutput):\
1678colors.combine( color1, color2, color3, ... )\
1679colors.subtract( colors, color1, color2, ... )\
1680colors.test( colors, color )\
1681\
1682Color constants in the colors api, in ascending bit order:\
1683colors.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.",["table"]="table is a standard Lua5.1 API.\
1684Refer to http://www.lua.org/manual/5.1/ for more information.",["list"]="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.",["shutdown"]="shutdown will turn off the computer.",["cd"]="cd changes the the directory you're in.\
1685\
1686ex:\
1687\"cd rom\" will move to \"rom\" folder.\
1688\"cd ..\" will move up one folder.\
1689\"cd /\" will move to the root.",["exit"]="exit will exit the current shell.",["peripherals"]="Peripherals are external devices which CraftOS Computers and Turtles can interact with using the peripheral API.\
1690Type \"help peripheral\" to learn about using the peripheral API.\
1691Type \"help drives\" to learn about using Disk Drives.\
1692Type \"help modems\" to learn about using Wireless Modems.\
1693Type \"help monitors\" to learn about using Monitors.\
1694Type \"help printers\" to learn about using Printers.",["events"]="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.\
1695\
1696Some events which can occur are:\
1697\"char\" when text is typed on the keyboard. Argument is the letter typed.\
1698\"key\" when a key is pressed on the keyboard. Argument is the numerical keycode. Compare to the values in keys API to see which key was pressed.\
1699\
1700Events only on advanced computers:\
1701\"mouse_click\" when a user clicks the mouse. Arguments are button, xPos, yPos.\
1702\"mouse_drag\" when a user moves the mouse when held. Arguments are button, xPos, yPos.\
1703\"mouse_scroll\" when a user uses the scrollwheel on the mouse. Arguments are direction, xPos, yPos.\
1704\
1705Other APIs and peripherals will emit their own events. See their respective help pages for details.",["changelog"]="New Features in ComputerCraft 1.58:\
1706\
1707. Fixed a long standing bug where turtles could lose their identify if they travel too far away\
1708. Fixed use of deprecated code, ensuring mod compatibility with the latest versions of Minecraft Forge, and world compatibility with future versions of Minecraft\
1709\
1710New Features in ComputerCraft 1.57:\
1711\
1712. Ported to Minecraft 1.6.4\
1713. Added two new Treasure Disks: Conway’s Game of Life by vilsol and Protector by fredthead\
1714. Fixed a very nasty item duplication bug\
1715\
1716New Features in ComputerCraft 1.56:\
1717\
1718. Added Treasure Disks: Floppy Disks in dungeons which contain interesting community made programs. Find them all!\
1719. All turtle functions now return additional error messages when they fail.\
1720. Resource Packs with Lua Programs can now be edited when extracted to a folder, for easier editing.\
1721\
1722New Features in ComputerCraft 1.55:\
1723\
1724. Ported to Minecraft 1.6.2\
1725. Added Advanced Turtles\
1726. Added \"turtle_inventory\" event. Fires when any change is made to the inventory of a turtle\
1727. Added missing functions io.close, io.flush, io.input, io.lines, io.output\
1728. Tweaked the screen colours used by Advanced Computers, Monitors and Turtles\
1729. Added new features for Peripheral authors\
1730. Lua programs can now be included in Resource Packs\
1731\
1732New Features in ComputerCraft 1.52:\
1733\
1734. Ported to Minecraft 1.5.1\
1735\
1736New Features in ComputerCraft 1.51:\
1737\
1738. Ported to Minecraft 1.5\
1739. Added Wired Modems\
1740. Added Networking Cables\
1741. Made Wireless Modems more expensive to craft\
1742. New redstone API functions: getAnalogInput(), setAnalogOutput(), getAnalogOutput()\
1743. Peripherals can now be controlled remotely over wired networks. New peripheral API function: getNames()\
1744. New event: \"monitor_resize\" when the size of a monitor changes\
1745. Except for labelled computers and turtles, ComputerCraft blocks no longer drop items in creative mode\
1746. The pick block function works in creative mode now works for all ComputerCraft blocks\
1747. All blocks and items now use the IDs numbers assigned by FTB by default\
1748. Fixed turtles sometimes placing blocks with incorrect orientations\
1749. Fixed Wireless modems being able to send messages to themselves\
1750. Fixed turtle.attack() having a very short range\
1751. Various bugfixes\
1752\
1753New Features in ComputerCraft 1.5:\
1754\
1755. 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\
1756. Floppy Disks can now be dyed with multiple dyes, just like armour\
1757. The \"excavate\" program now retains fuel in it's inventory, so can run unattended\
1758. turtle.place() now tries all possible block orientations before failing\
1759. turtle.refuel(0) returns true if a fuel item is selected\
1760. turtle.craft(0) returns true if the inventory is a valid recipe\
1761. The in-game help system now has documentation for all the peripherals and their methods, including the new modem functionality\
1762. A romantic surprise\
1763\
1764New Features in ComputerCraft 1.48:\
1765\
1766. Ported to Minecraft 1.4.6\
1767. Advanced Monitors now emit a \"monitor_touch\" event when right clicked\
1768. Advanced Monitors are now cheaper to craft\
1769. Turtles now get slightly less fuel from items\
1770. Computers can now interact with Command Blocks (if enabled in ComputerCraft.cfg)\
1771. New API function: os.day()\
1772. A christmas surprise\
1773\
1774New Features in ComputerCraft 1.45:\
1775\
1776. Added Advanced Computers\
1777. Added Advanced Monitors\
1778. New program: paint by nitrogenfingers\
1779. New API: paintutils\
1780. New term functions: term.setBackgroundColor, term.setTextColor, term.isColor\
1781. New turtle function: turtle.transferTo\
1782\
1783New Features in ComputerCraft 1.43:\
1784\
1785. Added Printed Pages\
1786. Added Printed Books\
1787. Fixed incompatibility with Forge 275 and above\
1788. Labelled Turtles now keep their fuel when broken\
1789\
1790New Features in ComputerCraft 1.42:\
1791\
1792. Ported to Minecraft 1.3.2\
1793. Added Printers\
1794. Floppy Disks can be dyed different colours\
1795. Wireless Crafty Turtles can now be crafted\
1796. New textures\
1797. New forge config file\
1798. Bug fixes\
1799\
1800New Features in ComputerCraft 1.4:\
1801\
1802. Ported to Forge Mod Loader. ComputerCraft can now be ran directly from the .zip without extraction\
1803. Added Farming Turtles\
1804. Added Felling Turtles\
1805. Added Digging Turtles\
1806. Added Melee Turtles\
1807. Added Crafty Turtles\
1808. Added 14 new Turtle Combinations accessible by combining the turtle upgrades above\
1809. Labelled computers and turtles can now be crafted into turtles or other turtle types without losing their ID, label and data\
1810. Added a \"Turtle Upgrade API\" for mod developers to create their own tools and peripherals for turtles\
1811. Turtles can now attack entities with turtle.attack(), and collect their dropped items\
1812. Turtles can now use turtle.place() with any item the player can, and can interact with entities\
1813. Turtles can now craft items with turtle.craft()\
1814. Turtles can now place items into inventories with turtle.drop()\
1815. Changed the behaviour of turtle.place() and turtle.drop() to only consider the currently selected slot\
1816. Turtles can now pick up items from the ground, or from inventories, with turtle.suck()\
1817. Turtles can now compare items in their inventories\
1818. Turtles can place signs with text on them with turtle.place( [signText] )\
1819. Turtles now optionally require fuel items to move, and can refuel themselves\
1820. The size of the the turtle inventory has been increased to 16\
1821. The size of the turtle screen has been increased\
1822. New turtle functions: turtle.compareTo( [slotNum] ), turtle.craft(), turtle.attack(), turtle.attackUp(), turtle.attackDown(), turtle.dropUp(), turtle.dropDown(), turtle.getFuelLevel(), turtle.refuel()\
1823. New disk function: disk.getID()\
1824. New turtle programs: craft, refuel\
1825. \"excavate\" program now much smarter: Will return items to a chest when full, attack mobs, and refuel itself automatically\
1826. New API: keys\
1827. Added optional Floppy Disk and Hard Drive space limits for computers and turtles\
1828. New fs function: fs.getFreeSpace( path ), also fs.getDrive() works again\
1829. The send and receive range of wireless modems now increases with altitude, allowing long range networking from high-altitude computers (great for GPS networks)\
1830. http.request() now supports https:// URLs\
1831. Right clicking a Disk Drive with a Floppy Disk or a Record when sneaking will insert the item into the Disk Drive automatically\
1832. The default size of the computer screen has been increased\
1833. 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.\
1834\
1835New Features in ComputerCraft 1.31:\
1836\
1837. Ported to Minecraft 1.2.3\
1838. Added Monitors (thanks to Cloudy)\
1839. Updated LuaJ to a newer, less memory hungry version\
1840. rednet_message event now has a third parameter, \"distance\", to support position triangulation.\
1841. New programs: gps, monitor, pastebin.\
1842. Added a secret program. Use with large monitors!\
1843. New apis: gps, vector\
1844. New turtle functions: turtle.compare(), turtle.compareUp(), turtle.compareDown(), turtle.drop( quantity )\
1845. New http functions: http.post().\
1846. New term functonss: term.redirect(), term.restore()\
1847. New textutils functions: textutils.urlEncode()\
1848. New rednet functions: rednet.isOpen()\
1849. New config options: modem_range, modem_rangeDuringStorm\
1850. Bug fixes, program tweaks, and help updates\
1851\
1852New Features in ComputerCraft 1.3:\
1853\
1854. Ported to Minecraft Forge\
1855. Added Turtles\
1856. Added Wireless Modems\
1857. Added Mining Turtles\
1858. Added Wireless Turtles\
1859. Added Wireless Mining Turtles\
1860. Computers and Disk Drives no longer get destroyed by water.\
1861. Computers and Turtles can now be labelled with the label program, and labelled devices keep their state when destroyed.\
1862. Computers/Turtles can connect to adjacent devices, and turn them on and off\
1863. User programs now give line numbers in their error messages\
1864. New APIs: turtle, peripheral\
1865. New programs for turtles: tunnel, excavate, go, turn, dance\
1866. New os functions: os.getComputerLabel(), os.setComputerLabel()\
1867. Added \"filter\" parameter to os.pullEvent()\
1868. New shell function: shell.getCurrentProgram()\
1869. New textutils functions: textutils.serialize(), textutils.unserialize(), textutils.tabulate(), textutils.pagedTabulate(), textutils.slowWrite()\
1870. New io file function: file:lines()\
1871. New fs function: fs.getSize()\
1872. Disk Drives can now play records from other mods\
1873. Bug fixes, program tweaks, and help updates\
1874\
1875New Features in ComputerCraft 1.2:\
1876\
1877. Added Disk Drives and Floppy Disks\
1878. Added Ctrl+T shortcut to terminate the current program (hold)\
1879. Added Ctrl+S shortcut to shutdown the computer (hold)\
1880. Added Ctrl+R shortcut to reboot the computer (hold)\
1881. New Programs: alias, apis, copy, delete, dj, drive, eject, id, label, list, move, reboot, redset, rename, time, worm.\
1882. New APIs: bit, colours, disk, help, rednet, parallel, textutils.\
1883. New color functions: colors.combine(), colors.subtract(), colors.test()\
1884. New fs functions: fs.getName(), new modes for fs.open()\
1885. New os functions: os.loadAPI(), os.unloadAPI(),\
1886os.clock(), os.time(), os.setAlarm(),\
1887os.reboot(), os.queueEvent()\
1888. New redstone function: redstone.getSides()\
1889. New shell functions: shell.setPath(), shell.programs(), shell.resolveProgram(), shell.setAlias()\
1890. Lots of updates to the help pages\
1891. Bug fixes\
1892\
1893New Features in ComputerCraft 1.1:\
1894\
1895. Added Multiplayer support throughout.\
1896. Added connectivity with RedPower bundled cables\
1897. Added HTTP api, enabled via the mod config, to allow computers to access the real world internet\
1898. Added command history to the shell.\
1899. Programs which spin in an infinite loop without yielding will no longer freeze minecraft\
1900. Help updates and bug fixes\
1901\
1902New Features in ComputerCraft 1.0:\
1903\
1904. First Release!",["monitors"]="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\".\
1905\
1906Methods exposed by the Monitor:\
1907write( text )\
1908clear()\
1909clearLine()\
1910getCursorPos()\
1911setCursorPos( x, y )\
1912setCursorBlink( blink )\
1913isColor()\
1914setTextColor( color )\
1915setBackgroundColor( color )\
1916getSize()\
1917scroll( n )\
1918redirect( object )\
1919restore()\
1920\
1921Events fired by the Monitor:\
1922\"monitor_touch\" when an Advanced Monitor is touched by the player. Arguments are side, x, y\
1923\"monitor_resize\" when the size of a Monitor changes. Arguments is the side.",["credits"]="ComputerCraft was created by Daniel \"dan200\" Ratcliffe (@DanTwoHundred on twitter).\
1924Additional code by Aaron \"Cloudy\" Mills (@Cloudhunter).\
1925Thanks to everyone on the ComputerCraft forums and IRC channel who help with moral support beta testing.\
1926Thanks to nitrogenfingers for the \"paint\" program.\
1927Thanks to deadlystrike for providing hosting for www.computercraft.info.\
1928Thanks to Eloraam for permission to interface with RedPower2.\
1929Thanks to mojang, the Forge team, and the MCP team for Minecraft, Forge and MCP.\
1930Uses LuaJ from http://luaj.sourceforge.net/\
1931\
1932Join the ComputerCraft community online at http://www.computercraft.info and share your creations!",["time"]="time prints the current time of day.",["reboot"]="reboot will turn the computer off and on again.\
1933You can also hold Ctrl+R at any time to quickly reboot.",["http"]="Functions in the HTTP API:\
1934http.request( url, postData* )\
1935http.get( url )\
1936http.post( url, postData )\
1937*optional\
1938\
1939The HTTP API must be enabled in ComputerCraft.cfg before being used.\
1940A 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. http.get() and http.post() block until this event fires.",["id"]="id prints the unique identifier of this computer, or a Disk in an attached Disk Drive.\
1941\
1942ex:\
1943\"id\" will print this Computers ID and label\
1944\"id left\" will print the ID and label of the disk in the Disk Drive on the left",["whatsnew"]="New Features in ComputerCraft 1.58:\
1945\
1946. Fixed a long standing bug where turtles could lose their identify if they travel too far away\
1947. Fixed use of deprecated code, ensuring mod compatibility with the latest versions of Minecraft Forge, and world compatibility with future versions of Minecraft\
1948\
1949Type \"help changelog\" to see the full version history.",["rename"]="mv moves a file or directory from one location to another.\
1950\
1951ex:\
1952\"mv foo bar\" renames the file \"foo\" to \"bar\".\
1953\"mv foo bar/foo\" moves the file \"foo\" to a folder called \"bar\".",["craft"]="craft is a program for Crafty Turtles. Craft will craft a stack of items using the current inventory.\
1954\
1955ex:\
1956\"craft\" will craft as many items as possible\
1957\"craft 5\" will craft at most 5 times",["turtle"]="turtle is an api availiable on Turtles, which controls their movement.\
1958Functions in the Turtle API:\
1959turtle.forward()\
1960turtle.back()\
1961turtle.up()\
1962turtle.down()\
1963turtle.turnLeft()\
1964turtle.turnRight()\
1965turtle.select( slotNum )\
1966turtle.getItemCount( slotNum )\
1967turtle.getItemSpace( slotNum )\
1968turtle.dig()\
1969turtle.digUp()\
1970turtle.digDown()\
1971turtle.place()\
1972turtle.placeUp()\
1973turtle.placeDown()\
1974turtle.attack()\
1975turtle.attackUp()\
1976turtle.attackDown()\
1977turtle.detect()\
1978turtle.detectUp()\
1979turtle.detectDown()\
1980turtle.compare()\
1981turtle.compareUp()\
1982turtle.compareDown()\
1983turtle.compareTo( slotNum )\
1984turtle.transferTo( slotNum, [quantity] )\
1985turtle.drop( [quantity] )\
1986turtle.dropUp( [quantity] )\
1987turtle.dropDown( [quantity] )\
1988turtle.suck()\
1989turtle.suckUp()\
1990turtle.suckDown()\
1991turtle.getFuelLevel()\
1992turtle.refuel( [quantity] )\
1993turtle.craft( [quantity] ) (requires Crafty Turtle)\
1994\
1995Events fired by the Turtle API:\
1996\"turtle_inventory\" when any of the items in the inventory are changed. Use comparison operations to inspect the changes.",["eject"]="eject ejects the contents of an attached disk drive.\
1997\
1998ex:\
1999\"eject left\" ejects the contents of the disk drive to the left of the computer.",["worm"]="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!",["drives"]="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\".\
2000\
2001Methods exposed by the Disk Drive:\
2002isDiskPresent()\
2003getDiskLabel()\
2004setDiskLabel( label )\
2005hasData()\
2006getMountPath()\
2007hasAudio()\
2008getAudioTitle()\
2009playAudio()\
2010stopAudio()\
2011ejectDisk()\
2012getDiskID()\
2013\
2014Events fired by the Disk Drive:\
2015\"disk\" when a disk or other item is inserted into the drive. Argument is the side\
2016\"disk_eject\" when a disk is removed from a drive. Argument is the side\
2017Type \"help events\" to learn about the event system.",["math"]="math is a standard Lua5.1 API.\
2018Refer to http://www.lua.org/manual/5.1/ for more information.",["coroutine"]="coroutine is a standard Lua5.1 API.\
2019Refer to http://www.lua.org/manual/5.1/ for more information.",["move"]="mv moves a file or directory from one location to another.\
2020\
2021ex:\
2022\"mv foo bar\" renames the file \"foo\" to \"bar\".\
2023\"mv foo bar/foo\" moves the file \"foo\" to a folder called \"bar\".",["monitor"]="monitor will connect to an attached Monitor peripheral, and run a program on its display.\
2024\
2025ex:\
2026\"monitor left hello\" will run the \"hello\" program on the monitor to the left of the computer.\
2027\"monitor top edit foo\" will run the edit program on the top monitor, editing the file \"foo\".",["fs"]="Functions in the Filesystem API:\
2028fs.list( path )\
2029fs.exists( path )\
2030fs.isDir( path )\
2031fs.isReadOnly( path )\
2032fs.getName( path )\
2033fs.getSize( path )\
2034fs.getDrive( path )\
2035fs.getFreeSpace( path )\
2036fs.makeDir( path )\
2037fs.move( path, path )\
2038fs.copy( path, path )\
2039fs.delete( path )\
2040fs.combine( path, localpath )\
2041fs.open( path, mode )\
2042Available fs.open() modes are \"r\", \"w\", \"a\", \"rb\", \"wb\" and \"ab\".",["redpower"]="To set bundled outputs:\
2043c = colors.combine( colors.red, colors.blue )\
2044rs.setBundledOutput( \"left\", c )\
2045\
2046c = colors.combine( c, colors.green )\
2047rs.setBundledOutput( \"left\", c )\
2048\
2049c = colors.subtract( c, colors.blue )\
2050rs.setBundledOutput( \"left\", c )\
2051\
2052To read bundled inputs:\
2053c = rs.getBundledInput( \"right\" )\
2054red = colors.test( c, colors.red )\
2055\
2056Type \"help colors\" for the list of wire colors.",["pastebin"]="pastebin is a program for uploading files to and downloading files from pastebin.com. This is useful for sharing programs with other players.\
2057The HTTP API must be enabled in ComputerCraft.cfg to use this program.\
2058\
2059ex:\
2060\"pastebin put foo\" will upload the file \"foo\" to pastebin.com, and print the URL.\
2061\"pastebin get xq5gc7LB foo\" will download the file from the URL http://pastebin.com/xq5gc7LB, and save it as \"foo\".\
2062\"pastebin run CxaWmPrX\" will download the file from the URL http://pastebin.com/CxaWmPrX, and immediately run it.",["dj"]="dj plays Music Discs from disk drives attached to the computer.\
2063\
2064ex:\
2065\"dj\" or \"dj play\" plays a random disc.\
2066\"dj play left\" plays the disc in the drive on the left of the computer.\
2067\"dj stop\" stops the current disc.",["os"]="Functions in the os (Operating System) API:\
2068os.version()\
2069os.getComputerID()\
2070os.getComputerLabel()\
2071os.setComputerLabel()\
2072os.run( environment, programpath, arguments )\
2073os.loadAPI( path )\
2074os.unloadAPI( name )\
2075os.pullEvent( [filter] )\
2076os.queueEvent( event, arguments )\
2077os.clock()\
2078os.startTimer( timeout )\
2079os.sleep( timeout )\
2080os.time()\
2081os.day()\
2082os.setAlarm( time )\
2083os.shutdown()\
2084os.reboot()\
2085\
2086Events emitted by the os API:\
2087\"timer\" when a timeout started by os.startTimer() completes. Argument is the value returned by startTimer().\
2088\"alarm\" when a time passed to os.setAlarm() is reached. Argument is the value returned by setAlarm().\
2089Type \"help events\" to learn about the event system.",["delete"]="rm deletes a file or a directory and its contents.\
2090\
2091ex:\
2092\"rm foo\" will delete the file foo.",["hello"]="hello prints the text \"Hello World!\" to the screen.",["lua"]="lua is an interactive prompt for the lua programming language. It's a useful tool for learning the language.",["excavate"]="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.\
2093\
2094ex:\
2095\"excavate 3\" will mine a 3x3 shaft.",["rs"]="Functions in the Redstone API:\
2096rs.getSides( )\
2097rs.getInput( side )\
2098rs.setOutput( side, boolean )\
2099rs.getOutput( side )\
2100rs.getAnalogInput( side )\
2101rs.setAnalogOutput( side, number )\
2102rs.getAnalogOutput( side )\
2103\
2104Functions in the Redstone API for working with RedPower bundled cables:\
2105rs.getBundledInput( side )\
2106rs.testBundledInput( side, color )\
2107rs.setBundledOutput( side, colors )\
2108rs.getBundledOutput( side )\
2109Type \"help redpower\" for usage examples.\
2110\
2111Events emitted by the redstone API:\
2112\"redstone\", when the state of any redstone input changes. Use getInput() or getBundledInput() to inspect the changes\
2113Type \"help events\" to learn about the event system.",["bit"]="Functions in the bit manipulation API:\
2114bit.bnot(n) -- bitwise not (~n)\
2115bit.band(m, n) -- bitwise and (m & n)\
2116bit.bor(m, n) -- bitwise or (m | n)\
2117bit.bxor(m, n) -- bitwise xor (m ^ n)\
2118bit.brshift(n, bits) -- right shift (n >> bits)\
2119bit.blshift(n, bits) -- left shift (n << bits)",["gps"]="gps can be used to host a GPS server over rednet, or determine a position using trilateration.\
2120Type \"help gpsapi\" for help using GPS functions in lua programs.\
2121\
2122ex:\
2123\"gps locate\" will connect to nearby GPS servers, and try to determine the position of the computer or turtle.\
2124\"gps host\" will try to detemine the position, and host a GPS server if successful.\
2125\"gps host 10 20 30\" will host a GPS server, using the manually entered position 10,20,30. \
2126\
2127Take care when manually entering host positions. If the positions entered into multiple GPS host\
2128are not consisent, the results of locate calls will be incorrect.",},["programs"]={["programs"]="\
2129local bAll = false\
2130local tArgs = { ... }\
2131if #tArgs > 0 and tArgs[1] == \"all\" then\
2132 bAll = true\
2133end\
2134\
2135local tPrograms = shell.programs( bAll )\
2136textutils.pagedTabulate( tPrograms )",["move"]="\
2137local tArgs = { ... }\
2138if #tArgs < 2 then\
2139 print( \"Usage: mv <source> <destination>\" )\
2140 return\
2141end\
2142\
2143local sSource = shell.resolve( tArgs[1] )\
2144local sDest = shell.resolve( tArgs[2] )\
2145if fs.exists( sDest ) and fs.isDir( sDest ) then\
2146 sDest = fs.combine( sDest, fs.getName(sSource) )\
2147end\
2148fs.move( sSource, sDest )",["delete"]="\
2149local tArgs = { ... }\
2150if #tArgs < 1 then\
2151 print( \"Usage: rm <path>\" )\
2152 return\
2153end\
2154\
2155local sNewPath = shell.resolve( tArgs[1] )\
2156fs.delete( sNewPath )",["lua"]="\
2157local tArgs = { ... }\
2158if #tArgs > 0 then\
2159 print( \"This is an interactive Lua prompt.\" )\
2160 print( \"To run a lua program, just type its name.\" )\
2161 return\
2162end\
2163\
2164local bRunning = true\
2165local tCommandHistory = {}\
2166local tEnv = {\
2167 [\"exit\"] = function()\
2168 bRunning = false\
2169 end,\
2170}\
2171setmetatable( tEnv, { __index = getfenv() } )\
2172\
2173if term.isColour() then\
2174 term.setTextColour( colours.yellow )\
2175end\
2176print( \"Interactive Lua prompt.\" )\
2177print( \"Call exit() to exit.\" )\
2178term.setTextColour( colours.white )\
2179\
2180while bRunning do\
2181 --if term.isColour() then\
2182 -- term.setTextColour( colours.yellow )\
2183 --end\
2184 write( \"lua> \" )\
2185 --term.setTextColour( colours.white )\
2186 \
2187 local s = read( nil, tCommandHistory )\
2188 table.insert( tCommandHistory, s )\
2189 \
2190 local nForcePrint = 0\
2191 local func, e = loadstring( s, \"lua\" )\
2192 local func2, e2 = loadstring( \"return \"..s, \"lua\" )\
2193 if not func then\
2194 if func2 then\
2195 func = func2\
2196 e = nil\
2197 nForcePrint = 1\
2198 end\
2199 else\
2200 if func2 then\
2201 func = func2\
2202 end\
2203 end\
2204 \
2205 if func then\
2206 setfenv( func, tEnv )\
2207 local tResults = { pcall( function() return func() end ) }\
2208 if tResults[1] then\
2209 local n = 1\
2210 while (tResults[n + 1] ~= nil) or (n <= nForcePrint) do\
2211 print( tostring( tResults[n + 1] ) )\
2212 n = n + 1\
2213 end\
2214 else\
2215 printError( tResults[2] )\
2216 end\
2217 else\
2218 printError( e )\
2219 end\
2220 \
2221end",["edit"]="-- Get file to edit\
2222local tArgs = { ... }\
2223if #tArgs == 0 then\
2224 print( \"Usage: edit <path>\" )\
2225 return\
2226end\
2227\
2228-- Error checking\
2229local sPath = shell.resolve( tArgs[1] )\
2230local bReadOnly = fs.isReadOnly( sPath )\
2231if fs.exists( sPath ) and fs.isDir( sPath ) then\
2232 print( \"Cannot edit a directory.\" )\
2233 return\
2234end\
2235\
2236local x,y = 1,1\
2237local w,h = term.getSize()\
2238local scrollX, scrollY = 0,0\
2239\
2240local tLines = {}\
2241local bRunning = true\
2242\
2243-- Colours\
2244local highlightColour, keywordColour, commentColour, textColour, bgColour\
2245if term.isColour() then\
2246 bgColour = colours.black\
2247 textColour = colours.white\
2248 highlightColour = colours.yellow\
2249 keywordColour = colours.yellow\
2250 commentColour = colours.green\
2251 stringColour = colours.red\
2252else\
2253 bgColour = colours.black\
2254 textColour = colours.white\
2255 highlightColour = colours.white\
2256 keywordColour = colours.white\
2257 commentColour = colours.white\
2258 stringColour = colours.white\
2259end\
2260\
2261-- Menus\
2262local bMenu = false\
2263local nMenuItem = 1\
2264\
2265local tMenuItems\
2266if bReadOnly then\
2267 tMenuItems = { \"Exit\", \"Print\" }\
2268else\
2269 tMenuItems = { \"Save\", \"Exit\", \"Print\" }\
2270end\
2271 \
2272local sStatus = \"Press Ctrl to access menu\"\
2273\
2274local function load( _sPath )\
2275 tLines = {}\
2276 if fs.exists( _sPath ) then\
2277 local file = io.open( _sPath, \"r\" )\
2278 local sLine = file:read()\
2279 while sLine do\
2280 table.insert( tLines, sLine )\
2281 sLine = file:read()\
2282 end\
2283 file:close()\
2284 end\
2285 \
2286 if #tLines == 0 then\
2287 table.insert( tLines, \"\" )\
2288 end\
2289end\
2290\
2291local function save( _sPath )\
2292 -- Create intervening folder\
2293 local sDir = sPath:sub(1, sPath:len() - fs.getName(sPath):len() )\
2294 if not fs.exists( sDir ) then\
2295 fs.makeDir( sDir )\
2296 end\
2297\
2298 -- Save\
2299 local file = nil\
2300 local function innerSave()\
2301 file = fs.open( _sPath, \"w\" )\
2302 if file then\
2303 for n, sLine in ipairs( tLines ) do\
2304 file.write( sLine .. \"\\n\" )\
2305 end\
2306 else\
2307 error( \"Failed to open \".._sPath )\
2308 end\
2309 end\
2310 \
2311 local ok = pcall( innerSave )\
2312 if file then \
2313 file.close()\
2314 end\
2315 return ok\
2316end\
2317\
2318local tKeywords = {\
2319 [\"and\"] = true,\
2320 [\"break\"] = true,\
2321 [\"do\"] = true,\
2322 [\"else\"] = true,\
2323 [\"elseif\"] = true,\
2324 [\"end\"] = true,\
2325 [\"false\"] = true,\
2326 [\"for\"] = true,\
2327 [\"function\"] = true,\
2328 [\"if\"] = true,\
2329 [\"in\"] = true,\
2330 [\"local\"] = true,\
2331 [\"nil\"] = true,\
2332 [\"not\"] = true,\
2333 [\"or\"] = true,\
2334 [\"repeat\"] = true,\
2335 [\"return\"] = true,\
2336 [\"then\"] = true,\
2337 [\"true\"] = true,\
2338 [\"until\"]= true,\
2339 [\"while\"] = true,\
2340}\
2341\
2342local function tryWrite( sLine, regex, colour )\
2343 local match = string.match( sLine, regex )\
2344 if match then\
2345 if type(colour) == \"number\" then\
2346 term.setTextColour( colour )\
2347 else\
2348 term.setTextColour( colour(match) )\
2349 end\
2350 term.write( match )\
2351 term.setTextColour( textColour )\
2352 return string.sub( sLine, string.len(match) + 1 )\
2353 end\
2354 return nil\
2355end\
2356\
2357local function writeHighlighted( sLine )\
2358 while string.len(sLine) > 0 do \
2359 sLine = \
2360 tryWrite( sLine, \"^%-%-%[%[.-%]%]\", commentColour ) or\
2361 tryWrite( sLine, \"^%-%-.*\", commentColour ) or\
2362 tryWrite( sLine, \"^\\\".-[^\\\\]\\\"\", stringColour ) or\
2363 tryWrite( sLine, \"^\\'.-[^\\\\]\\'\", stringColour ) or\
2364 tryWrite( sLine, \"^%[%[.-%]%]\", stringColour ) or\
2365 tryWrite( sLine, \"^[%w_]+\", function( match )\
2366 if tKeywords[ match ] then\
2367 return keywordColour\
2368 end\
2369 return textColour\
2370 end ) or\
2371 tryWrite( sLine, \"^[^%w_]\", textColour )\
2372 end\
2373end\
2374\
2375local function redrawText()\
2376 for y=1,h-1 do\
2377 term.setCursorPos( 1 - scrollX, y )\
2378 term.clearLine()\
2379\
2380 local sLine = tLines[ y + scrollY ]\
2381 if sLine ~= nil then\
2382 writeHighlighted( sLine )\
2383 end\
2384 end\
2385 term.setCursorPos( x - scrollX, y - scrollY )\
2386end\
2387\
2388local function redrawLine(_nY)\
2389 local sLine = tLines[_nY]\
2390 term.setCursorPos( 1 - scrollX, _nY - scrollY )\
2391 term.clearLine()\
2392 writeHighlighted( sLine )\
2393 term.setCursorPos( x - scrollX, _nY - scrollY )\
2394end\
2395\
2396local function redrawMenu()\
2397 term.setCursorPos( 1, h )\
2398 term.clearLine()\
2399\
2400 local sLeft, sRight\
2401 local nLeftColour, nLeftHighlight1, nLeftHighlight2\
2402 if bMenu then\
2403 local sMenu = \"\"\
2404 for n,sItem in ipairs( tMenuItems ) do\
2405 if n == nMenuItem then\
2406 nLeftHighlight1 = sMenu:len() + 1\
2407 nLeftHighlight2 = sMenu:len() + sItem:len() + 2\
2408 end\
2409 sMenu = sMenu..\" \"..sItem..\" \"\
2410 end\
2411 sLeft = sMenu\
2412 nLeftColour = textColour\
2413 else\
2414 sLeft = sStatus\
2415 nLeftColour = highlightColour\
2416 end\
2417 \
2418 -- Left goes last so that it can overwrite the line numbers.\
2419 sRight = \"Ln \"..y\
2420 term.setTextColour( highlightColour )\
2421 term.setCursorPos( w-sRight:len() + 1, h )\
2422 term.write(sRight)\
2423\
2424 sRight = tostring(y)\
2425 term.setTextColour( textColour )\
2426 term.setCursorPos( w-sRight:len() + 1, h )\
2427 term.write(sRight)\
2428\
2429 if sLeft then\
2430 term.setCursorPos( 1, h )\
2431 term.setTextColour( nLeftColour )\
2432 term.write(sLeft) \
2433 if nLeftHighlight1 then\
2434 term.setTextColour( highlightColour )\
2435 term.setCursorPos( nLeftHighlight1, h )\
2436 term.write( \"[\" )\
2437 term.setCursorPos( nLeftHighlight2, h )\
2438 term.write( \"]\" )\
2439 end\
2440 term.setTextColour( textColour )\
2441 end\
2442 \
2443 -- Cursor highlights selection\
2444 term.setCursorPos( x - scrollX, y - scrollY )\
2445end\
2446\
2447local tMenuFuncs = { \
2448 Save=function()\
2449 if bReadOnly then\
2450 sStatus = \"Access denied\"\
2451 else\
2452 local ok, err = save( sPath )\
2453 if ok then\
2454 sStatus=\"Saved to \"..sPath\
2455 else\
2456 sStatus=\"Error saving to \"..sPath\
2457 end\
2458 end\
2459 redrawMenu()\
2460 end,\
2461 Print=function()\
2462 local sPrinterSide = nil\
2463 for n,sName in ipairs(peripheral.getNames()) do\
2464 if peripheral.isPresent(sName) and peripheral.getType(sName) == \"printer\" then\
2465 sPrinterSide = sName\
2466 break\
2467 end\
2468 end\
2469 \
2470 if not sPrinterSide then\
2471 sStatus = \"No printer attached\"\
2472 return\
2473 end\
2474\
2475 local nPage = 0\
2476 local sName = fs.getName( sPath )\
2477 local printer = peripheral.wrap(sPrinterSide)\
2478 if printer.getInkLevel() < 1 then\
2479 sStatus = \"Printer out of ink\"\
2480 return\
2481 elseif printer.getPaperLevel() < 1 then\
2482 sStatus = \"Printer out of paper\"\
2483 return\
2484 end\
2485 \
2486 local terminal = {\
2487 getCursorPos = printer.getCursorPos,\
2488 setCursorPos = printer.setCursorPos,\
2489 getSize = printer.getPageSize,\
2490 write = printer.write,\
2491 }\
2492 terminal.scroll = function()\
2493 if nPage == 1 then\
2494 printer.setPageTitle( sName..\" (page \"..nPage..\")\" ) \
2495 end\
2496 \
2497 while not printer.newPage() do\
2498 if printer.getInkLevel() < 1 then\
2499 sStatus = \"Printer out of ink, please refill\"\
2500 elseif printer.getPaperLevel() < 1 then\
2501 sStatus = \"Printer out of paper, please refill\"\
2502 else\
2503 sStatus = \"Printer output tray full, please empty\"\
2504 end\
2505 \
2506 term.restore()\
2507 redrawMenu()\
2508 term.redirect( terminal )\
2509 \
2510 local timer = os.startTimer(0.5)\
2511 sleep(0.5)\
2512 end\
2513\
2514 nPage = nPage + 1\
2515 if nPage == 1 then\
2516 printer.setPageTitle( sName )\
2517 else\
2518 printer.setPageTitle( sName..\" (page \"..nPage..\")\" )\
2519 end\
2520 end\
2521 \
2522 bMenu = false\
2523 term.redirect( terminal )\
2524 local ok, error = pcall( function()\
2525 term.scroll()\
2526 for n, sLine in ipairs( tLines ) do\
2527 print( sLine )\
2528 end\
2529 end )\
2530 term.restore()\
2531 if not ok then\
2532 print( error )\
2533 end\
2534 \
2535 while not printer.endPage() do\
2536 sStatus = \"Printer output tray full, please empty\"\
2537 redrawMenu()\
2538 sleep( 0.5 )\
2539 end\
2540 bMenu = true\
2541 \
2542 if nPage > 1 then\
2543 sStatus = \"Printed \"..nPage..\" Pages\"\
2544 else\
2545 sStatus = \"Printed 1 Page\"\
2546 end\
2547 redrawMenu()\
2548 end,\
2549 Exit=function()\
2550 bRunning = false\
2551 end\
2552}\
2553\
2554local function doMenuItem( _n )\
2555 tMenuFuncs[tMenuItems[_n]]()\
2556 if bMenu then\
2557 bMenu = false\
2558 term.setCursorBlink( true )\
2559 end\
2560 redrawMenu()\
2561end\
2562\
2563local function setCursor( x, y )\
2564 local screenX = x - scrollX\
2565 local screenY = y - scrollY\
2566 \
2567 local bRedraw = false\
2568 if screenX < 1 then\
2569 scrollX = x - 1\
2570 screenX = 1\
2571 bRedraw = true\
2572 elseif screenX > w then\
2573 scrollX = x - w\
2574 screenX = w\
2575 bRedraw = true\
2576 end\
2577 \
2578 if screenY < 1 then\
2579 scrollY = y - 1\
2580 screenY = 1\
2581 bRedraw = true\
2582 elseif screenY > h-1 then\
2583 scrollY = y - (h-1)\
2584 screenY = h-1\
2585 bRedraw = true\
2586 end\
2587 \
2588 if bRedraw then\
2589 redrawText()\
2590 end\
2591 term.setCursorPos( screenX, screenY )\
2592 \
2593 -- Statusbar now pertains to menu, it would probably be safe to redraw the menu on every key event.\
2594 redrawMenu()\
2595end\
2596\
2597-- Actual program functionality begins\
2598load(sPath)\
2599\
2600term.setBackgroundColour( bgColour )\
2601term.clear()\
2602term.setCursorPos(x,y)\
2603term.setCursorBlink( true )\
2604\
2605redrawText()\
2606redrawMenu()\
2607\
2608-- Handle input\
2609while bRunning do\
2610 local sEvent, param, param2, param3 = os.pullEvent()\
2611 if sEvent == \"key\" then\
2612 if param == keys.up then\
2613 -- Up\
2614 if not bMenu then\
2615 if y > 1 then\
2616 -- Move cursor up\
2617 y = y - 1\
2618 x = math.min( x, string.len( tLines[y] ) + 1 )\
2619 setCursor( x, y )\
2620 end\
2621 end\
2622 elseif param == keys.down then\
2623 -- Down\
2624 if not bMenu then\
2625 -- Move cursor down\
2626 if y < #tLines then\
2627 y = y + 1\
2628 x = math.min( x, string.len( tLines[y] ) + 1 )\
2629 setCursor( x, y )\
2630 end\
2631 end\
2632 elseif param == keys.tab then\
2633 -- Tab\
2634 if not bMenu and not bReadOnly then\
2635 -- Indent line\
2636 tLines[y]=\" \"..tLines[y]\
2637 x = x + 2\
2638 setCursor( x, y )\
2639 redrawLine(y)\
2640 end\
2641 elseif param == keys.pageUp then\
2642 -- Page Up\
2643 if not bMenu then\
2644 -- Move up a page\
2645 local sx,sy=term.getSize()\
2646 y=y-sy-1\
2647 if y<1 then y=1 end\
2648 x = math.min( x, string.len( tLines[y] ) + 1 )\
2649 setCursor( x, y )\
2650 end\
2651 elseif param == keys.pageDown then\
2652 -- Page Down\
2653 if not bMenu then\
2654 -- Move down a page\
2655 local sx,sy=term.getSize()\
2656 if y<#tLines-sy-1 then\
2657 y = y+sy-1\
2658 else\
2659 y = #tLines\
2660 end\
2661 x = math.min( x, string.len( tLines[y] ) + 1 )\
2662 setCursor( x, y )\
2663 end\
2664 elseif param == keys.home then\
2665 -- Home\
2666 if not bMenu then\
2667 -- Move cursor to the beginning\
2668 x=1\
2669 setCursor(x,y)\
2670 end\
2671 elseif param == keys[\"end\"] then\
2672 -- End\
2673 if not bMenu then\
2674 -- Move cursor to the end\
2675 x = string.len( tLines[y] ) + 1\
2676 setCursor(x,y)\
2677 end\
2678 elseif param == keys.left then\
2679 -- Left\
2680 if not bMenu then\
2681 if x > 1 then\
2682 -- Move cursor left\
2683 x = x - 1\
2684 elseif x==1 and y>1 then\
2685 x = string.len( tLines[y-1] ) + 1\
2686 y = y - 1\
2687 end\
2688 setCursor( x, y )\
2689 else\
2690 -- Move menu left\
2691 nMenuItem = nMenuItem - 1\
2692 if nMenuItem < 1 then\
2693 nMenuItem = #tMenuItems\
2694 end\
2695 redrawMenu()\
2696 end\
2697 elseif param == keys.right then\
2698 -- Right\
2699 if not bMenu then\
2700 if x < string.len( tLines[y] ) + 1 then\
2701 -- Move cursor right\
2702 x = x + 1\
2703 elseif x==string.len( tLines[y] ) + 1 and y<#tLines then\
2704 x = 1\
2705 y = y + 1\
2706 end\
2707 setCursor( x, y )\
2708 else\
2709 -- Move menu right\
2710 nMenuItem = nMenuItem + 1\
2711 if nMenuItem > #tMenuItems then\
2712 nMenuItem = 1\
2713 end\
2714 redrawMenu()\
2715 end\
2716 elseif param == keys.delete then\
2717 -- Delete\
2718 if not bMenu and not bReadOnly then\
2719 if x < string.len( tLines[y] ) + 1 then\
2720 local sLine = tLines[y]\
2721 tLines[y] = string.sub(sLine,1,x-1) .. string.sub(sLine,x+1)\
2722 redrawLine(y)\
2723 elseif y<#tLines then\
2724 tLines[y] = tLines[y] .. tLines[y+1]\
2725 table.remove( tLines, y+1 )\
2726 redrawText()\
2727 redrawMenu()\
2728 end\
2729 end\
2730 elseif param == keys.backspace then\
2731 -- Backspace\
2732 if not bMenu and not bReadOnly then\
2733 if x > 1 then\
2734 -- Remove character\
2735 local sLine = tLines[y]\
2736 tLines[y] = string.sub(sLine,1,x-2) .. string.sub(sLine,x)\
2737 redrawLine(y)\
2738 \
2739 x = x - 1\
2740 setCursor( x, y )\
2741 elseif y > 1 then\
2742 -- Remove newline\
2743 local sPrevLen = string.len( tLines[y-1] )\
2744 tLines[y-1] = tLines[y-1] .. tLines[y]\
2745 table.remove( tLines, y )\
2746 redrawText()\
2747 \
2748 x = sPrevLen + 1\
2749 y = y - 1\
2750 setCursor( x, y )\
2751 end\
2752 end\
2753 elseif param == keys.enter then\
2754 -- Enter\
2755 if not bMenu and not bReadOnly then\
2756 -- Newline\
2757 local sLine = tLines[y]\
2758 local _,spaces=string.find(sLine,\"^[ ]+\")\
2759 if not spaces then\
2760 spaces=0\
2761 end\
2762 tLines[y] = string.sub(sLine,1,x-1)\
2763 table.insert( tLines, y+1, string.rep(' ',spaces)..string.sub(sLine,x) )\
2764 redrawText()\
2765 \
2766 x = spaces+1\
2767 y = y + 1\
2768 setCursor( x, y )\
2769 elseif bMenu then\
2770 -- Menu selection\
2771 doMenuItem( nMenuItem )\
2772 end\
2773 elseif param == keys.leftCtrl or param == keys.rightCtrl then\
2774 -- Menu toggle\
2775 bMenu = not bMenu\
2776 if bMenu then\
2777 term.setCursorBlink( false )\
2778 nMenuItem = 1\
2779 else\
2780 term.setCursorBlink( true )\
2781 end\
2782 redrawMenu()\
2783 end\
2784 \
2785 elseif sEvent == \"char\" then\
2786 if not bMenu and not bReadOnly then\
2787 -- Input text\
2788 local sLine = tLines[y]\
2789 tLines[y] = string.sub(sLine,1,x-1) .. param .. string.sub(sLine,x)\
2790 redrawLine(y)\
2791 \
2792 x = x + string.len( param )\
2793 setCursor( x, y )\
2794 elseif bMenu then\
2795 -- Select menu items\
2796 for n,sMenuItem in ipairs( tMenuItems ) do\
2797 if string.lower(string.sub(sMenuItem,1,1)) == string.lower(param) then\
2798 doMenuItem( n )\
2799 break\
2800 end\
2801 end\
2802 end\
2803 \
2804 elseif sEvent == \"mouse_click\" then\
2805 if not bMenu then\
2806 if param == 1 then\
2807 -- Left click\
2808 local cx,cy = param2, param3\
2809 if cy < h then\
2810 y = math.min( math.max( scrollY + cy, 1 ), #tLines )\
2811 x = math.min( math.max( scrollX + cx, 1 ), string.len( tLines[y] ) + 1 )\
2812 setCursor( x, y )\
2813 end\
2814 end\
2815 end\
2816 \
2817 elseif sEvent == \"mouse_scroll\" then\
2818 if not bMenu then\
2819 if param == -1 then\
2820 -- Scroll up\
2821 if scrollY > 0 then\
2822 -- Move cursor up\
2823 scrollY = scrollY - 1\
2824 redrawText()\
2825 end\
2826 \
2827 elseif param == 1 then\
2828 -- Scroll down\
2829 local nMaxScroll = #tLines - (h-1)\
2830 if scrollY < nMaxScroll then\
2831 -- Move cursor down\
2832 scrollY = scrollY + 1\
2833 redrawText()\
2834 end\
2835 \
2836 end\
2837 end\
2838 end\
2839end\
2840\
2841-- Cleanup\
2842term.clear()\
2843term.setCursorBlink( false )\
2844term.setCursorPos( 1, 1 )",["alias"]="\
2845local tArgs = { ... }\
2846if #tArgs > 2 then\
2847 print( \"Usage: alias <alias> <program>\" )\
2848 return\
2849end\
2850\
2851local sAlias = tArgs[1]\
2852local sProgram = tArgs[2]\
2853\
2854if sAlias and sProgram then\
2855 -- Set alias\
2856 shell.setAlias( sAlias, sProgram )\
2857elseif sAlias then\
2858 -- Clear alias\
2859 shell.clearAlias( sAlias )\
2860else\
2861 -- List aliases\
2862 local tAliases = shell.aliases()\
2863 local tList = {}\
2864 for sAlias, sCommand in pairs( tAliases ) do\
2865 table.insert( tList, sAlias )\
2866 end\
2867 table.sort( tList )\
2868 textutils.pagedTabulate( tList )\
2869end\
2870 ",["computer"]={["hello"]="if term.isColour() then\
2871 term.setTextColour( 2^math.random(0,15) )\
2872end\
2873textutils.slowPrint( \"Hello World!\" )\
2874term.setTextColour( colours.white )",["worm"]="\
2875-- Display the start screen\
2876local w,h = term.getSize()\
2877\
2878local headingColour, textColour, wormColour, fruitColour\
2879if term.isColour() then\
2880 headingColour = colours.yellow\
2881 textColour = colours.white\
2882 wormColour = colours.green\
2883 fruitColour = colours.red\
2884else\
2885 headingColour = colours.white\
2886 textColour = colours.white\
2887 wormColour = colours.white\
2888 fruitColour = colours.white\
2889end\
2890\
2891function printCentred( y, s )\
2892 local x = math.floor((w - string.len(s)) / 2)\
2893 term.setCursorPos(x,y)\
2894 --term.clearLine()\
2895 term.write( s )\
2896end\
2897\
2898local xVel,yVel = 1,0\
2899local xPos, yPos = math.floor(w/2), math.floor(h/2)\
2900local pxVel, pyVel = nil, nil\
2901\
2902local nLength = 1\
2903local nExtraLength = 6\
2904local bRunning = true\
2905\
2906local tailX,tailY = xPos,yPos\
2907local nScore = 0\
2908local nDifficulty = 2\
2909local nSpeed, nInterval\
2910\
2911-- Setup the screen\
2912local screen = {}\
2913for x=1,w do\
2914 screen[x] = {}\
2915 for y=1,h do\
2916 screen[x][y] = {}\
2917 end\
2918end\
2919screen[xPos][yPos] = { snake = true }\
2920\
2921local nFruit = 1\
2922local tFruits = {\
2923 \"A\", \"B\", \"C\", \"D\", \"E\", \"F\", \"G\", \"H\",\
2924 \"I\", \"J\", \"K\", \"L\", \"M\", \"N\", \"O\", \"P\",\
2925 \"Q\", \"R\", \"S\", \"T\", \"U\", \"V\", \"W\", \"X\",\
2926 \"Y\", \"Z\",\
2927 \"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"h\",\
2928 \"i\", \"j\", \"k\", \"l\", \"m\", \"n\", \"o\", \"p\",\
2929 \"q\", \"r\", \"s\", \"t\", \"u\", \"v\", \"w\", \"x\",\
2930 \"y\", \"z\",\
2931 \"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\", \"9\", \"0\",\
2932 \"@\", \"$\", \"%\", \"#\", \"&\", \"!\", \"?\", \"+\", \"*\", \"~\"\
2933}\
2934\
2935local function addFruit()\
2936 while true do\
2937 local x = math.random(1,w)\
2938 local y = math.random(2,h)\
2939 local fruit = screen[x][y]\
2940 if fruit.snake == nil and fruit.wall == nil and fruit.fruit == nil then\
2941 screen[x][y] = { fruit = true }\
2942 term.setCursorPos(x,y)\
2943 term.setBackgroundColour( fruitColour )\
2944 term.write(\" \")\
2945 term.setBackgroundColour( colours.black )\
2946 break\
2947 end\
2948 end\
2949 \
2950 nFruit = nFruit + 1\
2951 if nFruit > #tFruits then\
2952 nFruit = 1\
2953 end\
2954end\
2955\
2956local function drawMenu()\
2957 term.setTextColour( headingColour )\
2958 term.setCursorPos(1,1)\
2959 term.write( \"SCORE \" )\
2960 \
2961 term.setTextColour( textColour )\
2962 term.setCursorPos(7,1)\
2963 term.write( tostring(nScore) )\
2964\
2965 term.setTextColour( headingColour )\
2966 term.setCursorPos(w-11,1)\
2967 term.write( \"DIFFICULTY \")\
2968\
2969 term.setTextColour( textColour )\
2970 term.setCursorPos(w,1)\
2971 term.write( tostring(nDifficulty or \"?\") ) \
2972\
2973 term.setTextColour( colours.white )\
2974end\
2975\
2976local function update( )\
2977 local x,y = xPos,yPos\
2978 if pxVel and pyVel then\
2979 xVel, yVel = pxVel, pyVel\
2980 pxVel, pyVel = nil, nil\
2981 end\
2982\
2983 -- Remove the tail\
2984 if nExtraLength == 0 then\
2985 local tail = screen[tailX][tailY]\
2986 screen[tailX][tailY] = {}\
2987 term.setCursorPos(tailX,tailY)\
2988 term.write(\" \")\
2989 tailX = tail.nextX\
2990 tailY = tail.nextY\
2991 else\
2992 nExtraLength = nExtraLength - 1\
2993 end\
2994 \
2995 -- Update the head\
2996 local head = screen[xPos][yPos]\
2997 local newXPos = xPos + xVel\
2998 local newYPos = yPos + yVel\
2999 if newXPos < 1 then\
3000 newXPos = w\
3001 elseif newXPos > w then\
3002 newXPos = 1\
3003 end\
3004 if newYPos < 2 then\
3005 newYPos = h\
3006 elseif newYPos > h then\
3007 newYPos = 2\
3008 end\
3009 \
3010 local newHead = screen[newXPos][newYPos]\
3011 term.setCursorPos(1,1);\
3012 print( newHead.snake )\
3013 if newHead.snake == true or newHead.wall == true then\
3014 bRunning = false\
3015 \
3016 else\
3017 if newHead.fruit == true then\
3018 nScore = nScore + 10\
3019 nExtraLength = nExtraLength + 1\
3020 addFruit()\
3021 end\
3022 xPos = newXPos\
3023 yPos = newYPos\
3024 head.nextX = newXPos\
3025 head.nextY = newYPos\
3026 screen[newXPos][newYPos] = { snake = true }\
3027 \
3028 end\
3029 \
3030 term.setCursorPos(xPos,yPos)\
3031 term.setBackgroundColour( wormColour )\
3032 term.write(\" \")\
3033 term.setBackgroundColour( colours.black )\
3034\
3035 drawMenu()\
3036end\
3037\
3038-- Display the frontend\
3039term.clear()\
3040local function drawFrontend()\
3041 term.setTextColour( headingColour )\
3042 printCentred( math.floor(h/2) - 3, \"\" )\
3043 printCentred( math.floor(h/2) - 2, \" SELECT DIFFICULTY \" )\
3044 printCentred( math.floor(h/2) - 1, \"\" )\
3045 \
3046 printCentred( math.floor(h/2) + 0, \" \" )\
3047 printCentred( math.floor(h/2) + 1, \" \" )\
3048 printCentred( math.floor(h/2) + 2, \" \" )\
3049 printCentred( math.floor(h/2) - 1 + nDifficulty, \" [ ] \" )\
3050\
3051 term.setTextColour( textColour )\
3052 printCentred( math.floor(h/2) + 0, \"EASY\" )\
3053 printCentred( math.floor(h/2) + 1, \"MEDIUM\" )\
3054 printCentred( math.floor(h/2) + 2, \"HARD\" )\
3055 printCentred( math.floor(h/2) + 3, \"\" )\
3056\
3057 term.setTextColour( colours.white )\
3058end\
3059\
3060drawMenu()\
3061drawFrontend()\
3062while true do\
3063 local e,key = os.pullEvent( \"key\" )\
3064 if key == keys.up or key == keys.w then\
3065 -- Up\
3066 if nDifficulty > 1 then\
3067 nDifficulty = nDifficulty - 1\
3068 drawMenu()\
3069 drawFrontend()\
3070 end\
3071 elseif key == keys.down or key == keys.s then\
3072 -- Down\
3073 if nDifficulty < 3 then\
3074 nDifficulty = nDifficulty + 1\
3075 drawMenu()\
3076 drawFrontend()\
3077 end\
3078 elseif key == keys.enter then\
3079 -- Enter\
3080 break\
3081 end\
3082end\
3083\
3084local tSpeeds = { 5, 10, 25 }\
3085nSpeed = tSpeeds[nDifficulty]\
3086nInterval = 1 / nSpeed\
3087\
3088-- Grow the snake to its intended size\
3089term.clear()\
3090drawMenu()\
3091screen[tailX][tailY].snake = true\
3092while nExtraLength > 0 do\
3093 update()\
3094end\
3095addFruit()\
3096addFruit()\
3097\
3098-- Play the game\
3099local timer = os.startTimer(0)\
3100while bRunning do\
3101 local event, p1, p2 = os.pullEvent()\
3102 if event == \"timer\" and p1 == timer then\
3103 timer = os.startTimer(nInterval)\
3104 update( false )\
3105 \
3106 elseif event == \"key\" then\
3107 local key = p1\
3108 if key == keys.up or key == keys.w then\
3109 -- Up\
3110 if yVel == 0 then\
3111 pxVel,pyVel = 0,-1\
3112 end\
3113 elseif key == keys.down or key == keys.s then\
3114 -- Down\
3115 if yVel == 0 then\
3116 pxVel,pyVel = 0,1\
3117 end\
3118 elseif key == keys.left or key == keys.a then\
3119 -- Left\
3120 if xVel == 0 then\
3121 pxVel,pyVel = -1,0\
3122 end\
3123 \
3124 elseif key == keys.right or key == keys.d then\
3125 -- Right\
3126 if xVel == 0 then\
3127 pxVel,pyVel = 1,0\
3128 end\
3129 \
3130 end \
3131 end\
3132end\
3133\
3134-- Display the gameover screen\
3135term.setTextColour( headingColour )\
3136printCentred( math.floor(h/2) - 2, \" \" )\
3137printCentred( math.floor(h/2) - 1, \" G A M E O V E R \" )\
3138\
3139term.setTextColour( textColour )\
3140printCentred( math.floor(h/2) + 0, \" \" )\
3141printCentred( math.floor(h/2) + 1, \" FINAL SCORE \"..nScore..\" \" )\
3142printCentred( math.floor(h/2) + 2, \" \" )\
3143term.setTextColour( colours.white )\
3144\
3145local timer = os.startTimer(2.5)\
3146repeat\
3147 local e,p = os.pullEvent()\
3148 if e == \"timer\" and p == timer then\
3149 term.setTextColour( textColour )\
3150 printCentred( math.floor(h/2) + 2, \" PRESS ANY KEY \" )\
3151 printCentred( math.floor(h/2) + 3, \" \" )\
3152 term.setTextColour( colours.white )\
3153 end\
3154until e == \"char\"\
3155\
3156term.clear()\
3157term.setCursorPos(1,1)\
3158\
3159 ",["adventure"]="\
3160local tBiomes = {\
3161 \"in a forest\",\
3162 \"in a pine forest\",\
3163 \"knee deep in a swamp\",\
3164 \
3165 \"in a mountain range\",\
3166 \"in a desert\",\
3167 \"in a grassy plain\",\
3168 \"in frozen tundra\",\
3169 \
3170 --\"in the ocean\",\
3171}\
3172\
3173local function hasTrees( _nBiome )\
3174 return _nBiome <= 3\
3175end\
3176\
3177local function hasStone( _nBiome )\
3178 return _nBiome == 4\
3179end\
3180\
3181local function hasRivers( _nBiome )\
3182 return _nBiome ~= 3 and _nBiome ~= 5\
3183end\
3184\
3185local items = {\
3186 [\"no tea\"] = {\
3187 droppable = false,\
3188 desc = \"Pull yourself together man.\",\
3189 },\
3190 [\"a pig\"] = {\
3191 heavy = true,\
3192 creature = true,\
3193 drops = { \"some pork\" },\
3194 aliases = { \"pig\" },\
3195 desc = \"The pig has a square nose.\",\
3196 },\
3197 [\"a cow\"] = {\
3198 heavy = true,\
3199 creature = true,\
3200 aliases = { \"cow\" },\
3201 desc = \"The cow stares at you blankly.\",\
3202 },\
3203 [\"a sheep\"] = {\
3204 heavy = true,\
3205 creature = true,\
3206 hitDrops = { \"some wool\" },\
3207 aliases = { \"sheep\" },\
3208 desc = \"The sheep is fluffy.\",\
3209 },\
3210 [\"a chicken\"] = {\
3211 heavy = true,\
3212 creature = true,\
3213 drops = { \"some chicken\" },\
3214 aliases = { \"chicken\" },\
3215 desc = \"The chicken looks delicious.\",\
3216 },\
3217 [\"a creeper\"] = {\
3218 heavy = true,\
3219 creature = true,\
3220 monster = true,\
3221 aliases = { \"creeper\" },\
3222 desc = \"The creeper needs a hug.\",\
3223 },\
3224 [\"a skeleton\"] = {\
3225 heavy = true,\
3226 creature = true,\
3227 monster = true,\
3228 aliases = { \"skeleton\" },\
3229 nocturnal = true,\
3230 desc = \"The head bone's connected to the neck bone, the neck bones connected to the chest bone, the chest bones connected to the arm bone, the arm bones connected to the bow, and the bow is pointed at you.\",\
3231 },\
3232 [\"a zombie\"] = {\
3233 heavy = true,\
3234 creature = true,\
3235 monster = true,\
3236 aliases = { \"zombie\" },\
3237 nocturnal = true,\
3238 desc = \"All he wants to do is eat your brains.\",\
3239 },\
3240 [\"a spider\"] = {\
3241 heavy = true,\
3242 creature = true,\
3243 monster = true,\
3244 aliases = { \"spider\" },\
3245 desc = \"Dozens of eyes stare back at you.\",\
3246 },\
3247 [\"a cave entrance\"] = {\
3248 heavy = true,\
3249 aliases = { \"cave entance\", \"cave\", \"entrance\" },\
3250 desc = \"The entrance to the cave is dark, but it looks like you can climb down.\",\
3251 },\
3252 [\"an exit to the surface\"] = {\
3253 heavy = true,\
3254 aliases = { \"exit to the surface\", \"exit\", \"opening\" },\
3255 desc = \"You can just see the sky through the opening.\",\
3256 },\
3257 [\"a river\"] = {\
3258 heavy = true,\
3259 aliases = { \"river\" },\
3260 desc = \"The river flows majestically towards the horizon.\",\
3261 },\
3262 [\"some wood\"] = {\
3263 aliases = { \"wood\" },\
3264 material = true,\
3265 desc = \"You could easilly craft this wood into planks.\",\
3266 },\
3267 [\"some planks\"] = {\
3268 aliases = { \"planks\", \"wooden planks\", \"wood planks\" },\
3269 desc = \"You could easilly craft these planks into sticks.\",\
3270 },\
3271 [\"some sticks\"] = {\
3272 aliases = { \"sticks\", \"wooden sticks\", \"wood sticks\" },\
3273 desc = \"A perfect handle for torches or a pickaxe.\",\
3274 },\
3275 [\"a crafting table\"] = {\
3276 aliases = { \"crafting table\", \"craft table\", \"work bench\", \"workbench\", \"crafting bench\", \"table\", },\
3277 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.\",\
3278 },\
3279 [\"a furnace\"] = {\
3280 aliases = { \"furnace\" },\
3281 desc = \"It's a furnace. Between you and me, these don't actually do anything in this game.\",\
3282 },\
3283 [\"a wooden pickaxe\"] = {\
3284 aliases = { \"pickaxe\", \"pick\", \"wooden pick\", \"wooden pickaxe\", \"wood pick\", \"wood pickaxe\" },\
3285 tool = true,\
3286 toolLevel = 1,\
3287 toolType = \"pick\",\
3288 desc = \"The pickaxe looks good for breaking stone and coal.\",\
3289 },\
3290 [\"a stone pickaxe\"] = {\
3291 aliases = { \"pickaxe\", \"pick\", \"stone pick\", \"stone pickaxe\" },\
3292 tool = true,\
3293 toolLevel = 2,\
3294 toolType = \"pick\",\
3295 desc = \"The pickaxe looks good for breaking iron.\",\
3296 },\
3297 [\"an iron pickaxe\"] = {\
3298 aliases = { \"pickaxe\", \"pick\", \"iron pick\", \"iron pickaxe\" },\
3299 tool = true,\
3300 toolLevel = 3,\
3301 toolType = \"pick\",\
3302 desc = \"The pickaxe looks strong enough to break diamond.\",\
3303 },\
3304 [\"a diamond pickaxe\"] = {\
3305 aliases = { \"pickaxe\", \"pick\", \"diamond pick\", \"diamond pickaxe\" },\
3306 tool = true,\
3307 toolLevel = 4,\
3308 toolType = \"pick\",\
3309 desc = \"Best. Pickaxe. Ever.\",\
3310 },\
3311 [\"a wooden sword\"] = {\
3312 aliases = { \"sword\", \"wooden sword\", \"wood sword\" },\
3313 tool = true,\
3314 toolLevel = 1,\
3315 toolType = \"sword\",\
3316 desc = \"Flimsy, but better than nothing.\",\
3317 },\
3318 [\"a stone sword\"] = {\
3319 aliases = { \"sword\", \"stone sword\" },\
3320 tool = true,\
3321 toolLevel = 2,\
3322 toolType = \"sword\",\
3323 desc = \"A pretty good sword.\",\
3324 },\
3325 [\"an iron sword\"] = {\
3326 aliases = { \"sword\", \"iron sword\" },\
3327 tool = true,\
3328 toolLevel = 3,\
3329 toolType = \"sword\",\
3330 desc = \"This sword can slay any enemy.\",\
3331 },\
3332 [\"a diamond sword\"] = {\
3333 aliases = { \"sword\", \"diamond sword\" },\
3334 tool = true,\
3335 toolLevel = 4,\
3336 toolType = \"sword\",\
3337 desc = \"Best. Sword. Ever.\",\
3338 },\
3339 [\"a wooden shovel\"] = {\
3340 aliases = { \"shovel\", \"wooden shovel\", \"wood shovel\" },\
3341 tool = true,\
3342 toolLevel = 1,\
3343 toolType = \"shovel\",\
3344 desc = \"Good for digging holes.\",\
3345 },\
3346 [\"a stone shovel\"] = {\
3347 aliases = { \"shovel\", \"stone shovel\" },\
3348 tool = true,\
3349 toolLevel = 2,\
3350 toolType = \"shovel\",\
3351 desc = \"Good for digging holes.\",\
3352 },\
3353 [\"an iron shovel\"] = {\
3354 aliases = { \"shovel\", \"iron shovel\" },\
3355 tool = true,\
3356 toolLevel = 3,\
3357 toolType = \"shovel\",\
3358 desc = \"Good for digging holes.\",\
3359 },\
3360 [\"a diamond shovel\"] = {\
3361 aliases = { \"shovel\", \"diamond shovel\" },\
3362 tool = true,\
3363 toolLevel = 4,\
3364 toolType = \"shovel\",\
3365 desc = \"Good for digging holes.\",\
3366 },\
3367 [\"some coal\"] = {\
3368 aliases = { \"coal\" },\
3369 ore = true,\
3370 toolLevel = 1,\
3371 toolType = \"pick\",\
3372 desc = \"That coal looks useful for building torches, if only you had a pickaxe to mine it.\",\
3373 },\
3374 [\"some dirt\"] = {\
3375 aliases = { \"dirt\" },\
3376 material = true,\
3377 desc = \"Why not build a mudhut?\",\
3378 },\
3379 [\"some stone\"] = {\
3380 aliases = { \"stone\", \"cobblestone\" },\
3381 material = true,\
3382 ore = true,\
3383 infinite = true,\
3384 toolLevel = 1,\
3385 toolType = \"pick\",\
3386 desc = \"Stone is useful for building things, and making stone pickaxes.\",\
3387 },\
3388 [\"some iron\"] = {\
3389 aliases = { \"iron\" },\
3390 material = true,\
3391 ore = true,\
3392 toolLevel = 2,\
3393 toolType = \"pick\",\
3394 desc = \"That iron looks mighty strong, you'll need a stone pickaxe to mine it.\",\
3395 },\
3396 [\"some diamond\"] = {\
3397 aliases = { \"diamond\", \"diamonds\" },\
3398 material = true,\
3399 ore = true,\
3400 toolLevel = 3,\
3401 toolType = \"pick\",\
3402 desc = \"Sparkly, rare, and impossible to mine without an iron pickaxe.\",\
3403 },\
3404 [\"some torches\"] = {\
3405 aliases = { \"torches\", \"torch\" },\
3406 desc = \"These won't run out for a while.\",\
3407 },\
3408 [\"a torch\"] = {\
3409 aliases = { \"torch\" },\
3410 desc = \"Fire, fire, burn so bright, won't you light my cave tonight?\",\
3411 },\
3412 [\"some wool\"] = {\
3413 aliases = { \"wool\" },\
3414 material = true,\
3415 desc = \"Soft and good for building.\",\
3416 },\
3417 [\"some pork\"] = {\
3418 aliases = { \"pork\", \"porkchops\" },\
3419 food = true,\
3420 desc = \"Delicious and nutricious.\",\
3421 },\
3422 [\"some chicken\"] = {\
3423 aliases = { \"chicken\" },\
3424 food = true,\
3425 desc = \"Finger licking good.\",\
3426 },\
3427}\
3428\
3429local tAnimals = {\
3430 \"a pig\", \"a cow\", \"a sheep\", \"a chicken\",\
3431}\
3432\
3433local tMonsters = {\
3434 \"a creeper\", \"a skeleton\", \"a zombie\", \"a spider\"\
3435}\
3436\
3437local tRecipes = {\
3438 [\"some planks\"] = { \"some wood\" },\
3439 [\"some sticks\"] = { \"some planks\" },\
3440 [\"some sticks\"] = { \"some planks\" },\
3441 [\"a crafting table\"] = { \"some planks\" },\
3442 [\"a furnace\"] = { \"some stone\" },\
3443 [\"some torches\"] = { \"some sticks\", \"some coal\" },\
3444 \
3445 [\"a wooden pickaxe\"] = { \"some planks\", \"some sticks\" },\
3446 [\"a stone pickaxe\"] = { \"some stone\", \"some sticks\" },\
3447 [\"an iron pickaxe\"] = { \"some iron\", \"some sticks\" },\
3448 [\"a diamond pickaxe\"] = { \"some diamond\", \"some sticks\" },\
3449\
3450 [\"a wooden sword\"] = { \"some planks\", \"some sticks\" },\
3451 [\"a stone sword\"] = { \"some stone\", \"some sticks\" },\
3452 [\"an iron sword\"] = { \"some iron\", \"some sticks\" },\
3453 [\"a diamond sword\"] = { \"some diamond\", \"some sticks\" },\
3454\
3455 [\"a wooden shovel\"] = { \"some planks\", \"some sticks\" },\
3456 [\"a stone shovel\"] = { \"some stone\", \"some sticks\" },\
3457 [\"an iron shovel\"] = { \"some iron\", \"some sticks\" },\
3458 [\"a diamond shovel\"] = { \"some diamond\", \"some sticks\" },\
3459}\
3460\
3461local tGoWest = {\
3462 \"(life is peaceful there)\",\
3463 \"(lots of open air)\",\
3464 \"(to begin life anew)\",\
3465 \"(this is what we'll do)\",\
3466 \"(sun in winter time)\",\
3467 \"(we will do just fine)\",\
3468 \"(where the skies are blue)\",\
3469 \"(this and more we'll do)\",\
3470}\
3471local nGoWest = 0\
3472\
3473local bRunning = true\
3474local tMap = { { {}, }, }\
3475local x,y,z = 0,0,0\
3476local inventory = {\
3477 [\"no tea\"] = items[\"no tea\"],\
3478}\
3479\
3480local nTurn = 0\
3481local nTimeInRoom = 0\
3482local bInjured = false\
3483\
3484local tDayCycle = {\
3485 \"It is daytime.\",\
3486 \"It is daytime.\",\
3487 \"It is daytime.\",\
3488 \"It is daytime.\",\
3489 \"It is daytime.\",\
3490 \"It is daytime.\",\
3491 \"It is daytime.\",\
3492 \"It is daytime.\",\
3493 \"The sun is setting.\",\
3494 \"It is night.\",\
3495 \"It is night.\",\
3496 \"It is night.\",\
3497 \"It is night.\",\
3498 \"It is night.\",\
3499 \"The sun is rising.\",\
3500}\
3501\
3502local function getTimeOfDay()\
3503 return math.fmod( math.floor(nTurn/3), #tDayCycle ) + 1\
3504end\
3505\
3506local function isSunny()\
3507 return (getTimeOfDay() < 10)\
3508end\
3509\
3510local function getRoom( x, y, z, dontCreate )\
3511 tMap[x] = tMap[x] or {}\
3512 tMap[x][y] = tMap[x][y] or {}\
3513 if not tMap[x][y][z] and dontCreate ~= true then\
3514 local room = {\
3515 items = {},\
3516 exits = {},\
3517 nMonsters = 0,\
3518 }\
3519 tMap[x][y][z] = room\
3520 \
3521 if y == 0 then\
3522 -- Room is above ground\
3523\
3524 -- Pick biome\
3525 room.nBiome = math.random( 1, #tBiomes )\
3526 room.trees = hasTrees( room.nBiome )\
3527 \
3528 -- Add animals\
3529 if math.random(1,3) == 1 then\
3530 for n = 1,math.random(1,2) do\
3531 local sAnimal = tAnimals[ math.random( 1, #tAnimals ) ]\
3532 room.items[ sAnimal ] = items[ sAnimal ]\
3533 end\
3534 end\
3535 \
3536 -- Add surface ore\
3537 if math.random(1,5) == 1 or hasStone( room.nBiome ) then\
3538 room.items[ \"some stone\" ] = items[ \"some stone\" ]\
3539 end\
3540 if math.random(1,8) == 1 then\
3541 room.items[ \"some coal\" ] = items[ \"some coal\" ]\
3542 end\
3543 if math.random(1,8) == 1 and hasRivers( room.nBiome ) then\
3544 room.items[ \"a river\" ] = items[ \"a river\" ]\
3545 end\
3546 \
3547 -- Add exits\
3548 room.exits = {\
3549 [\"north\"] = true,\
3550 [\"south\"] = true,\
3551 [\"east\"] = true,\
3552 [\"west\"] = true,\
3553 }\
3554 if math.random(1,8) == 1 then\
3555 room.exits[\"down\"] = true\
3556 room.items[\"a cave entrance\"] = items[\"a cave entrance\"]\
3557 end\
3558 \
3559 else\
3560 -- Room is underground\
3561 -- Add exits\
3562 local function tryExit( sDir, sOpp, x, y, z )\
3563 local adj = getRoom( x, y, z, true )\
3564 if adj then\
3565 if adj.exits[sOpp] then\
3566 room.exits[sDir] = true\
3567 end\
3568 else\
3569 if math.random(1,3) == 1 then\
3570 room.exits[sDir] = true\
3571 end\
3572 end\
3573 end\
3574 \
3575 if y == -1 then\
3576 local above = getRoom( x, y + 1, z )\
3577 if above.exits[\"down\"] then\
3578 room.exits[\"up\"] = true\
3579 room.items[\"an exit to the surface\"] = items[\"an exit to the surface\"]\
3580 end\
3581 else\
3582 tryExit( \"up\", \"down\", x, y + 1, z )\
3583 end\
3584 \
3585 if y > -3 then\
3586 tryExit( \"down\", \"up\", x, y - 1, z )\
3587 end\
3588 \
3589 tryExit( \"east\", \"west\", x - 1, y, z )\
3590 tryExit( \"west\", \"east\", x + 1, y, z )\
3591 tryExit( \"north\", \"south\", x, y, z + 1 )\
3592 tryExit( \"south\", \"north\", x, y, z - 1 ) \
3593 \
3594 -- Add ores\
3595 room.items[ \"some stone\" ] = items[ \"some stone\" ]\
3596 if math.random(1,3) == 1 then\
3597 room.items[ \"some coal\" ] = items[ \"some coal\" ]\
3598 end\
3599 if math.random(1,8) == 1 then\
3600 room.items[ \"some iron\" ] = items[ \"some iron\" ]\
3601 end\
3602 if y == -3 and math.random(1,15) == 1 then\
3603 room.items[ \"some diamond\" ] = items[ \"some diamond\" ]\
3604 end\
3605 \
3606 -- Turn out the lights\
3607 room.dark = true\
3608 end\
3609 end\
3610 return tMap[x][y][z]\
3611end\
3612\
3613local function itemize( t )\
3614 local item = next( t )\
3615 if item == nil then\
3616 return \"nothing\"\
3617 end\
3618 \
3619 local text = \"\"\
3620 while item do\
3621 text = text .. item\
3622 \
3623 local nextItem = next( t, item )\
3624 if nextItem ~= nil then\
3625 local nextNextItem = next( t, nextItem )\
3626 if nextNextItem == nil then\
3627 text = text .. \" and \"\
3628 else\
3629 text = text .. \", \"\
3630 end\
3631 end\
3632 item = nextItem\
3633 end\
3634 return text\
3635end\
3636\
3637function findItem( _tList, _sQuery )\
3638 for sItem, tItem in pairs( _tList ) do\
3639 if sItem == _sQuery then\
3640 return sItem\
3641 end\
3642 if tItem.aliases ~= nil then\
3643 for n, sAlias in pairs( tItem.aliases ) do\
3644 if sAlias == _sQuery then\
3645 return sItem\
3646 end\
3647 end\
3648 end\
3649 end\
3650 return nil\
3651end\
3652\
3653local tMatches = {\
3654 [\"wait\"] = {\
3655 \"wait\",\
3656 },\
3657 [\"look\"] = {\
3658 \"look at the ([%a ]+)\",\
3659 \"look at ([%a ]+)\",\
3660 \"look\",\
3661 \"inspect ([%a ]+)\",\
3662 \"inspect the ([%a ]+)\",\
3663 \"inspect\",\
3664 },\
3665 [\"inventory\"] = {\
3666 \"check self\",\
3667 \"check inventory\",\
3668 \"inventory\",\
3669 \"i\",\
3670 },\
3671 [\"go\"] = {\
3672 \"go (%a+)\",\
3673 \"travel (%a+)\",\
3674 \"walk (%a+)\",\
3675 \"run (%a+)\",\
3676 \"go\",\
3677 },\
3678 [\"dig\"] = {\
3679 \"dig (%a+) using ([%a ]+)\",\
3680 \"dig (%a+) with ([%a ]+)\",\
3681 \"dig (%a+)\",\
3682 \"dig\",\
3683 },\
3684 [\"take\"] = {\
3685 \"pick up the ([%a ]+)\",\
3686 \"pick up ([%a ]+)\",\
3687 \"pickup ([%a ]+)\",\
3688 \"take the ([%a ]+)\",\
3689 \"take ([%a ]+)\",\
3690 \"take\",\
3691 },\
3692 [\"drop\"] = {\
3693 \"put down the ([%a ]+)\",\
3694 \"put down ([%a ]+)\",\
3695 \"drop the ([%a ]+)\",\
3696 \"drop ([%a ]+)\",\
3697 \"drop\",\
3698 },\
3699 [\"place\"] = {\
3700 \"place the ([%a ]+)\",\
3701 \"place ([%a ]+)\",\
3702 \"place\",\
3703 },\
3704 [\"cbreak\"] = {\
3705 \"punch the ([%a ]+)\",\
3706 \"punch ([%a ]+)\",\
3707 \"punch\",\
3708 \"break the ([%a ]+) with the ([%a ]+)\",\
3709 \"break ([%a ]+) with ([%a ]+) \",\
3710 \"break the ([%a ]+)\",\
3711 \"break ([%a ]+)\",\
3712 \"break\",\
3713 },\
3714 [\"mine\"] = {\
3715 \"mine the ([%a ]+) with the ([%a ]+)\",\
3716 \"mine ([%a ]+) with ([%a ]+)\",\
3717 \"mine ([%a ]+)\",\
3718 \"mine\",\
3719 },\
3720 [\"attack\"] = {\
3721 \"attack the ([%a ]+) with the ([%a ]+)\",\
3722 \"attack ([%a ]+) with ([%a ]+)\",\
3723 \"attack ([%a ]+)\",\
3724 \"attack\",\
3725 \"kill the ([%a ]+) with the ([%a ]+)\",\
3726 \"kill ([%a ]+) with ([%a ]+)\",\
3727 \"kill ([%a ]+)\",\
3728 \"kill\",\
3729 \"hit the ([%a ]+) with the ([%a ]+)\",\
3730 \"hit ([%a ]+) with ([%a ]+)\",\
3731 \"hit ([%a ]+)\",\
3732 \"hit\",\
3733 },\
3734 [\"craft\"] = {\
3735 \"craft a ([%a ]+)\",\
3736 \"craft some ([%a ]+)\",\
3737 \"craft ([%a ]+)\",\
3738 \"craft\",\
3739 \"make a ([%a ]+)\",\
3740 \"make some ([%a ]+)\",\
3741 \"make ([%a ]+)\",\
3742 \"make\",\
3743 },\
3744 [\"build\"] = {\
3745 \"build ([%a ]+) out of ([%a ]+)\",\
3746 \"build ([%a ]+) from ([%a ]+)\",\
3747 \"build ([%a ]+)\",\
3748 \"build\",\
3749 },\
3750 [\"eat\"] = {\
3751 \"eat a ([%a ]+)\",\
3752 \"eat the ([%a ]+)\",\
3753 \"eat ([%a ]+)\",\
3754 \"eat\",\
3755 },\
3756 [\"help\"] = {\
3757 \"help me\",\
3758 \"help\",\
3759 },\
3760 [\"exit\"] = {\
3761 \"exit\",\
3762 \"quit\",\
3763 \"goodbye\",\
3764 \"good bye\",\
3765 \"bye\",\
3766 \"farewell\",\
3767 },\
3768}\
3769\
3770local commands = {}\
3771function doCommand( text )\
3772 if text == \"\" then\
3773 commands[ \"noinput\" ]()\
3774 return\
3775 end\
3776 \
3777 for sCommand, t in pairs( tMatches ) do\
3778 for n, sMatch in pairs( t ) do\
3779 local tCaptures = { string.match( text, \"^\" .. sMatch .. \"$\" ) }\
3780 if #tCaptures ~= 0 then\
3781 local fnCommand = commands[ sCommand ]\
3782 if #tCaptures == 1 and tCaptures[1] == sMatch then\
3783 fnCommand()\
3784 else\
3785 fnCommand( unpack( tCaptures ) )\
3786 end\
3787 return\
3788 end\
3789 end\
3790 end\
3791 commands[ \"badinput\" ]()\
3792end\
3793\
3794function commands.wait()\
3795 print( \"Time passes...\" )\
3796end\
3797\
3798function commands.look( _sTarget )\
3799 local room = getRoom( x,y,z )\
3800 if room.dark then\
3801 print( \"It is pitch dark.\" )\
3802 return\
3803 end\
3804\
3805 if _sTarget == nil then\
3806 -- Look at the world\
3807 if y == 0 then\
3808 io.write( \"You are standing \" .. tBiomes[room.nBiome] .. \". \" )\
3809 print( tDayCycle[ getTimeOfDay() ] )\
3810 else\
3811 io.write( \"You are underground. \" )\
3812 if next( room.exits ) ~= nil then\
3813 print( \"You can travel \"..itemize( room.exits )..\".\" )\
3814 else\
3815 print()\
3816 end\
3817 end\
3818 if next( room.items ) ~= nil then\
3819 print( \"There is \" .. itemize( room.items ) .. \" here.\" )\
3820 end\
3821 if room.trees then\
3822 print( \"There are trees here.\" )\
3823 end\
3824 \
3825 else\
3826 -- Look at stuff\
3827 if room.trees and (_sTarget == \"tree\" or _sTarget == \"trees\") then\
3828 print( \"The trees look easy to break.\" )\
3829 elseif _sTarget == \"self\" or _sTarget == \"myself\" then\
3830 print( \"Very handsome.\" )\
3831 else\
3832 local tItem = nil\
3833 local sItem = findItem( room.items, _sTarget )\
3834 if sItem then\
3835 tItem = room.items[sItem]\
3836 else\
3837 sItem = findItem( inventory, _sTarget )\
3838 if sItem then\
3839 tItem = inventory[sItem]\
3840 end\
3841 end\
3842 \
3843 if tItem then\
3844 print( tItem.desc or (\"You see nothing special about \"..sItem..\".\") )\
3845 else\
3846 print( \"You don't see any \".._sTarget..\" here.\" )\
3847 end\
3848 end\
3849 end\
3850end\
3851\
3852function commands.go( _sDir )\
3853 local room = getRoom( x,y,z )\
3854 if _sDir == nil then\
3855 print( \"Go where?\" )\
3856 return\
3857 end\
3858 \
3859 if nGoWest ~= nil then\
3860 if _sDir == \"west\" then\
3861 nGoWest = nGoWest + 1\
3862 if nGoWest > #tGoWest then\
3863 nGoWest = 1\
3864 end\
3865 print( tGoWest[ nGoWest ] )\
3866 else\
3867 if nGoWest > 0 or nTurn > 6 then\
3868 nGoWest = nil\
3869 end\
3870 end\
3871 end\
3872 \
3873 if room.exits[_sDir] == nil then\
3874 print( \"You can't go that way.\" )\
3875 return\
3876 end\
3877 \
3878 if _sDir == \"north\" then\
3879 z = z + 1\
3880 elseif _sDir == \"south\" then\
3881 z = z - 1\
3882 elseif _sDir == \"east\" then\
3883 x = x - 1\
3884 elseif _sDir == \"west\" then\
3885 x = x + 1\
3886 elseif _sDir == \"up\" then\
3887 y = y + 1\
3888 elseif _sDir == \"down\" then\
3889 y = y - 1\
3890 else\
3891 print( \"I don't understand that direction.\" )\
3892 return\
3893 end\
3894 \
3895 nTimeInRoom = 0\
3896 doCommand( \"look\" )\
3897end\
3898\
3899function commands.dig( _sDir, _sTool )\
3900 local room = getRoom( x,y,z )\
3901 if _sDir == nil then\
3902 print( \"Dig where?\" )\
3903 return\
3904 end\
3905 \
3906 local sTool = nil\
3907 local tTool = nil\
3908 if _sTool ~= nil then\
3909 sTool = findItem( inventory, _sTool )\
3910 if not sTool then\
3911 print( \"You're not carrying a \".._sTool..\".\" )\
3912 return\
3913 end\
3914 tTool = inventory[ sTool ]\
3915 end\
3916 \
3917 local room = getRoom( x, y, z )\
3918 local bActuallyDigging = (room.exits[ _sDir ] ~= true)\
3919 if bActuallyDigging then\
3920 if sTool == nil or tTool.toolType ~= \"pick\" then\
3921 print( \"You need to use a pickaxe to dig through stone.\" )\
3922 return\
3923 end\
3924 end\
3925 \
3926 if _sDir == \"north\" then\
3927 room.exits[\"north\"] = true\
3928 z = z + 1\
3929 getRoom( x, y, z ).exits[\"south\"] = true\
3930\
3931 elseif _sDir == \"south\" then\
3932 room.exits[\"south\"] = true\
3933 z = z - 1\
3934 getRoom( x, y, z ).exits[\"north\"] = true\
3935 \
3936 elseif _sDir == \"east\" then\
3937 room.exits[\"east\"] = true\
3938 x = x - 1\
3939 getRoom( x, y, z ).exits[\"west\"] = true\
3940 \
3941 elseif _sDir == \"west\" then\
3942 room.exits[\"west\"] = true\
3943 x = x + 1\
3944 getRoom( x, y, z ).exits[\"east\"] = true\
3945 \
3946 elseif _sDir == \"up\" then\
3947 if y == 0 then\
3948 print( \"You can't dig that way.\" )\
3949 return\
3950 end\
3951\
3952 room.exits[\"up\"] = true\
3953 if y == -1 then\
3954 room.items[ \"an exit to the surface\" ] = items[ \"an exit to the surface\" ]\
3955 end\
3956 y = y + 1\
3957 \
3958 room = getRoom( x, y, z )\
3959 room.exits[\"down\"] = true\
3960 if y == 0 then\
3961 room.items[ \"a cave entrance\" ] = items[ \"a cave entrance\" ]\
3962 end\
3963 \
3964 elseif _sDir == \"down\" then\
3965 if y <= -3 then\
3966 print( \"You hit bedrock.\" )\
3967 return\
3968 end\
3969\
3970 room.exits[\"down\"] = true\
3971 if y == 0 then\
3972 room.items[ \"a cave entrance\" ] = items[ \"a cave entrance\" ]\
3973 end\
3974 y = y - 1\
3975 \
3976 room = getRoom( x, y, z )\
3977 room.exits[\"up\"] = true\
3978 if y == -1 then\
3979 room.items[ \"an exit to the surface\" ] = items[ \"an exit to the surface\" ]\
3980 end\
3981 \
3982 else\
3983 print( \"I don't understand that direction.\" )\
3984 return\
3985 end\
3986 \
3987 --\
3988 if bActuallyDigging then\
3989 if _sDir == \"down\" and y == -1 or\
3990 _sDir == \"up\" and y == 0 then\
3991 inventory[ \"some dirt\" ] = items[ \"some dirt\" ]\
3992 inventory[ \"some stone\" ] = items[ \"some stone\" ]\
3993 print( \"You dig \".._sDir..\" using \"..sTool..\" and collect some dirt and stone.\" )\
3994 else\
3995 inventory[ \"some stone\" ] = items[ \"some stone\" ]\
3996 print( \"You dig \".._sDir..\" using \"..sTool..\" and collect some stone.\" )\
3997 end\
3998 end\
3999 \
4000 nTimeInRoom = 0\
4001 doCommand( \"look\" )\
4002end\
4003\
4004function commands.inventory()\
4005 print( \"You are carrying \" .. itemize( inventory ) .. \".\" )\
4006end\
4007\
4008function commands.drop( _sItem )\
4009 if _sItem == nil then\
4010 print( \"Drop what?\" )\
4011 return\
4012 end\
4013 \
4014 local room = getRoom( x,y,z )\
4015 local sItem = findItem( inventory, _sItem )\
4016 if sItem then\
4017 local tItem = inventory[ sItem ]\
4018 if tItem.droppable == false then\
4019 print( \"You can't drop that.\" )\
4020 else\
4021 room.items[ sItem ] = tItem\
4022 inventory[ sItem ] = nil\
4023 print( \"Dropped.\" )\
4024 end\
4025 else\
4026 print( \"You don't have a \".._sItem..\".\" )\
4027 end\
4028end\
4029\
4030function commands.place( _sItem )\
4031 if _sItem == nil then\
4032 print( \"Place what?\" )\
4033 return\
4034 end\
4035 \
4036 if _sItem == \"torch\" or _sItem == \"a torch\" then\
4037 local room = getRoom( x,y,z )\
4038 if inventory[\"some torches\"] or inventory[\"a torch\"] then\
4039 inventory[\"a torch\"] = nil\
4040 room.items[\"a torch\"] = items[\"a torch\"]\
4041 if room.dark then\
4042 print( \"The cave lights up under the torchflame.\" )\
4043 room.dark = false\
4044 elseif y == 0 and not isSunny() then\
4045 print( \"The night gets a little brighter.\" )\
4046 else\
4047 print( \"Placed.\" )\
4048 end\
4049 else\
4050 print( \"You don't have torches.\" )\
4051 end\
4052 return\
4053 end\
4054 \
4055 commands.drop( _sItem )\
4056end\
4057\
4058function commands.take( _sItem )\
4059 if _sItem == nil then\
4060 print( \"Take what?\" )\
4061 return\
4062 end\
4063\
4064 local room = getRoom( x,y,z )\
4065 local sItem = findItem( room.items, _sItem )\
4066 if sItem then\
4067 local tItem = room.items[ sItem ]\
4068 if tItem.heavy == true then\
4069 print( \"You can't carry \"..sItem..\".\" )\
4070 elseif tItem.ore == true then\
4071 print( \"You need to mine this ore.\" )\
4072 else\
4073 if tItem.infinite ~= true then\
4074 room.items[ sItem ] = nil\
4075 end\
4076 inventory[ sItem ] = tItem\
4077 \
4078 if inventory[\"some torches\"] and inventory[\"a torch\"] then\
4079 inventory[\"a torch\"] = nil\
4080 end\
4081 if sItem == \"a torch\" and y < 0 then\
4082 room.dark = true\
4083 print( \"The cave plunges into darkness.\" )\
4084 else\
4085 print( \"Taken.\" )\
4086 end\
4087 end\
4088 else\
4089 print( \"You don't see a \".._sItem..\" here.\" )\
4090 end\
4091end\
4092\
4093function commands.mine( _sItem, _sTool )\
4094 if _sItem == nil then\
4095 print( \"Mine what?\" )\
4096 return\
4097 end\
4098 if _sTool == nil then\
4099 print( \"Mine \".._sItem..\" with what?\" )\
4100 return\
4101 end \
4102 commands.cbreak( _sItem, _sTool )\
4103end\
4104\
4105function commands.attack( _sItem, _sTool )\
4106 if _sItem == nil then\
4107 print( \"Attack what?\" )\
4108 return\
4109 end\
4110 commands.cbreak( _sItem, _sTool )\
4111end\
4112\
4113function commands.cbreak( _sItem, _sTool )\
4114 if _sItem == nil then\
4115 print( \"Break what?\" )\
4116 return\
4117 end\
4118 \
4119 local sTool = nil\
4120 if _sTool ~= nil then\
4121 sTool = findItem( inventory, _sTool )\
4122 if sTool == nil then\
4123 print( \"You're not carrying a \".._sTool..\".\" )\
4124 return\
4125 end\
4126 end\
4127\
4128 local room = getRoom( x,y,z )\
4129 if _sItem == \"tree\" or _sItem == \"trees\" or _sItem == \"a tree\" then\
4130 print( \"The tree breaks into blocks of wood, which you pick up.\" )\
4131 inventory[ \"some wood\" ] = items[ \"some wood\" ]\
4132 return\
4133 elseif _sItem == \"self\" or _sItem == \"myself\" then\
4134 if term.isColour() then\
4135 term.setTextColour( colours.red )\
4136 end\
4137 print( \"You have died.\" )\
4138 print( \"Score: &e0\" )\
4139 term.setTextColour( colours.white )\
4140 bRunning = false\
4141 return\
4142 end\
4143 \
4144 local sItem = findItem( room.items, _sItem )\
4145 if sItem then\
4146 local tItem = room.items[ sItem ]\
4147 if tItem.ore == true then\
4148 -- Breaking ore\
4149 if not sTool then\
4150 print( \"You need a tool to break this ore.\" )\
4151 return\
4152 end\
4153 local tTool = inventory[ sTool ]\
4154 if tTool.tool then\
4155 if tTool.toolLevel < tItem.toolLevel then\
4156 print( sTool ..\" is not strong enough to break this ore.\" )\
4157 elseif tTool.toolType ~= tItem.toolType then\
4158 print( \"You need a different kind of tool to break this ore.\" )\
4159 else\
4160 print( \"The ore breaks, dropping \"..sItem..\", which you pick up.\" )\
4161 inventory[ sItem ] = items[ sItem ]\
4162 if tItem.infinite ~= true then\
4163 room.items[ sItem ] = nil\
4164 end\
4165 end\
4166 else\
4167 print( \"You can't break \"..sItem..\" with \"..sTool..\".\")\
4168 end\
4169 \
4170 elseif tItem.creature == true then\
4171 -- Fighting monsters (or pigs)\
4172 local toolLevel = 0\
4173 local tTool = nil\
4174 if sTool then\
4175 tTool = inventory[ sTool ]\
4176 if tTool.toolType == \"sword\" then\
4177 toolLevel = tTool.toolLevel\
4178 end\
4179 end\
4180 \
4181 local tChances = { 0.2, 0.4, 0.55, 0.8, 1 }\
4182 if math.random() <= tChances[ toolLevel + 1 ] then\
4183 room.items[ sItem ] = nil\
4184 print( \"The \"..tItem.aliases[1]..\" dies.\" )\
4185 \
4186 if tItem.drops then\
4187 for n, sDrop in pairs( tItem.drops ) do\
4188 if not room.items[sDrop] then\
4189 print( \"The \"..tItem.aliases[1]..\" dropped \"..sDrop..\".\" )\
4190 room.items[sDrop] = items[sDrop]\
4191 end\
4192 end\
4193 end\
4194 \
4195 if tItem.monster then\
4196 room.nMonsters = room.nMonsters - 1\
4197 end\
4198 else\
4199 print( \"The \"..tItem.aliases[1]..\" is injured by your blow.\" )\
4200 end\
4201 \
4202 if tItem.hitDrops then\
4203 for n, sDrop in pairs( tItem.hitDrops ) do\
4204 if not room.items[sDrop] then\
4205 print( \"The \"..tItem.aliases[1]..\" dropped \"..sDrop..\".\" )\
4206 room.items[sDrop] = items[sDrop]\
4207 end\
4208 end\
4209 end\
4210 \
4211 else\
4212 print( \"You can't break \"..sItem..\".\" )\
4213 end\
4214 else\
4215 print( \"You don't see a \".._sItem..\" here.\" )\
4216 end\
4217end\
4218\
4219function commands.craft( _sItem )\
4220 if _sItem == nil then\
4221 print( \"Craft what?\" )\
4222 return\
4223 end\
4224 \
4225 if _sItem == \"computer\" or _sItem == \"a computer\" then\
4226 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.\" )\
4227 if term.isColour() then\
4228 term.setTextColour( colours.red )\
4229 end\
4230 print( \"You have died.\" )\
4231 print( \"Score: &e0\" )\
4232 term.setTextColour( colours.white )\
4233 bRunning = false\
4234 return\
4235 end\
4236 \
4237 local room = getRoom( x,y,z )\
4238 local sItem = findItem( items, _sItem )\
4239 local tRecipe = (sItem and tRecipes[ sItem ]) or nil\
4240 if tRecipe then\
4241 for n,sReq in ipairs( tRecipe ) do\
4242 if inventory[sReq] == nil then\
4243 print( \"You don't have the items you need to craft \"..sItem..\".\" )\
4244 return\
4245 end\
4246 end\
4247 \
4248 for n,sReq in ipairs( tRecipe ) do\
4249 inventory[sReq] = nil\
4250 end\
4251 inventory[ sItem ] = items[ sItem ]\
4252 if inventory[\"some torches\"] and inventory[\"a torch\"] then\
4253 inventory[\"a torch\"] = nil\
4254 end\
4255 print( \"Crafted.\" )\
4256 else\
4257 print( \"You don't know how to make \"..(sItem or _sItem)..\".\" )\
4258 end \
4259end\
4260\
4261function commands.build( _sThing, _sMaterial )\
4262 if _sThing == nil then\
4263 print( \"Build what?\" )\
4264 return\
4265 end\
4266 \
4267 local sMaterial = nil\
4268 if _sMaterial == nil then\
4269 for sItem, tItem in pairs( inventory ) do\
4270 if tItem.material then\
4271 sMaterial = sItem\
4272 break\
4273 end\
4274 end\
4275 if sMaterial == nil then\
4276 print( \"You don't have any building materials.\" )\
4277 return\
4278 end\
4279 else\
4280 sMaterial = findItem( inventory, _sMaterial )\
4281 if not sMaterial then\
4282 print( \"You don't have any \".._sMaterial )\
4283 return\
4284 end\
4285 \
4286 if inventory[sMaterial].material ~= true then\
4287 print( sMaterial..\" is not a good building material.\" )\
4288 return\
4289 end\
4290 end\
4291 \
4292 local alias = nil\
4293 if string.sub(_sThing, 1, 1) == \"a\" then\
4294 alias = string.match( _sThing, \"a ([%a ]+)\" )\
4295 end\
4296 \
4297 local room = getRoom( x,y,z )\
4298 inventory[sMaterial] = nil\
4299 room.items[ _sThing ] = {\
4300 heavy = true,\
4301 aliases = { alias },\
4302 desc = \"As you look at your creation (made from \"..sMaterial..\"), you feel a swelling sense of pride.\",\
4303 }\
4304\
4305 print( \"Your construction is complete.\" )\
4306end\
4307\
4308function commands.help()\
4309 local sText = \
4310 \"Welcome to adventure, the greatest text adventure game on CraftOS. \" ..\
4311 \"To get around the world, type actions, and the adventure will \" ..\
4312 \"be read back to you. The actions availiable to you are go, look, inspect, inventory, \" ..\
4313 \"take, drop, place, punch, attack, mine, dig, craft, build, eat and exit.\"\
4314 print( sText )\
4315end\
4316\
4317function commands.eat( _sItem )\
4318 if _sItem == nil then\
4319 print( \"Eat what?\" )\
4320 return\
4321 end\
4322\
4323 local sItem = findItem( inventory, _sItem )\
4324 if not sItem then\
4325 print( \"You don't have any \".._sItem..\".\" )\
4326 return\
4327 end\
4328 \
4329 local tItem = inventory[sItem]\
4330 if tItem.food then\
4331 print( \"That was delicious!\" )\
4332 inventory[sItem] = nil\
4333 \
4334 if bInjured then\
4335 print( \"You are no longer injured.\" )\
4336 bInjured = false\
4337 end\
4338 else\
4339 print( \"You can't eat \"..sItem..\".\" )\
4340 end\
4341end\
4342\
4343function commands.exit()\
4344 bRunning = false\
4345end\
4346\
4347function commands.badinput()\
4348 local tResponses = {\
4349 \"I don't understand.\",\
4350 \"I don't understand you.\",\
4351 \"You can't do that.\",\
4352 \"Nope.\",\
4353 \"Huh?\",\
4354 \"Say again?\",\
4355 \"That's crazy talk.\",\
4356 \"Speak clearly.\",\
4357 \"I'll think about it.\",\
4358 \"Let me get back to you on that one.\",\
4359 \"That doesn't make any sense.\",\
4360 \"What?\",\
4361 }\
4362 print( tResponses[ math.random(1,#tResponses) ] )\
4363end\
4364\
4365function commands.noinput()\
4366 local tResponses = {\
4367 \"Speak up.\",\
4368 \"Enunciate.\",\
4369 \"Project your voice.\",\
4370 \"Don't be shy.\",\
4371 \"Use your words.\",\
4372 }\
4373 print( tResponses[ math.random(1,#tResponses) ] )\
4374end\
4375\
4376local function simulate()\
4377 local bNewMonstersThisRoom = false\
4378 \
4379 -- Spawn monsters in nearby rooms\
4380 for sx = -2,2 do\
4381 for sy = -1,1 do\
4382 for sz = -2,2 do\
4383 local h = y + sy\
4384 if h >= -3 and h <= 0 then\
4385 local room = getRoom( x + sx, h, z + sz )\
4386 \
4387 -- Spawn monsters\
4388 if room.nMonsters < 2 and\
4389 ((h == 0 and not isSunny() and not room.items[\"a torch\"]) or room.dark) and\
4390 math.random(1,6) == 1 then\
4391 \
4392 local sMonster = tMonsters[ math.random(1,#tMonsters) ]\
4393 if room.items[ sMonster ] == nil then\
4394 room.items[ sMonster ] = items[ sMonster ]\
4395 room.nMonsters = room.nMonsters + 1\
4396 \
4397 if sx == 0 and sy == 0 and sz == 0 and not room.dark then\
4398 print( \"From the shadows, \"..sMonster..\" appears.\" )\
4399 bNewMonstersThisRoom = true\
4400 end\
4401 end \
4402 end\
4403 \
4404 -- Burn monsters\
4405 if h == 0 and isSunny() then\
4406 for n,sMonster in ipairs( tMonsters ) do\
4407 if room.items[sMonster] and items[sMonster].nocturnal then\
4408 room.items[sMonster] = nil\
4409 if sx == 0 and sy == 0 and sz == 0 and not room.dark then\
4410 print( \"With the sun high in the sky, the \"..items[sMonster].aliases[1]..\" bursts into flame and dies.\" )\
4411 end\
4412 room.nMonsters = room.nMonsters - 1\
4413 end\
4414 end\
4415 end \
4416 end\
4417 end\
4418 end\
4419 end\
4420\
4421 -- Make monsters attack\
4422 local room = getRoom( x, y, z )\
4423 if nTimeInRoom >= 2 and not bNewMonstersThisRoom then\
4424 for n,sMonster in ipairs( tMonsters ) do\
4425 if room.items[sMonster] then\
4426 if math.random(1,4) == 1 and\
4427 not (y == 0 and isSunny() and (sMonster == \"a spider\")) then\
4428 if sMonster == \"a creeper\" then\
4429 if room.dark then\
4430 print( \"A creeper explodes.\" )\
4431 else\
4432 print( \"The creeper explodes.\" )\
4433 end\
4434 room.items[sMonster] = nil\
4435 room.nMonsters = room.nMonsters - 1\
4436 else\
4437 if room.dark then\
4438 print( \"A \"..items[sMonster].aliases[1]..\" attacks you.\" )\
4439 else\
4440 print( \"The \"..items[sMonster].aliases[1]..\" attacks you.\" )\
4441 end\
4442 end\
4443 \
4444 if bInjured then\
4445 if term.isColour() then\
4446 term.setTextColour( colours.red )\
4447 end\
4448 print( \"You have died.\" )\
4449 print( \"Score: &e0\" )\
4450 term.setTextColour( colours.white )\
4451 bRunning = false\
4452 return\
4453 else\
4454 bInjured = true\
4455 end\
4456 \
4457 break\
4458 end\
4459 end\
4460 end\
4461 end\
4462 \
4463 -- Always print this\
4464 if bInjured then\
4465 if term.isColour() then\
4466 term.setTextColour( colours.red )\
4467 end\
4468 print( \"You are injured.\" )\
4469 term.setTextColour( colours.white )\
4470 end\
4471 \
4472 -- Advance time\
4473 nTurn = nTurn + 1\
4474 nTimeInRoom = nTimeInRoom + 1\
4475end\
4476\
4477doCommand( \"look\" )\
4478simulate()\
4479\
4480local tCommandHistory = {}\
4481while bRunning do\
4482 if term.isColour() then\
4483 term.setTextColour( colours.yellow )\
4484 end\
4485 write( \"? \" )\
4486 term.setTextColour( colours.white )\
4487 \
4488 local sRawLine = read( nil, tCommandHistory )\
4489 table.insert( tCommandHistory, sRawLine )\
4490 \
4491 local sLine = nil\
4492 for match in string.gmatch(sRawLine, \"%a+\") do\
4493 if sLine then\
4494 sLine = sLine .. \" \" .. string.lower(match)\
4495 else\
4496 sLine = string.lower(match)\
4497 end\
4498 end\
4499 \
4500 doCommand( sLine or \"\" )\
4501 if bRunning then\
4502 simulate()\
4503 end\
4504end",},["rename"]="shell.run( \"move\", ... )",["gps"]="\
4505local function printUsage()\
4506 print( \"Usages:\" )\
4507 print( \"gps host\" )\
4508 print( \"gps host <x> <y> <z>\" )\
4509 print( \"gps locate\" )\
4510end\
4511\
4512local tArgs = { ... }\
4513if #tArgs < 1 then\
4514 printUsage()\
4515 return\
4516end\
4517 \
4518local sCommand = tArgs[1]\
4519if sCommand == \"locate\" then\
4520 -- \"gps locate\"\
4521 -- Just locate this computer (this will print the results)\
4522 gps.locate( 2, true )\
4523 \
4524elseif sCommand == \"host\" then\
4525 -- \"gps host\"\
4526 -- Act as a GPS host\
4527 \
4528 -- Find a modem\
4529 local sModemSide = nil\
4530 for n,sSide in ipairs( rs.getSides() ) do\
4531 if peripheral.getType( sSide ) == \"modem\" and peripheral.call( sSide, \"isWireless\" ) then \
4532 sModemSide = sSide\
4533 break\
4534 end\
4535 end\
4536\
4537 if sModemSide == nil then\
4538 print( \"No wireless modem attached\" )\
4539 return\
4540 end\
4541 \
4542 -- Open a channel\
4543 local modem = peripheral.wrap( sModemSide )\
4544 local bCloseChannel = false\
4545 if not modem.isOpen( gps.CHANNEL_GPS ) then\
4546 print( \"Opening GPS channel on \"..sModemSide..\" modem\" )\
4547 modem.open( gps.CHANNEL_GPS )\
4548 bCloseChannel = true\
4549 end\
4550\
4551 -- Determine position\
4552 local x,y,z\
4553 if #tArgs >= 4 then\
4554 -- Position is manually specified\
4555 x = tonumber(tArgs[2])\
4556 y = tonumber(tArgs[3])\
4557 z = tonumber(tArgs[4])\
4558 if x == nil or y == nil or z == nil then\
4559 printUsage()\
4560 return\
4561 end\
4562 print( \"Position is \"..x..\",\"..y..\",\"..z )\
4563 else\
4564 -- Position is to be determined using locate \
4565 x,y,z = gps.locate( 2, true )\
4566 if x == nil then\
4567 print( \"Run \\\"gps host <x> <y> <z>\\\" to set position manually\" )\
4568 if bCloseChannel then\
4569 print( \"Closing GPS channel\" )\
4570 modem.close( gps.CHANNEL_GPS )\
4571 end\
4572 return\
4573 end\
4574 end\
4575 \
4576 -- Serve requests indefinately\
4577 print( \"Serving GPS requests. Press Q to quit\" )\
4578 \
4579 local nServed = 0\
4580 while true do\
4581 local e, p1, p2, p3, p4, p5 = os.pullEvent()\
4582 if e == \"modem_message\" then\
4583 -- We received a message from a modem\
4584 local sSide, sChannel, sReplyChannel, sMessage, nDistance = p1, p2, p3, p4, p5\
4585 if sSide == sModemSide and sChannel == gps.CHANNEL_GPS and sMessage == \"PING\" then\
4586 -- We received a ping message on the GPS channel, send a response\
4587 modem.transmit( sReplyChannel, gps.CHANNEL_GPS, textutils.serialize({x,y,z}) )\
4588 \
4589 -- Print the number of requests handled\
4590 nServed = nServed + 1\
4591 if nServed > 1 then\
4592 local x,y = term.getCursorPos()\
4593 term.setCursorPos(1,y-1)\
4594 end\
4595 print( nServed..\" GPS Requests served\" )\
4596 end\
4597 \
4598 elseif e == \"key\" then\
4599 -- We received a key press, quit\
4600 local key = p1\
4601 if key == keys.q then\
4602 os.pullEvent(\"char\")\
4603 break\
4604 end\
4605 \
4606 end\
4607 end\
4608 \
4609 if bCloseChannel then\
4610 print( \"Closing GPS channel\" )\
4611 modem.close( gps.CHANNEL_GPS )\
4612 end\
4613 \
4614else\
4615 -- \"gps somethingelse\"\
4616 -- Error\
4617 printUsage()\
4618 \
4619end",["exit"]="shell.exit()",["list"]="\
4620local tArgs = { ... }\
4621\
4622-- Get all the files in the directory\
4623local sDir = shell.dir()\
4624if tArgs[1] ~= nil then\
4625 sDir = shell.resolve( tArgs[1] )\
4626end\
4627\
4628-- Sort into dirs/files, and calculate column count\
4629local tAll = fs.list( sDir )\
4630local tFiles = {}\
4631local tDirs = {}\
4632\
4633for n, sItem in pairs( tAll ) do\
4634 if string.sub( sItem, 1, 1 ) ~= \".\" then\
4635 local sPath = fs.combine( sDir, sItem )\
4636 if fs.isDir( sPath ) then\
4637 table.insert( tDirs, sItem )\
4638 else\
4639 table.insert( tFiles, sItem )\
4640 end\
4641 end\
4642end\
4643table.sort( tDirs )\
4644table.sort( tFiles )\
4645\
4646if term.isColour() then\
4647 textutils.pagedTabulate( colors.green, tDirs, colours.white, tFiles )\
4648else\
4649 textutils.pagedTabulate( tDirs, tFiles )\
4650end",["monitor"]="\
4651function printUsage()\
4652 print( \"Usage: monitor <side> <program> <arguments>\" )\
4653 return\
4654end\
4655\
4656local tArgs = { ... }\
4657if #tArgs < 2 then\
4658 printUsage()\
4659 return\
4660end\
4661\
4662local sSide = tArgs[1]\
4663if peripheral.getType( sSide ) ~= \"monitor\" then\
4664 print( \"No monitor on \"..sSide..\" side\" )\
4665 return\
4666end\
4667\
4668local sProgram = tArgs[2]\
4669local sPath = shell.resolveProgram( sProgram )\
4670if sPath == nil then\
4671 print( \"No such program: \"..sProgram )\
4672 return\
4673end\
4674\
4675print( \"Running \"..sProgram..\" on \"..sSide..\" monitor\" )\
4676\
4677local monitor = peripheral.wrap( sSide )\
4678term.redirect( monitor )\
4679\
4680local co = coroutine.create( function()\
4681 shell.run( sProgram, unpack( tArgs, 3 ) )\
4682end )\
4683\
4684local function resume( ... )\
4685 local ok, param = coroutine.resume( co, ... )\
4686 if not ok then\
4687 printError( param )\
4688 end\
4689 return param\
4690end\
4691\
4692local ok, param = pcall( function()\
4693 local sFilter = resume()\
4694 while coroutine.status( co ) ~= \"dead\" do\
4695 local tEvent = { os.pullEventRaw() }\
4696 if sFilter == nil or tEvent[1] == sFilter or tEvent[1] == \"terminate\" then\
4697 sFilter = resume( unpack( tEvent ) )\
4698 end\
4699 if coroutine.status( co ) ~= \"dead\" and (sFilter == nil or sFilter == \"mouse_click\") then\
4700 if tEvent[1] == \"monitor_touch\" and tEvent[2] == sSide then\
4701 sFilter = resume( \"mouse_click\", 1, unpack( tEvent, 3 ) )\
4702 end\
4703 end\
4704 end\
4705end )\
4706\
4707term.restore()\
4708if not ok then\
4709 printError( param )\
4710end\
4711 ",["eject"]="\
4712-- Get arguments\
4713local tArgs = { ... }\
4714if #tArgs == 0 then\
4715 print( \"Usage: eject <drive>\" )\
4716 return\
4717end\
4718\
4719local sDrive = tArgs[1]\
4720\
4721-- Check the disk exists\
4722local bPresent = disk.isPresent( sDrive )\
4723if not bPresent then\
4724 print( \"Nothing in \"..sDrive..\" drive\" )\
4725 return\
4726end\
4727\
4728disk.eject( sDrive )",["shell"]="\
4729local parentShell = shell\
4730\
4731local bExit = false\
4732local sDir = (parentShell and parentShell.dir()) or \"\"\
4733local sPath = (parentShell and parentShell.path()) or \".:/rom/programs\"\
4734local tAliases = (parentShell and parentShell.aliases()) or {}\
4735local tProgramStack = {}\
4736\
4737local shell = {}\
4738local tEnv = {\
4739 [\"shell\"] = shell,\
4740}\
4741\
4742-- Colours\
4743local promptColour, textColour, bgColour\
4744if term.isColour() then\
4745 promptColour = colours.yellow\
4746 textColour = colours.white\
4747 bgColour = colours.black\
4748else\
4749 promptColour = colours.white\
4750 textColour = colours.white\
4751 bgColour = colours.black\
4752end\
4753\
4754\
4755local function run( _sCommand, ... )\
4756 local sPath = shell.resolveProgram( _sCommand )\
4757 if sPath ~= nil then\
4758 tProgramStack[#tProgramStack + 1] = sPath\
4759 local result = os.run( tEnv, sPath, ... )\
4760 tProgramStack[#tProgramStack] = nil\
4761 return result\
4762 else\
4763 printError( \"No such program\" )\
4764 return false\
4765 end\
4766end\
4767\
4768local function runLine( _sLine )\
4769 local tWords = {}\
4770 for match in string.gmatch( _sLine, \"[^ \\t]+\" ) do\
4771 table.insert( tWords, match )\
4772 end\
4773\
4774 local sCommand = tWords[1]\
4775 if sCommand then\
4776 return run( sCommand, unpack( tWords, 2 ) )\
4777 end\
4778 return false\
4779end\
4780\
4781-- Install shell API\
4782function shell.run( ... )\
4783 return runLine( table.concat( { ... }, \" \" ) )\
4784end\
4785\
4786function shell.exit()\
4787 bExit = true\
4788end\
4789\
4790function shell.dir()\
4791 return sDir\
4792end\
4793\
4794function shell.setDir( _sDir )\
4795 sDir = _sDir\
4796end\
4797\
4798function shell.path()\
4799 return sPath\
4800end\
4801\
4802function shell.setPath( _sPath )\
4803 sPath = _sPath\
4804end\
4805\
4806function shell.resolve( _sPath )\
4807 local sStartChar = string.sub( _sPath, 1, 1 )\
4808 if sStartChar == \"/\" or sStartChar == \"\\\\\" then\
4809 return fs.combine( \"\", _sPath )\
4810 else\
4811 return fs.combine( sDir, _sPath )\
4812 end\
4813end\
4814\
4815function shell.resolveProgram( _sCommand )\
4816 -- Substitute aliases firsts\
4817 if tAliases[ _sCommand ] ~= nil then\
4818 _sCommand = tAliases[ _sCommand ]\
4819 end\
4820\
4821 -- If the path is a global path, use it directly\
4822 local sStartChar = string.sub( _sCommand, 1, 1 )\
4823 if sStartChar == \"/\" or sStartChar == \"\\\\\" then\
4824 local sPath = fs.combine( \"\", _sCommand )\
4825 if fs.exists( sPath ) and not fs.isDir( sPath ) then\
4826 return sPath\
4827 end\
4828 return nil\
4829 end\
4830 \
4831 -- Otherwise, look on the path variable\
4832 for sPath in string.gmatch(sPath, \"[^:]+\") do\
4833 sPath = fs.combine( shell.resolve( sPath ), _sCommand )\
4834 if fs.exists( sPath ) and not fs.isDir( sPath ) then\
4835 return sPath\
4836 end\
4837 end\
4838 \
4839 -- Not found\
4840 return nil\
4841end\
4842\
4843function shell.programs( _bIncludeHidden )\
4844 local tItems = {}\
4845 \
4846 -- Add programs from the path\
4847 for sPath in string.gmatch(sPath, \"[^:]+\") do\
4848 sPath = shell.resolve( sPath )\
4849 if fs.isDir( sPath ) then\
4850 local tList = fs.list( sPath )\
4851 for n,sFile in pairs( tList ) do\
4852 if not fs.isDir( fs.combine( sPath, sFile ) ) and\
4853 (_bIncludeHidden or string.sub( sFile, 1, 1 ) ~= \".\") then\
4854 tItems[ sFile ] = true\
4855 end\
4856 end\
4857 end\
4858 end \
4859\
4860 -- Sort and return\
4861 local tItemList = {}\
4862 for sItem, b in pairs( tItems ) do\
4863 table.insert( tItemList, sItem )\
4864 end\
4865 table.sort( tItemList )\
4866 return tItemList\
4867end\
4868\
4869function shell.getRunningProgram()\
4870 if #tProgramStack > 0 then\
4871 return tProgramStack[#tProgramStack]\
4872 end\
4873 return nil\
4874end\
4875\
4876function shell.setAlias( _sCommand, _sProgram )\
4877 tAliases[ _sCommand ] = _sProgram\
4878end\
4879\
4880function shell.clearAlias( _sCommand )\
4881 tAliases[ _sCommand ] = nil\
4882end\
4883\
4884function shell.aliases()\
4885 -- Add aliases\
4886 local tCopy = {}\
4887 for sAlias, sCommand in pairs( tAliases ) do\
4888 tCopy[sAlias] = sCommand\
4889 end\
4890 return tCopy\
4891end\
4892 \
4893term.setBackgroundColor( bgColour )\
4894term.setTextColour( promptColour )\
4895print( os.version() )\
4896term.setTextColour( textColour )\
4897\
4898-- If this is the toplevel shell, run the startup programs\
4899if parentShell == nil then\
4900 -- Run the startup from the ROM first\
4901 local sRomStartup = shell.resolveProgram( \"/rom/startup\" )\
4902 if sRomStartup then\
4903 shell.run( sRomStartup )\
4904 end\
4905 \
4906 -- Then run the user created startup, from the disks or the root\
4907 local sUserStartup = shell.resolveProgram( \"/startup\" )\
4908 for n,sSide in pairs( peripheral.getNames() ) do\
4909 if disk.isPresent( sSide ) and disk.hasData( sSide ) then\
4910 local sDiskStartup = shell.resolveProgram( fs.combine(disk.getMountPath( sSide ), \"startup\") )\
4911 if sDiskStartup then\
4912 sUserStartup = sDiskStartup\
4913 break\
4914 end\
4915 end\
4916 end\
4917 \
4918 if sUserStartup then\
4919 shell.run( sUserStartup )\
4920 end\
4921end\
4922\
4923-- Run any programs passed in as arguments\
4924local tArgs = { ... }\
4925if #tArgs > 0 then\
4926 shell.run( ... )\
4927end\
4928\
4929-- Read commands and execute them\
4930local tCommandHistory = {}\
4931while not bExit do\
4932 term.setBackgroundColor( bgColour )\
4933 term.setTextColour( promptColour )\
4934 write( shell.dir() .. \"> \" )\
4935 term.setTextColour( textColour )\
4936\
4937 local sLine = read( nil, tCommandHistory )\
4938 table.insert( tCommandHistory, sLine )\
4939 runLine( sLine )\
4940end\
4941\
4942-- If this is the toplevel shell, run the shutdown program\
4943if parentShell == nil then\
4944 if shell.resolveProgram( \"shutdown\" ) then\
4945 shell.run( \"shutdown\" )\
4946 end\
4947 os.shutdown() -- just in case\
4948end",["shutdown"]="if term.isColour() then\
4949 term.setTextColour( colours.yellow )\
4950end\
4951print( \"Goodbye\" )\
4952term.setTextColour( colours.white )\
4953\
4954sleep( 1 )\
4955os.shutdown()",["copy"]="\
4956local tArgs = { ... }\
4957if #tArgs < 2 then\
4958 print( \"Usage: cp <source> <destination>\" )\
4959 return\
4960end\
4961\
4962local sSource = shell.resolve( tArgs[1] )\
4963local sDest = shell.resolve( tArgs[2] )\
4964if fs.exists( sDest ) and fs.isDir( sDest ) then\
4965 sDest = fs.combine( sDest, fs.getName(sSource) )\
4966end\
4967fs.copy( sSource, sDest )",["time"]="local nTime = os.time()\
4968local nDay = os.day()\
4969print( \"The time is \"..textutils.formatTime( nTime, false )..\" on Day \"..nDay )",["turtle"]={["excavate"]="\
4970local tArgs = { ... }\
4971if #tArgs ~= 1 then\
4972 print( \"Usage: excavate <diameter>\" )\
4973 return\
4974end\
4975\
4976-- Mine in a quarry pattern until we hit something we can't dig\
4977local size = tonumber( tArgs[1] )\
4978if size < 1 then\
4979 print( \"Excavate diameter must be positive\" )\
4980 return\
4981end\
4982 \
4983local depth = 0\
4984local unloaded = 0\
4985local collected = 0\
4986\
4987local xPos,zPos = 0,0\
4988local xDir,zDir = 0,1\
4989\
4990local goTo -- Filled in further down\
4991local refuel -- Filled in further down\
4992 \
4993local function unload( _bKeepOneFuelStack )\
4994 print( \"Unloading items...\" )\
4995 for n=1,16 do\
4996 local nCount = turtle.getItemCount(n)\
4997 if nCount > 0 then\
4998 turtle.select(n) \
4999 local bDrop = true\
5000 if _bKeepOneFuelStack and turtle.refuel(0) then\
5001 bDrop = false\
5002 _bKeepOneFuelStack = false\
5003 end \
5004 if bDrop then\
5005 turtle.drop()\
5006 unloaded = unloaded + nCount\
5007 end\
5008 end\
5009 end\
5010 collected = 0\
5011 turtle.select(1)\
5012end\
5013\
5014local function returnSupplies()\
5015 local x,y,z,xd,zd = xPos,depth,zPos,xDir,zDir\
5016 print( \"Returning to surface...\" )\
5017 goTo( 0,0,0,0,-1 )\
5018 \
5019 local fuelNeeded = 2*(x+y+z) + 1\
5020 if not refuel( fuelNeeded ) then\
5021 unload( true )\
5022 print( \"Waiting for fuel\" )\
5023 while not refuel( fuelNeeded ) do\
5024 sleep(1)\
5025 end\
5026 else\
5027 unload( true ) \
5028 end\
5029 \
5030 print( \"Resuming mining...\" )\
5031 goTo( x,y,z,xd,zd )\
5032end\
5033\
5034local function collect() \
5035 local bFull = true\
5036 local nTotalItems = 0\
5037 for n=1,16 do\
5038 local nCount = turtle.getItemCount(n)\
5039 if nCount == 0 then\
5040 bFull = false\
5041 end\
5042 nTotalItems = nTotalItems + nCount\
5043 end\
5044 \
5045 if nTotalItems > collected then\
5046 collected = nTotalItems\
5047 if math.fmod(collected + unloaded, 50) == 0 then\
5048 print( \"Mined \"..(collected + unloaded)..\" items.\" )\
5049 end\
5050 end\
5051 \
5052 if bFull then\
5053 print( \"No empty slots left.\" )\
5054 return false\
5055 end\
5056 return true\
5057end\
5058\
5059function refuel( ammount )\
5060 local fuelLevel = turtle.getFuelLevel()\
5061 if fuelLevel == \"unlimited\" then\
5062 return true\
5063 end\
5064 \
5065 local needed = ammount or (xPos + zPos + depth + 2)\
5066 if turtle.getFuelLevel() < needed then\
5067 local fueled = false\
5068 for n=1,16 do\
5069 if turtle.getItemCount(n) > 0 then\
5070 turtle.select(n)\
5071 if turtle.refuel(1) then\
5072 while turtle.getItemCount(n) > 0 and turtle.getFuelLevel() < needed do\
5073 turtle.refuel(1)\
5074 end\
5075 if turtle.getFuelLevel() >= needed then\
5076 turtle.select(1)\
5077 return true\
5078 end\
5079 end\
5080 end\
5081 end\
5082 turtle.select(1)\
5083 return false\
5084 end\
5085 \
5086 return true\
5087end\
5088\
5089local function tryForwards()\
5090 if not refuel() then\
5091 print( \"Not enough Fuel\" )\
5092 returnSupplies()\
5093 end\
5094 \
5095 while not turtle.forward() do\
5096 if turtle.detect() then\
5097 if turtle.dig() then\
5098 if not collect() then\
5099 returnSupplies()\
5100 end\
5101 else\
5102 return false\
5103 end\
5104 elseif turtle.attack() then\
5105 if not collect() then\
5106 returnSupplies()\
5107 end\
5108 else\
5109 sleep( 0.5 )\
5110 end\
5111 end\
5112 \
5113 xPos = xPos + xDir\
5114 zPos = zPos + zDir\
5115 return true\
5116end\
5117\
5118local function tryDown()\
5119 if not refuel() then\
5120 print( \"Not enough Fuel\" )\
5121 returnSupplies()\
5122 end\
5123 \
5124 while not turtle.down() do\
5125 if turtle.detectDown() then\
5126 if turtle.digDown() then\
5127 if not collect() then\
5128 returnSupplies()\
5129 end\
5130 else\
5131 return false\
5132 end\
5133 elseif turtle.attackDown() then\
5134 if not collect() then\
5135 returnSupplies()\
5136 end\
5137 else\
5138 sleep( 0.5 )\
5139 end\
5140 end\
5141\
5142 depth = depth + 1\
5143 if math.fmod( depth, 10 ) == 0 then\
5144 print( \"Descended \"..depth..\" metres.\" )\
5145 end\
5146\
5147 return true\
5148end\
5149\
5150local function turnLeft()\
5151 turtle.turnLeft()\
5152 xDir, zDir = -zDir, xDir\
5153end\
5154\
5155local function turnRight()\
5156 turtle.turnRight()\
5157 xDir, zDir = zDir, -xDir\
5158end\
5159\
5160function goTo( x, y, z, xd, zd )\
5161 while depth > y do\
5162 if turtle.up() then\
5163 depth = depth - 1\
5164 elseif turtle.digUp() or turtle.attackUp() then\
5165 collect()\
5166 else\
5167 sleep( 0.5 )\
5168 end\
5169 end\
5170\
5171 if xPos > x then\
5172 while xDir ~= -1 do\
5173 turnLeft()\
5174 end\
5175 while xPos > x do\
5176 if turtle.forward() then\
5177 xPos = xPos - 1\
5178 elseif turtle.dig() or turtle.attack() then\
5179 collect()\
5180 else\
5181 sleep( 0.5 )\
5182 end\
5183 end\
5184 elseif xPos < x then\
5185 while xDir ~= 1 do\
5186 turnLeft()\
5187 end\
5188 while xPos < x do\
5189 if turtle.forward() then\
5190 xPos = xPos + 1\
5191 elseif turtle.dig() or turtle.attack() then\
5192 collect()\
5193 else\
5194 sleep( 0.5 )\
5195 end\
5196 end\
5197 end\
5198 \
5199 if zPos > z then\
5200 while zDir ~= -1 do\
5201 turnLeft()\
5202 end\
5203 while zPos > z do\
5204 if turtle.forward() then\
5205 zPos = zPos - 1\
5206 elseif turtle.dig() or turtle.attack() then\
5207 collect()\
5208 else\
5209 sleep( 0.5 )\
5210 end\
5211 end\
5212 elseif zPos < z then\
5213 while zDir ~= 1 do\
5214 turnLeft()\
5215 end\
5216 while zPos < z do\
5217 if turtle.forward() then\
5218 zPos = zPos + 1\
5219 elseif turtle.dig() or turtle.attack() then\
5220 collect()\
5221 else\
5222 sleep( 0.5 )\
5223 end\
5224 end \
5225 end\
5226 \
5227 while depth < y do\
5228 if turtle.down() then\
5229 depth = depth + 1\
5230 elseif turtle.digDown() or turtle.attackDown() then\
5231 collect()\
5232 else\
5233 sleep( 0.5 )\
5234 end\
5235 end\
5236 \
5237 while zDir ~= zd or xDir ~= xd do\
5238 turnLeft()\
5239 end\
5240end\
5241\
5242if not refuel() then\
5243 print( \"Out of Fuel\" )\
5244 return\
5245end\
5246\
5247print( \"Excavating...\" )\
5248\
5249local reseal = false\
5250turtle.select(1)\
5251if turtle.digDown() then\
5252 reseal = true\
5253end\
5254\
5255local alternate = 0\
5256local done = false\
5257while not done do\
5258 for n=1,size do\
5259 for m=1,size-1 do\
5260 if not tryForwards() then\
5261 done = true\
5262 break\
5263 end\
5264 end\
5265 if done then\
5266 break\
5267 end\
5268 if n<size then\
5269 if math.fmod(n + alternate,2) == 0 then\
5270 turnLeft()\
5271 if not tryForwards() then\
5272 done = true\
5273 break\
5274 end\
5275 turnLeft()\
5276 else\
5277 turnRight()\
5278 if not tryForwards() then\
5279 done = true\
5280 break\
5281 end\
5282 turnRight()\
5283 end\
5284 end\
5285 end\
5286 if done then\
5287 break\
5288 end\
5289 \
5290 if size > 1 then\
5291 if math.fmod(size,2) == 0 then\
5292 turnRight()\
5293 else\
5294 if alternate == 0 then\
5295 turnLeft()\
5296 else\
5297 turnRight()\
5298 end\
5299 alternate = 1 - alternate\
5300 end\
5301 end\
5302 \
5303 if not tryDown() then\
5304 done = true\
5305 break\
5306 end\
5307end\
5308\
5309print( \"Returning to surface...\" )\
5310\
5311-- Return to where we started\
5312goTo( 0,0,0,0,-1 )\
5313unload( false )\
5314goTo( 0,0,0,0,1 )\
5315\
5316-- Seal the hole\
5317if reseal then\
5318 turtle.placeDown()\
5319end\
5320\
5321print( \"Mined \"..(collected + unloaded)..\" items total.\" )",["go"]="local tArgs = { ... }\
5322if #tArgs < 1 then\
5323 print( \"Usage: go <direction> <distance>\" )\
5324 return\
5325end\
5326\
5327local tHandlers = {\
5328 [\"fd\"] = turtle.forward,\
5329 [\"forward\"] = turtle.forward,\
5330 [\"forwards\"] = turtle.forward,\
5331 [\"bk\"] = turtle.back,\
5332 [\"back\"] = turtle.back,\
5333 [\"up\"] = turtle.up,\
5334 [\"dn\"] = turtle.down,\
5335 [\"down\"] = turtle.down,\
5336 [\"lt\"] = turtle.turnLeft,\
5337 [\"left\"] = turtle.turnLeft,\
5338 [\"rt\"] = turtle.turnRight,\
5339 [\"right\"] = turtle.turnRight,\
5340}\
5341\
5342local nArg = 1\
5343while nArg <= #tArgs do\
5344 local sDirection = tArgs[nArg]\
5345 local nDistance = 1\
5346 if nArg < #tArgs then\
5347 local num = tonumber( tArgs[nArg + 1] )\
5348 if num then\
5349 nDistance = num\
5350 nArg = nArg + 1\
5351 end\
5352 end\
5353 nArg = nArg + 1\
5354\
5355 local fnHandler = tHandlers[string.lower(sDirection)]\
5356 if fnHandler then\
5357 while nDistance > 0 do\
5358 if fnHandler() then\
5359 nDistance = nDistance - 1\
5360 elseif turtle.getFuelLevel() == 0 then\
5361 print( \"Out of fuel\" )\
5362 return\
5363 else\
5364 sleep(0.5)\
5365 end\
5366 end\
5367 else\
5368 print( \"No such direction: \"..sDirection )\
5369 print( \"Try: forward, back, up, down\" )\
5370 return\
5371 end\
5372\
5373end",["tunnel"]="\
5374local tArgs = { ... }\
5375if #tArgs ~= 1 then\
5376 print( \"Usage: tunnel <length>\" )\
5377 return\
5378end\
5379\
5380-- Mine in a quarry pattern until we hit something we can't dig\
5381local length = tonumber( tArgs[1] )\
5382if length < 1 then\
5383 print( \"Tunnel length must be positive\" )\
5384 return\
5385end\
5386 \
5387local depth = 0\
5388local collected = 0\
5389\
5390local function collect()\
5391 collected = collected + 1\
5392 if math.fmod(collected, 25) == 0 then\
5393 print( \"Mined \"..collected..\" items.\" )\
5394 end\
5395end\
5396\
5397local function tryDig()\
5398 while turtle.detect() do\
5399 if turtle.dig() then\
5400 collect()\
5401 sleep(0.5)\
5402 else\
5403 return false\
5404 end\
5405 end\
5406 return true\
5407end\
5408\
5409local function tryDigUp()\
5410 while turtle.detectUp() do\
5411 if turtle.digUp() then\
5412 collect()\
5413 sleep(0.5)\
5414 else\
5415 return false\
5416 end\
5417 end\
5418 return true\
5419end\
5420\
5421local function tryDigDown()\
5422 while turtle.detectDown() do\
5423 if turtle.digDown() then\
5424 collect()\
5425 sleep(0.5)\
5426 else\
5427 return false\
5428 end\
5429 end\
5430 return true\
5431end\
5432\
5433local function refuel()\
5434 local fuelLevel = turtle.getFuelLevel()\
5435 if fuelLevel == \"unlimited\" or fuelLevel > 0 then\
5436 return\
5437 end\
5438 \
5439 local function tryRefuel()\
5440 for n=1,16 do\
5441 if turtle.getItemCount(n) > 0 then\
5442 turtle.select(n)\
5443 if turtle.refuel(1) then\
5444 turtle.select(1)\
5445 return true\
5446 end\
5447 end\
5448 end\
5449 turtle.select(1)\
5450 return false\
5451 end\
5452 \
5453 if not tryRefuel() then\
5454 print( \"Add more fuel to continue.\" )\
5455 while not tryRefuel() do\
5456 sleep(1)\
5457 end\
5458 print( \"Resuming Tunnel.\" )\
5459 end\
5460end\
5461\
5462local function tryUp()\
5463 refuel()\
5464 while not turtle.up() do\
5465 if turtle.detectUp() then\
5466 if not tryDigUp() then\
5467 return false\
5468 end\
5469 elseif turtle.attackUp() then\
5470 collect()\
5471 else\
5472 sleep( 0.5 )\
5473 end\
5474 end\
5475 return true\
5476end\
5477\
5478local function tryDown()\
5479 refuel()\
5480 while not turtle.down() do\
5481 if turtle.detectDown() then\
5482 if not tryDigDown() then\
5483 return false\
5484 end\
5485 elseif turtle.attackDown() then\
5486 collect()\
5487 else\
5488 sleep( 0.5 )\
5489 end\
5490 end\
5491 return true\
5492end\
5493\
5494local function tryForward()\
5495 refuel()\
5496 while not turtle.forward() do\
5497 if turtle.detect() then\
5498 if not tryDig() then\
5499 return false\
5500 end\
5501 elseif turtle.attack() then\
5502 collect()\
5503 else\
5504 sleep( 0.5 )\
5505 end\
5506 end\
5507 return true\
5508end\
5509\
5510print( \"Tunnelling...\" )\
5511\
5512for n=1,length do\
5513 turtle.placeDown()\
5514 tryDigUp()\
5515 turtle.turnLeft()\
5516 tryDig()\
5517 tryUp()\
5518 tryDig()\
5519 turtle.turnRight()\
5520 turtle.turnRight()\
5521 tryDig()\
5522 tryDown()\
5523 tryDig()\
5524 turtle.turnLeft()\
5525 \
5526 if n<length then\
5527 tryDig()\
5528 if not tryForward() then\
5529 print( \"Aborting Tunnel.\" )\
5530 break\
5531 end\
5532 else\
5533 print( \"Tunnel complete.\" )\
5534 end\
5535\
5536end\
5537\
5538--[[\
5539print( \"Returning to start...\" )\
5540\
5541-- Return to where we started\
5542turtle.turnLeft()\
5543turtle.turnLeft()\
5544while depth > 0 do\
5545 if turtle.forward() then\
5546 depth = depth - 1\
5547 else\
5548 turtle.dig()\
5549 end\
5550end\
5551turtle.turnRight()\
5552turtle.turnRight()\
5553]]\
5554\
5555print( \"Tunnel complete.\" )\
5556print( \"Mined \"..collected..\" items total.\" )",["dance"]="\
5557local tMoves = {\
5558 function()\
5559 turtle.up()\
5560 turtle.down()\
5561 end,\
5562 function()\
5563 turtle.up()\
5564 turtle.turnLeft()\
5565 turtle.turnLeft()\
5566 turtle.turnLeft()\
5567 turtle.turnLeft()\
5568 turtle.down()\
5569 end,\
5570 function()\
5571 turtle.up()\
5572 turtle.turnRight()\
5573 turtle.turnRight()\
5574 turtle.turnRight()\
5575 turtle.turnRight()\
5576 turtle.down()\
5577 end,\
5578 function()\
5579 turtle.turnLeft()\
5580 turtle.turnLeft()\
5581 turtle.turnLeft()\
5582 turtle.turnLeft()\
5583 end,\
5584 function()\
5585 turtle.turnRight()\
5586 turtle.turnRight()\
5587 turtle.turnRight()\
5588 turtle.turnRight()\
5589 end,\
5590 function()\
5591 turtle.turnLeft()\
5592 turtle.back()\
5593 turtle.back()\
5594 turtle.turnRight()\
5595 turtle.turnRight()\
5596 turtle.back()\
5597 turtle.back()\
5598 turtle.turnLeft()\
5599 end,\
5600 function()\
5601 turtle.turnRight()\
5602 turtle.back()\
5603 turtle.back()\
5604 turtle.turnLeft()\
5605 turtle.turnLeft()\
5606 turtle.back()\
5607 turtle.back()\
5608 turtle.turnRight()\
5609 end,\
5610 function()\
5611 turtle.back()\
5612 turtle.turnLeft()\
5613 turtle.back()\
5614 turtle.turnLeft()\
5615 turtle.back()\
5616 turtle.turnLeft()\
5617 turtle.back()\
5618 turtle.turnLeft()\
5619 end,\
5620 function()\
5621 turtle.back()\
5622 turtle.turnRight()\
5623 turtle.back()\
5624 turtle.turnRight()\
5625 turtle.back()\
5626 turtle.turnRight()\
5627 turtle.back()\
5628 turtle.turnRight()\
5629 end,\
5630}\
5631\
5632textutils.slowWrite( \"Preparing to get down\" )\
5633textutils.slowPrint( \"...\", 1 )\
5634\
5635local sAudioSide = nil\
5636for n,sSide in pairs( peripheral.getNames() ) do\
5637 if disk.hasAudio( sSide ) then\
5638 disk.playAudio( sSide )\
5639 print( \"Jamming to \"..disk.getAudioTitle( sSide ) )\
5640 sAudioSide = sSide\
5641 break\
5642 end\
5643end\
5644\
5645print( \"Press any key to stop the groove\" )\
5646\
5647local bEnd = false\
5648parallel.waitForAll(\
5649 function()\
5650 while not bEnd do\
5651 local event, key = os.pullEvent(\"key\")\
5652 if key ~= keys.escape then\
5653 bEnd = true\
5654 end\
5655 end \
5656 end,\
5657 function()\
5658 while not bEnd do\
5659 local fnMove = tMoves[math.random(1,#tMoves)]\
5660 fnMove()\
5661 end\
5662 end\
5663)\
5664\
5665if sAudioSide then\
5666 disk.stopAudio( sAudioSide )\
5667end",["craft"]="\
5668if not turtle.craft then\
5669 print( \"Requires a Crafty Turtle\" )\
5670 return\
5671end\
5672\
5673local tArgs = { ... }\
5674local nLimit = nil\
5675if #tArgs < 1 then\
5676 print( \"Usage: craft [number]\" )\
5677 return\
5678else\
5679 nLimit = tonumber( tArgs[1] )\
5680end\
5681\
5682local nEmptySlot = nil\
5683for n=1,16 do\
5684 if turtle.getItemCount(n) == 0 then\
5685 nEmptySlot = n\
5686 turtle.select(nEmptySlot)\
5687 break\
5688 end\
5689end\
5690\
5691if nEmptySlot and turtle.craft( nLimit ) then\
5692 local nCount = turtle.getItemCount(nEmptySlot)\
5693 print( nCount..\" items crafted\" )\
5694else\
5695 print( \"No items crafted\" )\
5696end\
5697turtle.select(1)",["refuel"]="\
5698local tArgs = { ... }\
5699local nLimit = 1\
5700if #tArgs > 1 then\
5701 print( \"Usage: refuel [number]\" )\
5702 return\
5703elseif #tArgs > 0 then\
5704 if tArgs[1] == \"all\" then\
5705 nLimit = 64 * 16\
5706 else\
5707 nLimit = tonumber( tArgs[1] )\
5708 end\
5709end\
5710\
5711if turtle.getFuelLevel() ~= \"unlimited\" then\
5712 for n=1,16 do\
5713 local nCount = turtle.getItemCount(n)\
5714 if nCount > 0 then\
5715 turtle.select( n )\
5716 if nCount >= nLimit then\
5717 if turtle.refuel( nLimit ) then\
5718 break \
5719 end\
5720 else\
5721 if turtle.refuel( nCount ) then\
5722 nLimit = nLimit - nCount\
5723 end\
5724 end\
5725 end\
5726 end\
5727end\
5728\
5729print( \"Fuel level is \"..turtle.getFuelLevel() )",["turn"]="local tArgs = { ... }\
5730if #tArgs < 1 then\
5731 print( \"Usage: turn <direction> <turns>\" )\
5732 return\
5733end\
5734\
5735local tHandlers = {\
5736 [\"lt\"] = turtle.turnLeft,\
5737 [\"left\"] = turtle.turnLeft,\
5738 [\"rt\"] = turtle.turnRight,\
5739 [\"right\"] = turtle.turnRight,\
5740}\
5741\
5742local nArg = 1\
5743while nArg <= #tArgs do\
5744 local sDirection = tArgs[nArg]\
5745 local nDistance = 1\
5746 if nArg < #tArgs then\
5747 local num = tonumber( tArgs[nArg + 1] )\
5748 if num then\
5749 nDistance = num\
5750 nArg = nArg + 1\
5751 end\
5752 end\
5753 nArg = nArg + 1\
5754\
5755 local fnHandler = tHandlers[string.lower(sDirection)]\
5756 if fnHandler then\
5757 for n=1,nDistance do\
5758 fnHandler( nArg )\
5759 end\
5760 else\
5761 print( \"No such direction: \"..sDirection )\
5762 print( \"Try: left, right\" )\
5763 return\
5764 end\
5765 \
5766end",},["type"]="\
5767local tArgs = { ... }\
5768if #tArgs < 1 then\
5769 print( \"Usage: type <path>\" )\
5770 return\
5771end\
5772\
5773local sPath = shell.resolve( tArgs[1] )\
5774if fs.exists( sPath ) then\
5775 if fs.isDir( sPath ) then\
5776 print( \"directory\" )\
5777 else\
5778 print( \"file\" )\
5779 end\
5780else\
5781 print( \"No such path\" )\
5782end\
5783",["mkdir"]="local tArgs = { ... }\
5784if #tArgs < 1 then\
5785 print( \"Usage: mkdir <path>\" )\
5786 return\
5787end\
5788\
5789local sNewDir = shell.resolve( tArgs[1] )\
5790fs.makeDir( sNewDir )\
5791",["cd"]="\
5792local tArgs = { ... }\
5793if #tArgs < 1 then\
5794 print( \"Usage: cd <path>\" )\
5795 return\
5796end\
5797\
5798local sNewDir = shell.resolve( tArgs[1] )\
5799if fs.isDir( sNewDir ) then\
5800 shell.setDir( sNewDir )\
5801else\
5802 print( \"Not a directory\" )\
5803 return\
5804end",["label"]="\
5805local function printUsage()\
5806 print( \"Usages:\" )\
5807 print( \"label get\" )\
5808 print( \"label set <text>\" )\
5809 print( \"label clear\" )\
5810 print( \"label get <drive>\" )\
5811 print( \"label set <drive> <text>\" )\
5812 print( \"label clear <drive>\" )\
5813end\
5814\
5815-- Get arguments\
5816local tArgs = { ... }\
5817if #tArgs == 0 then\
5818 printUsage()\
5819 return\
5820end\
5821\
5822local sCommand = nil\
5823local sDrive = nil\
5824if #tArgs == 1 then\
5825 sCommand = tArgs[1]\
5826 sDrive = nil\
5827else\
5828 sCommand = tArgs[1]\
5829 local tSides = peripheral.getNames()\
5830 for n,sSide in ipairs( tSides ) do\
5831 if sSide == tArgs[2] then\
5832 sDrive = sSide\
5833 break\
5834 end\
5835 end\
5836end\
5837\
5838if sDrive ~= nil then\
5839 -- Check the disk exists\
5840 local bData = disk.hasData( sDrive )\
5841 if not bData then\
5842 print( \"No disk in \"..sDrive..\" drive\" )\
5843 return\
5844 end\
5845end\
5846\
5847-- Do commands\
5848if sCommand == \"get\" then\
5849 -- Get the label\
5850 local sLabel\
5851 if sDrive ~= nil then\
5852 sLabel = disk.getLabel( sDrive )\
5853 if sLabel then\
5854 print( \"Disk label is \\\"\"..sLabel..\"\\\"\" )\
5855 else\
5856 print( \"No Disk label\" )\
5857 end\
5858 else\
5859 sLabel = os.getComputerLabel()\
5860 if sLabel then\
5861 print( \"Computer label is \\\"\"..sLabel..\"\\\"\" )\
5862 else\
5863 print( \"No Computer label\" )\
5864 end\
5865 end\
5866 \
5867elseif sCommand == \"set\" or sCommand == \"clear\" then\
5868 -- Set the label\
5869 local sText = nil\
5870 local nFirstArg = 2\
5871 if sDrive ~= nil then\
5872 nFirstArg = 3\
5873 end\
5874 \
5875 if sCommand == \"set\" and #tArgs >= nFirstArg then\
5876 -- Build the label from input\
5877 sText = \"\"\
5878 for n = nFirstArg, #tArgs do\
5879 sText = sText..tArgs[n]..\" \"\
5880 end\
5881 end\
5882 \
5883 local sLabel = nil\
5884 if sDrive ~= nil then\
5885 disk.setLabel( sDrive, sText )\
5886 sLabel = disk.getLabel( sDrive )\
5887 if sLabel then\
5888 print( \"Disk label set to \\\"\"..sLabel..\"\\\"\" )\
5889 else\
5890 print( \"Disk label cleared\" )\
5891 end\
5892 else\
5893 os.setComputerLabel( sText )\
5894 sLabel = os.getComputerLabel()\
5895 if sLabel then\
5896 print( \"Computer label set to \\\"\"..sLabel..\"\\\"\" )\
5897 else\
5898 print( \"Computer label cleared\" )\
5899 end\
5900 end\
5901\
5902else\
5903 -- Unknown command\
5904 printUsage()\
5905 return\
5906 \
5907end",["apis"]="\
5908local tApis = {}\
5909for k,v in pairs( _G ) do\
5910 if type(k) == \"string\" and type(v) == \"table\" and k ~= \"_G\" then\
5911 table.insert( tApis, k )\
5912 end\
5913end\
5914table.insert( tApis, \"shell\" )\
5915table.sort( tApis )\
5916\
5917textutils.pagedTabulate( tApis )",["drive"]="local tArgs = { ... }\
5918\
5919-- Get where a directory is mounted\
5920local sPath = shell.dir()\
5921if tArgs[1] ~= nil then\
5922 sPath = shell.resolve( tArgs[1] )\
5923end\
5924\
5925if fs.exists( sPath ) then\
5926 write( fs.getDrive( sPath ) .. \" (\" )\
5927 local nSpace = fs.getFreeSpace( sPath )\
5928 if nSpace > 1024 * 1024 then\
5929 print( (math.floor( nSpace / (100 * 1000) ) / 10) .. \"MB remaining)\" )\
5930 elseif nSpace > 1024 then\
5931 print( math.floor( nSpace / 1000 ) .. \"KB remaining)\" )\
5932 else\
5933 print ( nSpace .. \"B remaining)\" )\
5934 end\
5935else\
5936 print( \"No such path\" )\
5937end",["help"]="tArgs = { ... }\
5938if #tArgs > 0 then\
5939 sTopic = tArgs[1]\
5940else\
5941 sTopic = \"intro\"\
5942end\
5943\
5944if sTopic == \"index\" then\
5945 print( \"Help topics availiable:\" )\
5946 local tTopics = help.topics()\
5947 textutils.pagedTabulate( tTopics )\
5948 return\
5949end\
5950 \
5951local w,h = term.getSize()\
5952local sFile = help.lookup( sTopic )\
5953local file = ((sFile ~= nil) and io.open( sFile )) or nil\
5954local nLinesPrinted = 0\
5955if file then\
5956 local sLine = file:read()\
5957 local nLines = 0\
5958 while sLine do\
5959 nLines = nLines + textutils.pagedPrint( sLine, (h-3) - nLines )\
5960 sLine = file:read()\
5961 end\
5962 file:close()\
5963else\
5964 print( \"No help available\" )\
5965end",["reboot"]="if term.isColour() then\
5966 term.setTextColour( colours.yellow )\
5967end\
5968print( \"Goodbye\" )\
5969term.setTextColour( colours.white )\
5970\
5971sleep( 1 )\
5972os.reboot()",["redprobe"]="\
5973-- Regular input\
5974print( \"Redstone inputs: \" )\
5975\
5976local count = 0\
5977local bundledCount = 0\
5978for n,sSide in ipairs( redstone.getSides() ) do\
5979 if redstone.getBundledInput( sSide ) > 0 then\
5980 bundledCount = bundledCount + 1\
5981 end\
5982 if redstone.getInput( sSide ) then\
5983 if count > 0 then\
5984 io.write( \", \" )\
5985 end\
5986 io.write( sSide )\
5987 count = count + 1\
5988 end\
5989end\
5990\
5991if count > 0 then\
5992 print( \".\" )\
5993else\
5994 print( \"None.\" )\
5995end\
5996\
5997-- Bundled input\
5998if bundledCount > 0 then\
5999 print()\
6000 print( \"Bundled inputs:\" )\
6001 for i,sSide in ipairs( redstone.getSides() ) do\
6002 if redstone.getBundledInput( sSide ) > 0 then\
6003 write( sSide..\" = \"..redstone.getBundledInput( sSide )..\" (\" )\
6004\
6005 local count = 0\
6006 for sColour,nColour in pairs( colors ) do\
6007 if type( nColour ) == \"number\" and \
6008 redstone.testBundledInput( sSide, nColour ) then\
6009 if count > 0 then\
6010 write( \" + \" )\
6011 end\
6012 if term.isColour() then\
6013 term.setTextColour( nColour )\
6014 end\
6015 write( sColour )\
6016 if term.isColour() then\
6017 term.setTextColour( colours.white )\
6018 end\
6019 count = count + 1\
6020 end\
6021 end\
6022 print( \")\" )\
6023 end\
6024 end\
6025end",["clear"]="term.clear()\
6026term.setCursorPos( 1, 1 )",["id"]="\
6027local sSide = nil\
6028local tArgs = { ... }\
6029if #tArgs > 0 then\
6030 sSide = tostring( tArgs[1] )\
6031end\
6032\
6033if sSide == nil then\
6034 print( \"This is computer #\"..os.getComputerID() )\
6035 \
6036 local label = os.getComputerLabel()\
6037 if label then\
6038 print( \"This computer is labelled \\\"\"..label..\"\\\"\" )\
6039 end\
6040\
6041else\
6042 local bData = disk.hasData( sSide )\
6043 if not bData then\
6044 print( \"No disk in \"..sSide..\" disk drive\" )\
6045 return\
6046 end\
6047 \
6048 print( \"The disk is #\"..disk.getID( sSide ) )\
6049\
6050 local label = disk.getLabel( sSide )\
6051 if label then\
6052 print( \"The disk is labelled \\\"\"..label..\"\\\"\" )\
6053 end\
6054end\
6055",["color"]={["paint"]="-- Paint created by nitrogenfingers (edited by dan200)\
6056-- http://www.youtube.com/user/NitrogenFingers\
6057\
6058------------\
6059-- Fields --\
6060------------\
6061\
6062-- The width and height of the terminal\
6063local w,h = term.getSize()\
6064\
6065-- The selected colours on the left and right mouse button, and the colour of the canvas\
6066local leftColour, rightColour = colours.black, colours.white\
6067local canvasColour = colours.white\
6068\
6069-- The values stored in the canvas\
6070local canvas = {}\
6071\
6072-- The menu options\
6073local mChoices = { \"Save\",\"Exit\" }\
6074\
6075-- The message displayed in the footer bar\
6076local fMessage = \"Press Ctrl to access menu\"\
6077\
6078-------------------------\
6079-- Initialisation --\
6080-------------------------\
6081\
6082-- Determine if we can even run this\
6083if not term.isColour() then\
6084 print(\"Requires an Advanced Computer\")\
6085 return\
6086end\
6087\
6088-- Determines if the file exists, and can be edited on this computer\
6089local tArgs = {...}\
6090if #tArgs == 0 then\
6091 print(\"Usage: paint <path>\")\
6092 return\
6093end\
6094local sPath = shell.resolve(tArgs[1])\
6095local bReadOnly = fs.isReadOnly(sPath)\
6096if fs.exists(sPath) and fs.isDir(sPath) then\
6097 print(\"Cannot edit a directory.\")\
6098 return\
6099end\
6100\
6101---------------\
6102-- Functions --\
6103---------------\
6104\
6105--[[\
6106 Converts a colour value to a text character\
6107 params: colour = the number to convert to a hex value\
6108 returns: a string representing the chosen colour\
6109]]\
6110local function getCharOf( colour )\
6111 -- Incorrect values always convert to nil\
6112 if type(colour) == \"number\" then\
6113 local value = math.floor( math.log(colour) / math.log(2) ) + 1\
6114 if value >= 1 and value <= 16 then\
6115 return string.sub( \"0123456789abcdef\", value, value )\
6116 end\
6117 end\
6118 return \" \"\
6119end \
6120\
6121--[[\
6122 Converts a text character to colour value\
6123 params: char = the char (from string.byte) to convert to number\
6124 returns: the colour number of the hex value\
6125]]\
6126local tColourLookup = {}\
6127for n=1,16 do\
6128 tColourLookup[ string.byte( \"0123456789abcdef\",n,n ) ] = 2^(n-1)\
6129end\
6130local function getColourOf( char )\
6131 -- Values not in the hex table are transparent (canvas coloured)\
6132 return tColourLookup[char]\
6133end\
6134\
6135--[[ \
6136 Loads the file into the canvas\
6137 params: path = the path of the file to open\
6138 returns: nil\
6139]]\
6140local function load(path)\
6141 -- Load the file\
6142 if fs.exists(path) then\
6143 local file = io.open(sPath, \"r\" )\
6144 local sLine = file:read()\
6145 while sLine do\
6146 local line = {}\
6147 for x=1,w-2 do\
6148 line[x] = getColourOf( string.byte(sLine,x,x) )\
6149 end\
6150 table.insert( canvas, line )\
6151 sLine = file:read()\
6152 end\
6153 file:close()\
6154 end\
6155 \
6156 -- Any extra space is filled in here\
6157 local lineCount = #canvas\
6158 for i=lineCount+1, h-1 do\
6159 table.insert( canvas, {} )\
6160 end\
6161end\
6162\
6163--[[ \
6164 Saves the current canvas to file \
6165 params: path = the path of the file to save\
6166 returns: true if save was successful, false otherwise\
6167]]\
6168local function save(path)\
6169 local sDir = string.sub(sPath, 1, #sPath - #fs.getName(sPath))\
6170 if not fs.exists(sDir) then\
6171 fs.makeDir(sDir)\
6172 end\
6173\
6174 local file = io.open(path, \"w\")\
6175 if not file then return false end\
6176 for y=1,h-1 do\
6177 for x=1,w-2 do\
6178 file:write( getCharOf( canvas[y][x] ) )\
6179 end\
6180 file:write( \"\\n\" )\
6181 end\
6182 file:close()\
6183 return true\
6184end\
6185\
6186--[[ \
6187 Draws colour picker sidebar, the pallette and the footer\
6188 returns: nil\
6189]]\
6190local function drawInterface()\
6191 -- Footer\
6192 term.setCursorPos(1, h)\
6193 term.setBackgroundColour(colours.lightGrey)\
6194 term.setTextColour(colours.white)\
6195 term.clearLine()\
6196 term.write(fMessage)\
6197 \
6198 -- Colour Picker\
6199 for i=1,16 do\
6200 term.setCursorPos(w-1, i)\
6201 term.setBackgroundColour( 2^(i-1) )\
6202 term.write(\" \")\
6203 end\
6204\
6205 term.setCursorPos(w-1, 17)\
6206 term.setBackgroundColour( canvasColour )\
6207 term.setTextColour( colours.lightGrey )\
6208 term.write(\"XX\")\
6209 \
6210 -- Left and Right Selected Colours\
6211 for i=18,18 do\
6212 term.setCursorPos(w-1, i)\
6213 if leftColour ~= nil then\
6214 term.setBackgroundColour( leftColour )\
6215 term.write(\" \")\
6216 else\
6217 term.setBackgroundColour( canvasColour )\
6218 term.setTextColour( colours.lightGrey )\
6219 term.write(\"X\")\
6220 end\
6221 if rightColour ~= nil then\
6222 term.setBackgroundColour( rightColour )\
6223 term.write(\" \")\
6224 else\
6225 term.setBackgroundColour( canvasColour )\
6226 term.setTextColour( colours.lightGrey )\
6227 term.write(\"X\")\
6228 end\
6229 end\
6230\
6231 -- Padding\
6232 term.setBackgroundColour(colours.lightGrey)\
6233 for i=20,h-1 do\
6234 term.setCursorPos(w-1, i)\
6235 term.write(\" \")\
6236 end\
6237end\
6238\
6239--[[ \
6240 Converts a single pixel of a single line of the canvas and draws it\
6241 returns: nil\
6242]]\
6243local function drawCanvasPixel( x, y )\
6244 local pixel = canvas[y][x]\
6245 if pixel then\
6246 term.setBackgroundColour( pixel or canvasColour )\
6247 term.setCursorPos(x, y)\
6248 term.write(\" \")\
6249 else\
6250 term.setBackgroundColour( canvasColour )\
6251 term.setTextColour( colours.lightGrey )\
6252 term.setCursorPos(x, y)\
6253 if leftColour == nil or rightColour == nil then\
6254 term.write(\"-\")\
6255 else\
6256 term.write(\" \")\
6257 end\
6258 end\
6259end\
6260\
6261--[[ \
6262 Converts each colour in a single line of the canvas and draws it\
6263 returns: nil\
6264]]\
6265local function drawCanvasLine( y )\
6266 local line = canvas[y]\
6267 for x = 1, w-2 do\
6268 drawCanvasPixel( x, y )\
6269 end\
6270end\
6271\
6272--[[ \
6273 Converts each colour in the canvas and draws it\
6274 returns: nil\
6275]]\
6276local function drawCanvas()\
6277 for y = 1, #canvas do\
6278 drawCanvasLine( y )\
6279 end\
6280end\
6281\
6282--[[\
6283 Draws menu options and handles input from within the menu.\
6284 returns: true if the program is to be exited; false otherwise\
6285]]\
6286local function accessMenu()\
6287 -- Selected menu option\
6288 local selection = 1\
6289 \
6290 term.setBackgroundColour(colours.lightGrey)\
6291 while true do\
6292 -- Draw the menu\
6293 term.setCursorPos(1,h)\
6294 term.clearLine()\
6295 term.setTextColour(colours.white)\
6296 for k,v in pairs(mChoices) do\
6297 if selection==k then \
6298 term.setTextColour(colours.yellow)\
6299 local ox,_ = term.getCursorPos()\
6300 term.write(\"[\"..string.rep(\" \",#v)..\"]\")\
6301 term.setCursorPos(ox+1,h)\
6302 term.setTextColour(colours.white)\
6303 term.write(v)\
6304 term.setCursorPos(term.getCursorPos()+1,h)\
6305 else\
6306 term.write(\" \"..v..\" \")\
6307 end\
6308 end\
6309 \
6310 -- Handle input in the menu\
6311 local id,key = os.pullEvent(\"key\")\
6312 if id == \"key\" then\
6313 -- S and E are shortcuts\
6314 if key == keys.s then\
6315 selection = 1\
6316 key = keys.enter\
6317 elseif key == keys.e then\
6318 selection = 2\
6319 key = keys.enter\
6320 end\
6321 \
6322 if key == keys.right then\
6323 -- Move right\
6324 selection = selection + 1\
6325 if selection > #mChoices then\
6326 selection = 1\
6327 end\
6328 \
6329 elseif key == keys.left and selection > 1 then\
6330 -- Move left\
6331 selection = selection - 1\
6332 if selection < 1 then\
6333 selection = #mChoices\
6334 end\
6335 \
6336 elseif key == keys.enter then\
6337 -- Select an option\
6338 if mChoices[selection]==\"Save\" then \
6339 if bReadOnly then \
6340 fMessage = \"Access Denied\"\
6341 return false\
6342 end\
6343 local success = save(sPath)\
6344 if success then\
6345 fMessage = \"Saved to \"..sPath\
6346 else\
6347 fMessage = \"Error saving to \"..sPath\
6348 end\
6349 return false\
6350 elseif mChoices[selection]==\"Exit\" then \
6351 return true\
6352 end\
6353 elseif key == keys.leftCtrl or keys == keys.rightCtrl then\
6354 -- Cancel the menu\
6355 return false \
6356 end\
6357 end\
6358 end\
6359end\
6360\
6361--[[ \
6362 Runs the main thread of execution. Draws the canvas and interface, and handles\
6363 mouse and key events.\
6364 returns: nil\
6365]]\
6366local function handleEvents()\
6367 local programActive = true\
6368 while programActive do\
6369 local id,p1,p2,p3 = os.pullEvent()\
6370 if id==\"mouse_click\" or id==\"mouse_drag\" then\
6371 if p2 >= w-1 and p3 >= 1 and p3 <= 17 then\
6372 if id ~= \"mouse_drag\" then\
6373 -- Selecting an items in the colour picker\
6374 if p3 <= 16 then\
6375 if p1==1 then\
6376 leftColour = 2^(p3-1)\
6377 else\
6378 rightColour = 2^(p3-1)\
6379 end\
6380 else\
6381 if p1==1 then\
6382 leftColour = nil\
6383 else\
6384 rightColour = nil\
6385 end\
6386 end\
6387 drawCanvas()\
6388 drawInterface()\
6389 end\
6390 elseif p2 < w-1 and p3 <= h-1 then\
6391 -- Clicking on the canvas\
6392 local paintColour = nil\
6393 if p1==1 then\
6394 paintColour = leftColour\
6395 elseif p1==2 then\
6396 paintColour = rightColour\
6397 end\
6398 \
6399 canvas[p3][p2] = paintColour\
6400 drawCanvasPixel( p2, p3 )\
6401 end\
6402 elseif id==\"key\" then\
6403 if p1==keys.leftCtrl or p1==keys.rightCtrl then\
6404 programActive = not accessMenu()\
6405 drawInterface()\
6406 end\
6407 end\
6408 end\
6409end\
6410\
6411-- Init\
6412load(sPath)\
6413drawCanvas()\
6414drawInterface()\
6415\
6416-- Main loop\
6417handleEvents()\
6418\
6419-- Shutdown\
6420term.setBackgroundColour(colours.black)\
6421term.setTextColour(colours.white)\
6422term.clear()\
6423term.setCursorPos(1,1)",},["dj"]="local tArgs = { ... }\
6424\
6425local function printUsage()\
6426 print( \"Usages:\")\
6427 print( \"dj play\" )\
6428 print( \"dj play <side>\" )\
6429 print( \"dj stop\" )\
6430end\
6431\
6432if #tArgs > 2 then\
6433 printUsage()\
6434 return\
6435end\
6436\
6437local sCommand = tArgs[1]\
6438if sCommand == \"stop\" then\
6439 -- Stop audio\
6440 disk.stopAudio()\
6441\
6442elseif sCommand == \"play\" or sCommand == nil then\
6443 -- Play audio\
6444 local sSide = tArgs[2]\
6445 if sSide == nil then\
6446 -- No disc specified, pick one at random\
6447 local tSides = {}\
6448 for n,sSide in ipairs( peripheral.getNames() ) do\
6449 if disk.isPresent( sSide ) and disk.hasAudio( sSide ) then\
6450 table.insert( tSides, sSide )\
6451 end\
6452 end\
6453 if #tSides == 0 then\
6454 print( \"No Music Discs in attached disk drives\" )\
6455 return\
6456 end\
6457 sSide = tSides[ math.random(1,#tSides) ]\
6458 end\
6459\
6460 -- Play the disc\
6461 if disk.isPresent( sSide ) and disk.hasAudio( sSide ) then\
6462 print( \"Playing \"..disk.getAudioTitle( sSide ) )\
6463 disk.playAudio( sSide )\
6464 else\
6465 print( \"No Music Disc in \"..sSide..\" disk drive\" )\
6466 return\
6467 end\
6468 \
6469else\
6470 printUsage()\
6471 \
6472end",["redset"]="\
6473local tArgs = { ... }\
6474if #tArgs == 0 or #tArgs > 3 then\
6475 print(\"Usages:\")\
6476 print(\"redset <side> <true/false>\")\
6477 print(\"redset <side> <number>\")\
6478 print(\"redset <side> <color> <true/false>\")\
6479 return\
6480end\
6481\
6482local sSide = tArgs[1]\
6483if #tArgs == 2 then\
6484 local value = tArgs[2]\
6485 if tonumber(value) ~= nil then\
6486 redstone.setBundledOutput( sSide, tonumber(value) )\
6487 elseif value == \"true\" or value == \"false\" then\
6488 redstone.setOutput( sSide, value == \"true\" )\
6489 else\
6490 print( \"Value must be a number or true/false\" )\
6491 return\
6492 end\
6493 \
6494else\
6495 local sColour = tArgs[2]\
6496 local nColour = colors[sColour] or colours[sColour]\
6497 if type(nColour) ~= \"number\" then\
6498 print( \"No such color\" )\
6499 return\
6500 end\
6501 \
6502 local sValue = tArgs[3]\
6503 if sValue == \"true\" then\
6504 rs.setBundledOutput( sSide, colors.combine( rs.getBundledOutput( sSide ), nColour ) )\
6505 elseif sValue == \"false\" then\
6506 rs.setBundledOutput( sSide, colors.subtract( rs.getBundledOutput( sSide ), nColour ) )\
6507 else\
6508 print( \"Value must be true/false\" )\
6509 return\
6510 end\
6511end",["redpulse"]="\
6512local tArgs = { ... }\
6513local sSide = tArgs[1]\
6514if not sSide then\
6515 print(\"Usage: redpulse <side> <count> <period>\")\
6516 return\
6517end\
6518\
6519local nCount = tonumber(tArgs[2]) or 1\
6520local nPeriod = tonumber(tArgs[3]) or 0.5\
6521\
6522for n=1,nCount do\
6523 redstone.setOutput( sSide, true )\
6524 sleep( nPeriod / 2 )\
6525 redstone.setOutput( sSide, false )\
6526 sleep( nPeriod / 2 )\
6527end",["http"]={["pastebin"]="\
6528local function printUsage()\
6529 print( \"Usages:\" )\
6530 print( \"pastebin put <filename>\" )\
6531 print( \"pastebin get <code> <filename>\" )\
6532 print( \"pastebin run <code> <arguments>\" )\
6533end\
6534 \
6535local tArgs = { ... }\
6536if #tArgs < 2 then\
6537 printUsage()\
6538 return\
6539end\
6540 \
6541if not http then\
6542 printError( \"Pastebin requires http API\" )\
6543 printError( \"Set enableAPI_http to true in ComputerCraft.cfg\" )\
6544 return\
6545end\
6546 \
6547local function get(paste)\
6548 write( \"Connecting to pastebin.com... \" )\
6549 local response = http.get(\
6550 \"http://pastebin.com/raw.php?i=\"..textutils.urlEncode( paste )\
6551 )\
6552 \
6553 if response then\
6554 print( \"Success.\" )\
6555 \
6556 local sResponse = response.readAll()\
6557 response.close()\
6558 return sResponse\
6559 else\
6560 printError( \"Failed.\" )\
6561 end\
6562end\
6563 \
6564local sCommand = tArgs[1]\
6565if sCommand == \"put\" then\
6566 -- Upload a file to pastebin.com\
6567 -- Determine file to upload\
6568 local sFile = tArgs[2]\
6569 local sPath = shell.resolve( sFile )\
6570 if not fs.exists( sPath ) or fs.isDir( sPath ) then\
6571 print( \"No such file\" )\
6572 return\
6573 end\
6574 \
6575 -- Read in the file\
6576 local sName = fs.getName( sPath )\
6577 local file = fs.open( sPath, \"r\" )\
6578 local sText = file.readAll()\
6579 file.close()\
6580 \
6581 -- POST the contents to pastebin\
6582 write( \"Connecting to pastebin.com... \" )\
6583 local key = \"0ec2eb25b6166c0c27a394ae118ad829\"\
6584 local response = http.post(\
6585 \"http://pastebin.com/api/api_post.php\", \
6586 \"api_option=paste&\"..\
6587 \"api_dev_key=\"..key..\"&\"..\
6588 \"api_paste_format=lua&\"..\
6589 \"api_paste_name=\"..textutils.urlEncode(sName)..\"&\"..\
6590 \"api_paste_code=\"..textutils.urlEncode(sText)\
6591 )\
6592 \
6593 if response then\
6594 print( \"Success.\" )\
6595 \
6596 local sResponse = response.readAll()\
6597 response.close()\
6598 \
6599 local sCode = string.match( sResponse, \"[^/]+$\" )\
6600 print( \"Uploaded as \"..sResponse )\
6601 print( \"Run \\\"pastebin get \"..sCode..\"\\\" to download anywhere\" )\
6602 \
6603 else\
6604 print( \"Failed.\" )\
6605 end\
6606 \
6607elseif sCommand == \"get\" then\
6608 -- Download a file from pastebin.com\
6609 if #tArgs < 3 then\
6610 printUsage()\
6611 return\
6612 end\
6613 \
6614 -- Determine file to download\
6615 local sCode = tArgs[2]\
6616 local sFile = tArgs[3]\
6617 local sPath = shell.resolve( sFile )\
6618 if fs.exists( sPath ) then\
6619 print( \"File already exists\" )\
6620 return\
6621 end\
6622 \
6623 -- GET the contents from pastebin\
6624 local res = get(sCode)\
6625 if res then \
6626 local file = fs.open( sPath, \"w\" )\
6627 file.write( res )\
6628 file.close()\
6629 \
6630 print( \"Downloaded as \"..sFile )\
6631 end \
6632elseif sCommand == \"run\" then\
6633 local sCode = tArgs[2]\
6634 \
6635 local res = get(sCode)\
6636 if res then\
6637 local func, err = loadstring(res)\
6638 if not func then\
6639 printError( err )\
6640 return\
6641 end\
6642 setfenv(func, getfenv())\
6643 local success, msg = pcall(func, unpack(tArgs, 3))\
6644 if not success then\
6645 printError( msg )\
6646 end\
6647 end\
6648else\
6649 printUsage()\
6650 return\
6651end",},},["startup"]="\
6652local sPath = \".:/rom/programs\"\
6653if turtle then\
6654 sPath = sPath..\":/rom/programs/turtle\"\
6655else\
6656 sPath = sPath..\":/rom/programs/computer\"\
6657end\
6658if http then\
6659 sPath = sPath..\":/rom/programs/http\"\
6660end\
6661if term.isColor() then\
6662 sPath = sPath..\":/rom/programs/color\"\
6663end\
6664\
6665shell.setPath( sPath )\
6666help.setPath( \"/rom/help\" )\
6667\
6668shell.setAlias( \"ls\", \"list\" )\
6669shell.setAlias( \"dir\", \"list\" )\
6670shell.setAlias( \"cp\", \"copy\" )\
6671shell.setAlias( \"mv\", \"move\" )\
6672shell.setAlias( \"rm\", \"delete\" )\
6673shell.setAlias( \"preview\", \"edit\" )\
6674\
6675if fs.exists( \"/rom/autorun\" ) and fs.isDir( \"/rom/autorun\" ) then\
6676 local tFiles = fs.list( \"/rom/autorun\" )\
6677 table.sort( tFiles )\
6678 for n, sFile in ipairs( tFiles ) do\
6679 if string.sub( sFile, 1, 1 ) ~= \".\" then\
6680 local sPath = \"/rom/autorun/\"..sFile\
6681 if not fs.isDir( sPath ) then\
6682 shell.run( sPath )\
6683 end\
6684 end\
6685 end\
6686end",},["mepsloader"]="term.setCursorPos(1,1)\
6687print(\"Loading UnisOS Interface APIs\")\
6688lc=0\
6689fc=0\
6690cc=0\
6691currentCRC=\"\"\
6692calculatedCRC=\"\"\
6693for i=1,#fs.list(\"FusedAPIS\") do\
6694 fh=fs.open(\"FusedAPIS/\"..fs.list(\"FusedAPIS\")[i]..\"/info\",\"r\")\
6695 if fh then\
6696 APIname=fh.readLine()\
6697 fh.close()\
6698 if fs.exists(\"FusedAPIS/\"..fs.list(\"FusedAPIS\")[i]..\"/CRC32\") then\
6699 fh=fs.open(\"FusedAPIS/\"..fs.list(\"FusedAPIS\")[i]..\"/CRC32\",\"r\")\
6700 currentCRC=tonumber(fh.readLine())\
6701 calculatedCRC=CRC32.CRC32(\"FusedAPIS/\"..fs.list(\"FusedAPIS\")[i]..\"/\"..APIname)\
6702 fh.close()\
6703 else\
6704 currentCRC=\"Not Found\"\
6705 calculatedCRC=\"Not Found\"\
6706 end\
6707 if calculatedCRC==currentCRC then\
6708 os.loadAPI(\"FusedAPIS/\"..fs.list(\"FusedAPIS\")[i]..\"/\"..APIname)\
6709 term.setTextColor(colours.green)\
6710 print(\"Loaded API \"..fs.list(\"FusedAPIS\")[i])\
6711 term.setTextColor(colours.white)\
6712 lc=lc+1\
6713 else\
6714 term.setTextColor(colours.yellow)\
6715 print(\"NCRC32 API \"..fs.list(\"FusedAPIS\")[i])\
6716 term.setTextColor(colours.white)\
6717 cc=cc+1\
6718 end\
6719 else\
6720 term.setTextColor(colours.red)\
6721 print(\"Failed API \"..fs.list(\"FusedAPIS\")[i])\
6722 term.setTextColor(colours.white)\
6723 fc=fc+1\
6724 end\
6725end\
6726term.setTextColor(colours.green)\
6727print(\"Loaded APIs: \"..lc ..\" APIs\")\
6728term.setTextColor(colours.red)\
6729print(\"Failed APIs: \"..fc ..\" APIs\")\
6730term.setTextColor(colours.yellow)\
6731print(\"CRC32 Fails: \"..cc ..\" APIs\")\
6732term.setTextColor(colours.white)",["startup"]="os.loadAPI(\"daemon\")\
6733term.clear()\
6734os.loadAPI(\"CRC32\")\
6735shell.run(\"mepsloader\")",["checkCRC32"]="tArgs={...}\
6736print(\"Calculating CRC32 on \"..tArgs[1])\
6737result=CRC32.CRC32(tArgs[1])\
6738print(\"CRC32 is \"..result)\
6739fh=fs.open(tArgs[1]..\".CRC32\",\"w\")\
6740fh.writeLine(result..\"\")\
6741fh.close()",["CRC32"]="os.loadAPI(\"CRC32_\")\
6742CRCSWITCH=1\
6743constant=0x04C11DB7\
6744if CRCSWITCH==1 then\
6745constant=0x04C11DB7\
6746end\
6747if CRCSWITCH==2 then\
6748constant=0x1EDC6F41\
6749end\
6750function CRC32(filename)\
6751 --Create a HEX Table of binary data\
6752 fh_BIN=fs.open(filename,\"rb\")\
6753 dataTable={}\
6754 pointer_8231A=1\
6755 prYeild_23E=0\
6756 prYeild_23F=0\
6757 prYeild_23D=50000\
6758 while true do\
6759 if fh_BIN then\
6760 bin1DATA_9192F=fh_BIN.read()\
6761 if bin1DATA_9192F==nil then\
6762 fh_BIN.close()\
6763 break\
6764 end\
6765 dataTable[pointer_8231A]=bin1DATA_9192F\
6766 else\
6767 fh_BIN.close()\
6768 break\
6769 end\
6770 pointer_8231A=pointer_8231A+1\
6771 \
6772 prYeild_23E=prYeild_23E+1\
6773 if prYeild_23E==prYeild_23D then\
6774 sleep(0.1)\
6775 prYeild_23F=prYeild_23F+1\
6776 --print(\"| \"..prYeild_23F*prYeild_23E..\"/\"..fs.getSize(filename)..\" bytes processed [\"..math.ceil(((prYeild_23F*prYeild_23E)/fs.getSize(filename))*100) ..\"%], yeilding\")\
6777 prYeild_23E=0\
6778 end\
6779 end\
6780 sleep(0.1)\
6781 retval=CRC32_.CRC32(constant,dataTable)\
6782 return retval\
6783end",["daemon"]="local function fIter (t, i)\
6784 i = not i and #t or (i - 1)\
6785 if i>0 then\
6786 return i, t[i]\
6787 end\
6788end\
6789local tBackground = setmetatable({},{\
6790 __newindex = function(t,k,v)\
6791 v = {cRoutine=coroutine.create(v[1]),sFilter=nil,sIdentifier=v[2]}\
6792 rawset(t,k,v)\
6793 end;\
6794})\
6795function add(fFunc,sIdentifier)\
6796 tBackground[#tBackground+1] = {fFunc,sIdentifier}\
6797 return tBackground[#tBackground]\
6798end\
6799function rem(cRoutine)\
6800 cRoutine.sFilter=\"Daemon_internal_remove\"\
6801end\
6802function getBackground()\
6803 return tBackground\
6804end\
6805local bPullMeta = false\
6806function os.pullEventRaw(sEvent)\
6807 local tData\
6808 if bPullMeta then\
6809 return coroutine.yield(sEvent)\
6810 else\
6811 repeat\
6812 bPullMeta = true\
6813 tData = {coroutine.yield()}\
6814 for iIndex,cRoutine in fIter, tBackground do\
6815 if cRoutine.sFilter==tData[1] or not cRoutine.sFilter then\
6816 local bOk, sInnerEvent = coroutine.resume(cRoutine.cRoutine,unpack(tData))\
6817 if bOk then\
6818 cRoutine.sFilter = sInnerEvent\
6819 else\
6820 print(sInnerEvent)\
6821 table.remove(tBackground,iIndex)\
6822 end\
6823 elseif cRoutine.sFilter==\"Daemon_internal_remove\" then\
6824 table.remove(tBackground,iIndex)\
6825 end\
6826 end\
6827 bPullMeta = false\
6828 until tData[1] == sEvent or not sEvent\
6829 return unpack(tData)\
6830 end\
6831end",["CRC32_"]="-- **********************************************************************************************\
6832-- CRC_Calculate - Calculate a 32-bit CRC based on a given polynomial and block of data.\
6833-- This function caluclates a CRC checksum.\
6834-- Arguments:\
6835-- gen_poly - The generator polynomial. (MSB-0)\
6836-- data - A table with the data to run the CRC on.\
6837-- Returns:\
6838-- The checksum\
6839function CRC32(gen_poly, data)\
6840 prYeild_23E=0\
6841 prYeild_23F=0\
6842 prYeild_23D=10000\
6843 local remainder = 0\
6844 --print(\"| \"..#data..\" bytes to process.\")\
6845 for i=1, #data do\
6846 remainder = bit.bxor(remainder, bit.blshift(data[i], 24))\
6847 for i=1, 8 do\
6848 if (bit.band(remainder, 0x80000000) > 0) then\
6849 remainder = bit.bxor(bit.blshift(remainder,1), gen_poly)\
6850 else\
6851 remainder = bit.blshift(remainder,1)\
6852 end\
6853 end\
6854 prYeild_23E=prYeild_23E+1\
6855 if prYeild_23E==prYeild_23D then\
6856 sleep(0.1)\
6857 prYeild_23F=prYeild_23F+1\
6858 --print(\"| \"..prYeild_23F*prYeild_23E..\"/\"..#data..\" bytes processed [\"..math.ceil(((prYeild_23F*prYeild_23E)/#data)*100) ..\"%], yeilding\")\
6859 prYeild_23E=0\
6860 end\
6861 end\
6862 return remainder\
6863end\
6864\
6865-- **********************************************************************************************\
6866-- intToHex() - Convert a number to a hexadecimal string\
6867-- Arguments:\
6868-- input - The input number\
6869-- Returns:\
6870-- string output\
6871-- This function is deprecated, use string.format(\"%X\", input) instead. (Thanks to tomass1996 for pointing this out)\
6872\
6873function intToHex(input)\
6874 -- local output = {}\
6875 -- local iter = 1\
6876 -- while true do\
6877 -- output[iter] = input % 16\
6878 -- input = math.floor((input - output[iter]) / 16)\
6879 -- if(output[iter] == 10) then\
6880 -- output[iter] = \"A\"\
6881 -- elseif(output[iter] == 11) then\
6882 -- output[iter] = \"B\"\
6883 -- elseif(output[iter] == 12) then\
6884 -- output[iter] = \"C\"\
6885 -- elseif(output[iter] == 13) then\
6886 -- output[iter] = \"D\"\
6887 -- elseif(output[iter] == 14) then\
6888 -- output[iter] = \"E\"\
6889 -- elseif(output[iter] == 15) then\
6890 -- output[iter] = \"F\"\
6891 -- end\
6892 -- if ( input == 0 ) then\
6893 -- return table.concat(output)\
6894 -- end\
6895 -- iter = iter+1\
6896 -- end\
6897 return string.format(\"%X\", input)\
6898end\
6899\
6900-- **********************************************************************************************\
6901-- intToHex() - Convert a hexadecimal digit into a number TYPE (\"string\" to \"number\")\
6902-- Arguments:\
6903-- input - The input hex digit\
6904-- Returns:\
6905-- number output\
6906-- This function is deprecated, use tonumber(input, 16) instead\
6907\
6908function hexToInt(input)\
6909 -- if (tonumber(input)) then\
6910 -- return tonumber(input)\
6911 -- else\
6912 -- if(input == \"a\" or input == \"A\") then\
6913 -- return 10\
6914 -- elseif(input == \"b\" or input == \"B\") then\
6915 -- return 11\
6916 -- elseif(input == \"c\" or input == \"C\") then\
6917 -- return 12\
6918 -- elseif(input == \"d\" or input == \"D\") then\
6919 -- return 13\
6920 -- elseif(input == \"e\" or input == \"E\") then\
6921 -- return 14\
6922 -- elseif(input == \"f\" or input == \"F\") then\
6923 -- return 15\
6924 -- end\
6925 -- end\
6926 -- return -1\
6927 return tonumber(input, 16)\
6928end",["FusedAPIS"]={["cofh.thermalexpansion"]={["bigreactor"]="function init()\
6929\
6930end",["info"]="bigreactor",["CRC32"]="2554170628\
69312522408590",},["algorithmx2.appliedenergistics"]={["bigreactor"]="function init()\
6932\
6933end",["info"]="bigreactor",["CRC32"]="2554170628\
69342522408590",},["erogneousbeef.bigreactors"]={["bigreactor"]="function init()\
6935\
6936end",["info"]="bigreactor",["CRC32"]="2554170628",},},}