mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2025-10-26 19:37:39 +00:00
Relocate all resource files
- textures/{block,item}s -> textures/{block,item}
- assets/*/{advancements,lua,recipes} -> data/*/...
This commit is contained in:
1048
src/main/resources/data/computercraft/lua/bios.lua
Normal file
1048
src/main/resources/data/computercraft/lua/bios.lua
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,86 @@
|
||||
-- Colors
|
||||
white = 1
|
||||
orange = 2
|
||||
magenta = 4
|
||||
lightBlue = 8
|
||||
yellow = 16
|
||||
lime = 32
|
||||
pink = 64
|
||||
gray = 128
|
||||
lightGray = 256
|
||||
cyan = 512
|
||||
purple = 1024
|
||||
blue = 2048
|
||||
brown = 4096
|
||||
green = 8192
|
||||
red = 16384
|
||||
black = 32768
|
||||
|
||||
function combine( ... )
|
||||
local r = 0
|
||||
for n,c in ipairs( { ... } ) do
|
||||
if type( c ) ~= "number" then
|
||||
error( "bad argument #"..n.." (expected number, got " .. type( c ) .. ")", 2 )
|
||||
end
|
||||
r = bit32.bor(r,c)
|
||||
end
|
||||
return r
|
||||
end
|
||||
|
||||
function subtract( colors, ... )
|
||||
if type( colors ) ~= "number" then
|
||||
error( "bad argument #1 (expected number, got " .. type( colors ) .. ")", 2 )
|
||||
end
|
||||
local r = colors
|
||||
for n,c in ipairs( { ... } ) do
|
||||
if type( c ) ~= "number" then
|
||||
error( "bad argument #"..tostring( n+1 ).." (expected number, got " .. type( c ) .. ")", 2 )
|
||||
end
|
||||
r = bit32.band(r, bit32.bnot(c))
|
||||
end
|
||||
return r
|
||||
end
|
||||
|
||||
function test( colors, color )
|
||||
if type( colors ) ~= "number" then
|
||||
error( "bad argument #1 (expected number, got " .. type( colors ) .. ")", 2 )
|
||||
end
|
||||
if type( color ) ~= "number" then
|
||||
error( "bad argument #2 (expected number, got " .. type( color ) .. ")", 2 )
|
||||
end
|
||||
return bit32.band(colors, color) == color
|
||||
end
|
||||
|
||||
function packRGB( r, g, b )
|
||||
if type( r ) ~= "number" then
|
||||
error( "bad argument #1 (expected number, got " .. type( r ) .. ")", 2 )
|
||||
end
|
||||
if type( g ) ~= "number" then
|
||||
error( "bad argument #2 (expected number, got " .. type( g ) .. ")", 2 )
|
||||
end
|
||||
if type( b ) ~= "number" then
|
||||
error( "bad argument #3 (expected number, got " .. type( b ) .. ")", 2 )
|
||||
end
|
||||
return
|
||||
bit32.band( r * 255, 0xFF ) * 2^16 +
|
||||
bit32.band( g * 255, 0xFF ) * 2^8 +
|
||||
bit32.band( b * 255, 0xFF )
|
||||
end
|
||||
|
||||
function unpackRGB( rgb )
|
||||
if type( rgb ) ~= "number" then
|
||||
error( "bad argument #1 (expected number, got " .. type( rgb ) .. ")", 2 )
|
||||
end
|
||||
return
|
||||
bit32.band( bit32.rshift( rgb, 16 ), 0xFF ) / 255,
|
||||
bit32.band( bit32.rshift( rgb, 8 ), 0xFF ) / 255,
|
||||
bit32.band( rgb, 0xFF ) / 255
|
||||
end
|
||||
|
||||
function rgb8( r, g, b )
|
||||
if g == nil and b == nil then
|
||||
return unpackRGB( r )
|
||||
else
|
||||
return packRGB( r, g, b )
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,11 @@
|
||||
-- Colours (for lovers of british spelling)
|
||||
local colours = _ENV
|
||||
for k,v in pairs(colors) do
|
||||
colours[k] = v
|
||||
end
|
||||
|
||||
colours.grey = colors.gray
|
||||
colours.gray = nil
|
||||
|
||||
colours.lightGrey = colors.lightGray
|
||||
colours.lightGray = nil
|
||||
@@ -0,0 +1,49 @@
|
||||
|
||||
if not commands then
|
||||
error( "Cannot load command API on normal computer", 2 )
|
||||
end
|
||||
native = commands.native or commands
|
||||
|
||||
local function collapseArgs( bJSONIsNBT, ... )
|
||||
local args = table.pack(...)
|
||||
for i = 1, #args do
|
||||
local arg = args[i]
|
||||
if type(arg) == "boolean" or type(arg) == "number" or type(arg) == "string" then
|
||||
args[i] = tostring(arg)
|
||||
elseif type(arg) == "table" then
|
||||
args[i] = textutils.serialiseJSON( arg, bJSONIsNBT )
|
||||
else
|
||||
error( "Expected string, number, boolean or table", 3 )
|
||||
end
|
||||
end
|
||||
|
||||
return table.concat(args, " ")
|
||||
end
|
||||
|
||||
-- Put native functions into the environment
|
||||
local env = _ENV
|
||||
for k,v in pairs( native ) do
|
||||
env[k] = v
|
||||
end
|
||||
|
||||
-- Create wrapper functions for all the commands
|
||||
local tAsync = {}
|
||||
local tNonNBTJSONCommands = {
|
||||
[ "tellraw" ] = true,
|
||||
[ "title" ] = true
|
||||
}
|
||||
local tCommands = native.list()
|
||||
for n,sCommandName in ipairs(tCommands) do
|
||||
if env[ sCommandName ] == nil then
|
||||
local bJSONIsNBT = (tNonNBTJSONCommands[ sCommandName ] == nil)
|
||||
env[ sCommandName ] = function( ... )
|
||||
local sCommand = collapseArgs( bJSONIsNBT, sCommandName, ... )
|
||||
return native.exec( sCommand )
|
||||
end
|
||||
tAsync[ sCommandName ] = function( ... )
|
||||
local sCommand = collapseArgs( bJSONIsNBT, sCommandName, ... )
|
||||
return native.execAsync( sCommand )
|
||||
end
|
||||
end
|
||||
end
|
||||
env.async = tAsync
|
||||
87
src/main/resources/data/computercraft/lua/rom/apis/disk.lua
Normal file
87
src/main/resources/data/computercraft/lua/rom/apis/disk.lua
Normal file
@@ -0,0 +1,87 @@
|
||||
|
||||
local function isDrive( name )
|
||||
if type( name ) ~= "string" then
|
||||
error( "bad argument #1 (expected string, got " .. type( name ) .. ")", 3 )
|
||||
end
|
||||
return peripheral.getType( name ) == "drive"
|
||||
end
|
||||
|
||||
function isPresent( name )
|
||||
if isDrive( name ) then
|
||||
return peripheral.call( name, "isDiskPresent" )
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function getLabel( name )
|
||||
if isDrive( name ) then
|
||||
return peripheral.call( name, "getDiskLabel" )
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function setLabel( name, label )
|
||||
if isDrive( name ) then
|
||||
peripheral.call( name, "setDiskLabel", label )
|
||||
end
|
||||
end
|
||||
|
||||
function hasData( name )
|
||||
if isDrive( name ) then
|
||||
return peripheral.call( name, "hasData" )
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function getMountPath( name )
|
||||
if isDrive( name ) then
|
||||
return peripheral.call( name, "getMountPath" )
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function hasAudio( name )
|
||||
if isDrive( name ) then
|
||||
return peripheral.call( name, "hasAudio" )
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function getAudioTitle( name )
|
||||
if isDrive( name ) then
|
||||
return peripheral.call( name, "getAudioTitle" )
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function playAudio( name )
|
||||
if isDrive( name ) then
|
||||
peripheral.call( name, "playAudio" )
|
||||
end
|
||||
end
|
||||
|
||||
function stopAudio( name )
|
||||
if not name then
|
||||
for n,sName in ipairs( peripheral.getNames() ) do
|
||||
stopAudio( sName )
|
||||
end
|
||||
else
|
||||
if isDrive( name ) then
|
||||
peripheral.call( name, "stopAudio" )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function eject( name )
|
||||
if isDrive( name ) then
|
||||
peripheral.call( name, "ejectDisk" )
|
||||
end
|
||||
end
|
||||
|
||||
function getID( name )
|
||||
if isDrive( name ) then
|
||||
return peripheral.call( name, "getDiskID" )
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
167
src/main/resources/data/computercraft/lua/rom/apis/gps.lua
Normal file
167
src/main/resources/data/computercraft/lua/rom/apis/gps.lua
Normal file
@@ -0,0 +1,167 @@
|
||||
CHANNEL_GPS = 65534
|
||||
|
||||
local function trilaterate( A, B, C )
|
||||
local a2b = B.vPosition - A.vPosition
|
||||
local a2c = C.vPosition - A.vPosition
|
||||
|
||||
if math.abs( a2b:normalize():dot( a2c:normalize() ) ) > 0.999 then
|
||||
return nil
|
||||
end
|
||||
|
||||
local d = a2b:length()
|
||||
local ex = a2b:normalize( )
|
||||
local i = ex:dot( a2c )
|
||||
local ey = (a2c - (ex * i)):normalize()
|
||||
local j = ey:dot( a2c )
|
||||
local ez = ex:cross( ey )
|
||||
|
||||
local r1 = A.nDistance
|
||||
local r2 = B.nDistance
|
||||
local r3 = C.nDistance
|
||||
|
||||
local x = (r1*r1 - r2*r2 + d*d) / (2*d)
|
||||
local y = (r1*r1 - r3*r3 - x*x + (x-i)*(x-i) + j*j) / (2*j)
|
||||
|
||||
local result = A.vPosition + (ex * x) + (ey * y)
|
||||
|
||||
local zSquared = r1*r1 - x*x - y*y
|
||||
if zSquared > 0 then
|
||||
local z = math.sqrt( zSquared )
|
||||
local result1 = result + (ez * z)
|
||||
local result2 = result - (ez * z)
|
||||
|
||||
local rounded1, rounded2 = result1:round( 0.01 ), result2:round( 0.01 )
|
||||
if rounded1.x ~= rounded2.x or rounded1.y ~= rounded2.y or rounded1.z ~= rounded2.z then
|
||||
return rounded1, rounded2
|
||||
else
|
||||
return rounded1
|
||||
end
|
||||
end
|
||||
return result:round( 0.01 )
|
||||
|
||||
end
|
||||
|
||||
local function narrow( p1, p2, fix )
|
||||
local dist1 = math.abs( (p1 - fix.vPosition):length() - fix.nDistance )
|
||||
local dist2 = math.abs( (p2 - fix.vPosition):length() - fix.nDistance )
|
||||
|
||||
if math.abs(dist1 - dist2) < 0.01 then
|
||||
return p1, p2
|
||||
elseif dist1 < dist2 then
|
||||
return p1:round( 0.01 )
|
||||
else
|
||||
return p2:round( 0.01 )
|
||||
end
|
||||
end
|
||||
|
||||
function locate( _nTimeout, _bDebug )
|
||||
if _nTimeout ~= nil and type( _nTimeout ) ~= "number" then
|
||||
error( "bad argument #1 (expected number, got " .. type( _nTimeout ) .. ")", 2 )
|
||||
end
|
||||
if _bDebug ~= nil and type( _bDebug ) ~= "boolean" then
|
||||
error( "bad argument #2 (expected boolean, got " .. type( _bDebug) .. ")", 2 )
|
||||
end
|
||||
-- Let command computers use their magic fourth-wall-breaking special abilities
|
||||
if commands then
|
||||
return commands.getBlockPosition()
|
||||
end
|
||||
|
||||
-- Find a modem
|
||||
local sModemSide = nil
|
||||
for n,sSide in ipairs( rs.getSides() ) do
|
||||
if peripheral.getType( sSide ) == "modem" and peripheral.call( sSide, "isWireless" ) then
|
||||
sModemSide = sSide
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if sModemSide == nil then
|
||||
if _bDebug then
|
||||
print( "No wireless modem attached" )
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
if _bDebug then
|
||||
print( "Finding position..." )
|
||||
end
|
||||
|
||||
-- Open a channel
|
||||
local modem = peripheral.wrap( sModemSide )
|
||||
local bCloseChannel = false
|
||||
if not modem.isOpen( os.getComputerID() ) then
|
||||
modem.open( os.getComputerID() )
|
||||
bCloseChannel = true
|
||||
end
|
||||
|
||||
-- Send a ping to listening GPS hosts
|
||||
modem.transmit( CHANNEL_GPS, os.getComputerID(), "PING" )
|
||||
|
||||
-- Wait for the responses
|
||||
local tFixes = {}
|
||||
local pos1, pos2 = nil, nil
|
||||
local timeout = os.startTimer( _nTimeout or 2 )
|
||||
while true do
|
||||
local e, p1, p2, p3, p4, p5 = os.pullEvent()
|
||||
if e == "modem_message" then
|
||||
-- We received a reply from a modem
|
||||
local sSide, sChannel, sReplyChannel, tMessage, nDistance = p1, p2, p3, p4, p5
|
||||
if sSide == sModemSide and sChannel == os.getComputerID() and sReplyChannel == CHANNEL_GPS and nDistance then
|
||||
-- Received the correct message from the correct modem: use it to determine position
|
||||
if type(tMessage) == "table" and #tMessage == 3 and tonumber(tMessage[1]) and tonumber(tMessage[2]) and tonumber(tMessage[3]) then
|
||||
local tFix = { vPosition = vector.new( tMessage[1], tMessage[2], tMessage[3] ), nDistance = nDistance }
|
||||
if _bDebug then
|
||||
print( tFix.nDistance.." metres from "..tostring( tFix.vPosition ) )
|
||||
end
|
||||
if tFix.nDistance == 0 then
|
||||
pos1, pos2 = tFix.vPosition, nil
|
||||
else
|
||||
table.insert( tFixes, tFix )
|
||||
if #tFixes >= 3 then
|
||||
if not pos1 then
|
||||
pos1, pos2 = trilaterate( tFixes[1], tFixes[2], tFixes[#tFixes] )
|
||||
else
|
||||
pos1, pos2 = narrow( pos1, pos2, tFixes[#tFixes] )
|
||||
end
|
||||
end
|
||||
end
|
||||
if pos1 and not pos2 then
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
elseif e == "timer" then
|
||||
-- We received a timeout
|
||||
local timer = p1
|
||||
if timer == timeout then
|
||||
break
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
-- Close the channel, if we opened one
|
||||
if bCloseChannel then
|
||||
modem.close( os.getComputerID() )
|
||||
end
|
||||
|
||||
-- Return the response
|
||||
if pos1 and pos2 then
|
||||
if _bDebug then
|
||||
print( "Ambiguous position" )
|
||||
print( "Could be "..pos1.x..","..pos1.y..","..pos1.z.." or "..pos2.x..","..pos2.y..","..pos2.z )
|
||||
end
|
||||
return nil
|
||||
elseif pos1 then
|
||||
if _bDebug then
|
||||
print( "Position is "..pos1.x..","..pos1.y..","..pos1.z )
|
||||
end
|
||||
return pos1.x, pos1.y, pos1.z
|
||||
else
|
||||
if _bDebug then
|
||||
print( "Could not determine position" )
|
||||
end
|
||||
return nil
|
||||
end
|
||||
end
|
||||
78
src/main/resources/data/computercraft/lua/rom/apis/help.lua
Normal file
78
src/main/resources/data/computercraft/lua/rom/apis/help.lua
Normal file
@@ -0,0 +1,78 @@
|
||||
|
||||
local sPath = "/rom/help"
|
||||
|
||||
function path()
|
||||
return sPath
|
||||
end
|
||||
|
||||
function setPath( _sPath )
|
||||
if type( _sPath ) ~= "string" then
|
||||
error( "bad argument #1 (expected string, got " .. type( _sPath ) .. ")", 2 )
|
||||
end
|
||||
sPath = _sPath
|
||||
end
|
||||
|
||||
function lookup( _sTopic )
|
||||
if type( _sTopic ) ~= "string" then
|
||||
error( "bad argument #1 (expected string, got " .. type( _sTopic ) .. ")", 2 )
|
||||
end
|
||||
-- Look on the path variable
|
||||
for sPath in string.gmatch(sPath, "[^:]+") do
|
||||
sPath = fs.combine( sPath, _sTopic )
|
||||
if fs.exists( sPath ) and not fs.isDir( sPath ) then
|
||||
return sPath
|
||||
elseif fs.exists( sPath..".txt" ) and not fs.isDir( sPath..".txt" ) then
|
||||
return sPath..".txt"
|
||||
end
|
||||
end
|
||||
|
||||
-- Not found
|
||||
return nil
|
||||
end
|
||||
|
||||
function topics()
|
||||
-- Add index
|
||||
local tItems = {
|
||||
[ "index" ] = true
|
||||
}
|
||||
|
||||
-- Add topics from the path
|
||||
for sPath in string.gmatch(sPath, "[^:]+") do
|
||||
if fs.isDir( sPath ) then
|
||||
local tList = fs.list( sPath )
|
||||
for n,sFile in pairs( tList ) do
|
||||
if string.sub( sFile, 1, 1 ) ~= "." then
|
||||
if not fs.isDir( fs.combine( sPath, sFile ) ) then
|
||||
if #sFile > 4 and sFile:sub(-4) == ".txt" then
|
||||
sFile = sFile:sub(1,-5)
|
||||
end
|
||||
tItems[ sFile ] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Sort and return
|
||||
local tItemList = {}
|
||||
for sItem, b in pairs( tItems ) do
|
||||
table.insert( tItemList, sItem )
|
||||
end
|
||||
table.sort( tItemList )
|
||||
return tItemList
|
||||
end
|
||||
|
||||
function completeTopic( sText )
|
||||
if type( sText ) ~= "string" then
|
||||
error( "bad argument #1 (expected string, got " .. type( sText ) .. ")", 2 )
|
||||
end
|
||||
local tTopics = topics()
|
||||
local tResults = {}
|
||||
for n=1,#tTopics do
|
||||
local sTopic = tTopics[n]
|
||||
if #sTopic > #sText and string.sub( sTopic, 1, #sText ) == sText then
|
||||
table.insert( tResults, string.sub( sTopic, #sText + 1 ) )
|
||||
end
|
||||
end
|
||||
return tResults
|
||||
end
|
||||
249
src/main/resources/data/computercraft/lua/rom/apis/io.lua
Normal file
249
src/main/resources/data/computercraft/lua/rom/apis/io.lua
Normal file
@@ -0,0 +1,249 @@
|
||||
-- Definition for the IO API
|
||||
local typeOf = _G.type
|
||||
|
||||
--- If we return nil then close the file, as we've reached the end.
|
||||
-- We use this weird wrapper function as we wish to preserve the varargs
|
||||
local function checkResult(handle, ...)
|
||||
if ... == nil and handle._autoclose and not handle._closed then handle:close() end
|
||||
return ...
|
||||
end
|
||||
|
||||
local handleMetatable
|
||||
handleMetatable = {
|
||||
__name = "FILE*",
|
||||
__tostring = function(self)
|
||||
if self._closed then
|
||||
return "file (closed)"
|
||||
else
|
||||
local hash = tostring(self._handle):match("table: (%x+)")
|
||||
return "file (" .. hash .. ")"
|
||||
end
|
||||
end,
|
||||
__index = {
|
||||
close = function(self)
|
||||
if typeOf(self) ~= "table" or getmetatable(self) ~= handleMetatable then
|
||||
error("bad argument #1 (FILE expected, got " .. typeOf(self) .. ")", 2)
|
||||
end
|
||||
if self._closed then error("attempt to use a closed file", 2) end
|
||||
|
||||
local handle = self._handle
|
||||
if handle.close then
|
||||
self._closed = true
|
||||
handle.close()
|
||||
return true
|
||||
else
|
||||
return nil, "attempt to close standard stream"
|
||||
end
|
||||
end,
|
||||
flush = function(self)
|
||||
if typeOf(self) ~= "table" or getmetatable(self) ~= handleMetatable then
|
||||
error("bad argument #1 (FILE expected, got " .. typeOf(self) .. ")", 2)
|
||||
end
|
||||
if self._closed then error("attempt to use a closed file", 2) end
|
||||
|
||||
local handle = self._handle
|
||||
if handle.flush then handle.flush() end
|
||||
end,
|
||||
lines = function(self, ...)
|
||||
if typeOf(self) ~= "table" or getmetatable(self) ~= handleMetatable then
|
||||
error("bad argument #1 (FILE expected, got " .. typeOf(self) .. ")", 2)
|
||||
end
|
||||
if self._closed then error("attempt to use a closed file", 2) end
|
||||
|
||||
local handle = self._handle
|
||||
if not handle.read then return nil, "file is not readable" end
|
||||
|
||||
local args = table.pack(...)
|
||||
return function() return checkResult(self, self:read(table.unpack(args, 1, args.n))) end
|
||||
end,
|
||||
read = function(self, ...)
|
||||
if typeOf(self) ~= "table" or getmetatable(self) ~= handleMetatable then
|
||||
error("bad argument #1 (FILE expected, got " .. typeOf(self) .. ")", 2)
|
||||
end
|
||||
if self._closed then error("attempt to use a closed file", 2) end
|
||||
|
||||
local handle = self._handle
|
||||
if not handle.read and not handle.readLine then return nil, "Not opened for reading" end
|
||||
|
||||
local n = select('#', ...)
|
||||
local output = {}
|
||||
for i = 1, n do
|
||||
local arg = select(i, ...)
|
||||
local res
|
||||
if typeOf(arg) == "number" then
|
||||
if handle.read then res = handle.read(arg) end
|
||||
elseif typeOf(arg) == "string" then
|
||||
local format = arg:gsub("^%*", ""):sub(1, 1)
|
||||
|
||||
if format == "l" then
|
||||
if handle.readLine then res = handle.readLine() end
|
||||
elseif format == "L" and handle.readLine then
|
||||
if handle.readLine then res = handle.readLine(true) end
|
||||
elseif format == "a" then
|
||||
if handle.readAll then res = handle.readAll() or "" end
|
||||
elseif format == "n" then
|
||||
res = nil -- Skip this format as we can't really handle it
|
||||
else
|
||||
error("bad argument #" .. i .. " (invalid format)", 2)
|
||||
end
|
||||
else
|
||||
error("bad argument #" .. i .. " (expected string, got " .. typeOf(arg) .. ")", 2)
|
||||
end
|
||||
|
||||
output[i] = res
|
||||
if not res then break end
|
||||
end
|
||||
|
||||
-- Default to "l" if possible
|
||||
if n == 0 and handle.readLine then return handle.readLine() end
|
||||
return table.unpack(output, 1, n)
|
||||
end,
|
||||
seek = function(self, whence, offset)
|
||||
if typeOf(self) ~= "table" or getmetatable(self) ~= handleMetatable then
|
||||
error("bad argument #1 (FILE expected, got " .. typeOf(self) .. ")", 2)
|
||||
end
|
||||
if self._closed then error("attempt to use a closed file", 2) end
|
||||
|
||||
local handle = self._handle
|
||||
if not handle.seek then return nil, "file is not seekable" end
|
||||
|
||||
-- It's a tail call, so error positions are preserved
|
||||
return handle.seek(whence, offset)
|
||||
end,
|
||||
setvbuf = function(self, mode, size) end,
|
||||
write = function(self, ...)
|
||||
if typeOf(self) ~= "table" or getmetatable(self) ~= handleMetatable then
|
||||
error("bad argument #1 (FILE expected, got " .. typeOf(self) .. ")", 2)
|
||||
end
|
||||
if self._closed then error("attempt to use a closed file", 2) end
|
||||
|
||||
local handle = self._handle
|
||||
if not handle.write then return nil, "file is not writable" end
|
||||
|
||||
local n = select("#", ...)
|
||||
for i = 1, n do handle.write(select(i, ...)) end
|
||||
return self
|
||||
end,
|
||||
},
|
||||
}
|
||||
|
||||
local defaultInput = setmetatable({
|
||||
_handle = { readLine = _G.read }
|
||||
}, handleMetatable)
|
||||
|
||||
local defaultOutput = setmetatable({
|
||||
_handle = { write = _G.write }
|
||||
}, handleMetatable)
|
||||
|
||||
local defaultError = setmetatable({
|
||||
_handle = {
|
||||
write = function(...)
|
||||
local oldColour
|
||||
if term.isColour() then
|
||||
oldColour = term.getTextColour()
|
||||
term.setTextColour(colors.red)
|
||||
end
|
||||
_G.write(...)
|
||||
if term.isColour() then term.setTextColour(oldColour) end
|
||||
end,
|
||||
}
|
||||
}, handleMetatable)
|
||||
|
||||
local currentInput = defaultInput
|
||||
local currentOutput = defaultOutput
|
||||
|
||||
stdin = defaultInput
|
||||
stdout = defaultOutput
|
||||
stderr = defaultError
|
||||
|
||||
function close(_file)
|
||||
if _file == nil then return currentOutput:close() end
|
||||
|
||||
if typeOf(_file) ~= "table" or getmetatable(_file) ~= handleMetatable then
|
||||
error("bad argument #1 (FILE expected, got " .. typeOf(_file) .. ")", 2)
|
||||
end
|
||||
return _file:close()
|
||||
end
|
||||
|
||||
function flush()
|
||||
return currentOutput:flush()
|
||||
end
|
||||
|
||||
function input(_arg)
|
||||
if typeOf(_arg) == "string" then
|
||||
local res, err = open(_arg, "rb")
|
||||
if not res then error(err, 2) end
|
||||
currentInput = res
|
||||
elseif typeOf(_arg) == "table" and getmetatable(_arg) == handleMetatable then
|
||||
currentInput = _arg
|
||||
elseif _arg ~= nil then
|
||||
error("bad argument #1 (FILE expected, got " .. typeOf(_arg) .. ")", 2)
|
||||
end
|
||||
|
||||
return currentInput
|
||||
end
|
||||
|
||||
function lines(_sFileName)
|
||||
if _sFileName ~= nil and typeOf(_sFileName) ~= "string" then
|
||||
error("bad argument #1 (expected string, got " .. typeOf(_sFileName) .. ")", 2)
|
||||
end
|
||||
if _sFileName then
|
||||
local ok, err = open(_sFileName, "rb")
|
||||
if not ok then error(err, 2) end
|
||||
|
||||
-- We set this magic flag to mark this file as being opened by io.lines and so should be
|
||||
-- closed automatically
|
||||
ok._autoclose = true
|
||||
return ok:lines()
|
||||
else
|
||||
return currentInput:lines()
|
||||
end
|
||||
end
|
||||
|
||||
function open(_sPath, _sMode)
|
||||
if typeOf(_sPath) ~= "string" then
|
||||
error("bad argument #1 (expected string, got " .. typeOf(_sPath) .. ")", 2)
|
||||
end
|
||||
if _sMode ~= nil and typeOf(_sMode) ~= "string" then
|
||||
error("bad argument #2 (expected string, got " .. typeOf(_sMode) .. ")", 2)
|
||||
end
|
||||
|
||||
local sMode = _sMode and _sMode:gsub("%+", "") or "rb"
|
||||
local file, err = fs.open(_sPath, sMode)
|
||||
if not file then return nil, err end
|
||||
|
||||
return setmetatable({ _handle = file }, handleMetatable)
|
||||
end
|
||||
|
||||
function output(_arg)
|
||||
if typeOf(_arg) == "string" then
|
||||
local res, err = open(_arg, "w")
|
||||
if not res then error(err, 2) end
|
||||
currentOutput = res
|
||||
elseif typeOf(_arg) == "table" and getmetatable(_arg) == handleMetatable then
|
||||
currentOutput = _arg
|
||||
elseif _arg ~= nil then
|
||||
error("bad argument #1 (FILE expected, got " .. typeOf(_arg) .. ")", 2)
|
||||
end
|
||||
|
||||
return currentOutput
|
||||
end
|
||||
|
||||
function read(...)
|
||||
return currentInput:read(...)
|
||||
end
|
||||
|
||||
function type(handle)
|
||||
if typeOf(handle) == "table" and getmetatable(handle) == handleMetatable then
|
||||
if handle._closed then
|
||||
return "closed file"
|
||||
else
|
||||
return "file"
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function write(...)
|
||||
return currentOutput:write(...)
|
||||
end
|
||||
65
src/main/resources/data/computercraft/lua/rom/apis/keys.lua
Normal file
65
src/main/resources/data/computercraft/lua/rom/apis/keys.lua
Normal file
@@ -0,0 +1,65 @@
|
||||
|
||||
-- Minecraft key code bindings
|
||||
-- See http://www.minecraftwiki.net/wiki/Key_codes for more info
|
||||
|
||||
local tKeys = {
|
||||
nil, "one", "two", "three", "four", -- 1
|
||||
"five", "six", "seven", "eight", "nine", -- 6
|
||||
"zero", "minus", "equals", "backspace","tab", -- 11
|
||||
"q", "w", "e", "r", "t", -- 16
|
||||
"y", "u", "i", "o", "p", -- 21
|
||||
"leftBracket","rightBracket","enter","leftCtrl","a", -- 26
|
||||
"s", "d", "f", "g", "h", -- 31
|
||||
"j", "k", "l", "semiColon","apostrophe", -- 36
|
||||
"grave", "leftShift","backslash","z", "x", -- 41
|
||||
"c", "v", "b", "n", "m", -- 46
|
||||
"comma", "period", "slash", "rightShift","multiply", -- 51
|
||||
"leftAlt", "space", "capsLock", "f1", "f2", -- 56
|
||||
"f3", "f4", "f5", "f6", "f7", -- 61
|
||||
"f8", "f9", "f10", "numLock", "scrollLock", -- 66
|
||||
"numPad7", "numPad8", "numPad9", "numPadSubtract","numPad4", -- 71
|
||||
"numPad5", "numPad6", "numPadAdd","numPad1", "numPad2", -- 76
|
||||
"numPad3", "numPad0", "numPadDecimal",nil, nil, -- 81
|
||||
nil, "f11", "f12", nil, nil, -- 86
|
||||
nil, nil, nil, nil, nil, -- 91
|
||||
nil, nil, nil, nil, "f13", -- 96
|
||||
"f14", "f15", nil, nil, nil, -- 101
|
||||
nil, nil, nil, nil, nil, -- 106
|
||||
nil, "kana", nil, nil, nil, -- 111
|
||||
nil, nil, nil, nil, nil, -- 116
|
||||
"convert", nil, "noconvert",nil, "yen", -- 121
|
||||
nil, nil, nil, nil, nil, -- 126
|
||||
nil, nil, nil, nil, nil, -- 131
|
||||
nil, nil, nil, nil, nil, -- 136
|
||||
"numPadEquals",nil, nil, "circumflex","at", -- 141
|
||||
"colon", "underscore","kanji", "stop", "ax", -- 146
|
||||
nil, nil, nil, nil, nil, -- 151
|
||||
"numPadEnter","rightCtrl",nil, nil, nil, -- 156
|
||||
nil, nil, nil, nil, nil, -- 161
|
||||
nil, nil, nil, nil, nil, -- 166
|
||||
nil, nil, nil, nil, nil, -- 171
|
||||
nil, nil, nil, "numPadComma",nil, -- 176
|
||||
"numPadDivide",nil, nil, "rightAlt", nil, -- 181
|
||||
nil, nil, nil, nil, nil, -- 186
|
||||
nil, nil, nil, nil, nil, -- 191
|
||||
nil, "pause", nil, "home", "up", -- 196
|
||||
"pageUp", nil, "left", nil, "right", -- 201
|
||||
nil, "end", "down", "pageDown", "insert", -- 206
|
||||
"delete" -- 211
|
||||
}
|
||||
|
||||
local keys = _ENV
|
||||
for nKey, sKey in pairs( tKeys ) do
|
||||
keys[sKey] = nKey
|
||||
end
|
||||
keys["return"] = keys.enter
|
||||
--backwards compatibility to earlier, typo prone, versions
|
||||
keys.scollLock = keys.scrollLock
|
||||
keys.cimcumflex = keys.circumflex
|
||||
|
||||
function getName( _nKey )
|
||||
if type( _nKey ) ~= "number" then
|
||||
error( "bad argument #1 (expected number, got " .. type( _nKey ) .. ")", 2 )
|
||||
end
|
||||
return tKeys[ _nKey ]
|
||||
end
|
||||
@@ -0,0 +1,213 @@
|
||||
|
||||
local function drawPixelInternal( xPos, yPos )
|
||||
term.setCursorPos( xPos, yPos )
|
||||
term.write(" ")
|
||||
end
|
||||
|
||||
local tColourLookup = {}
|
||||
for n=1,16 do
|
||||
tColourLookup[ string.byte( "0123456789abcdef",n,n ) ] = 2^(n-1)
|
||||
end
|
||||
|
||||
local function parseLine( tImageArg, sLine )
|
||||
local tLine = {}
|
||||
for x=1,sLine:len() do
|
||||
tLine[x] = tColourLookup[ string.byte(sLine,x,x) ] or 0
|
||||
end
|
||||
table.insert( tImageArg, tLine )
|
||||
end
|
||||
|
||||
function parseImage( sRawData )
|
||||
if type( sRawData ) ~= "string" then
|
||||
error( "bad argument #1 (expected string, got " .. type( sRawData ) .. ")" )
|
||||
end
|
||||
local tImage = {}
|
||||
for sLine in ( sRawData .. "\n" ):gmatch( "(.-)\n" ) do -- read each line like original file handling did
|
||||
parseLine( tImage, sLine )
|
||||
end
|
||||
return tImage
|
||||
end
|
||||
|
||||
function loadImage( sPath )
|
||||
if type( sPath ) ~= "string" then
|
||||
error( "bad argument #1 (expected string, got " .. type( sPath ) .. ")", 2 )
|
||||
end
|
||||
|
||||
if fs.exists( sPath ) then
|
||||
local file = io.open( sPath, "r" )
|
||||
local sContent = file:read("*a")
|
||||
file:close()
|
||||
return parseImage( sContent ) -- delegate image parse to parseImage
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function drawPixel( xPos, yPos, nColour )
|
||||
if type( xPos ) ~= "number" then error( "bad argument #1 (expected number, got " .. type( xPos ) .. ")", 2 ) end
|
||||
if type( yPos ) ~= "number" then error( "bad argument #2 (expected number, got " .. type( yPos ) .. ")", 2 ) end
|
||||
if nColour ~= nil and type( nColour ) ~= "number" then error( "bad argument #3 (expected number, got " .. type( nColour ) .. ")", 2 ) end
|
||||
if nColour then
|
||||
term.setBackgroundColor( nColour )
|
||||
end
|
||||
drawPixelInternal( xPos, yPos )
|
||||
end
|
||||
|
||||
function drawLine( startX, startY, endX, endY, nColour )
|
||||
if type( startX ) ~= "number" then error( "bad argument #1 (expected number, got " .. type( startX ) .. ")", 2 ) end
|
||||
if type( startY ) ~= "number" then error( "bad argument #2 (expected number, got " .. type( startY ) .. ")", 2 ) end
|
||||
if type( endX ) ~= "number" then error( "bad argument #3 (expected number, got " .. type( endX ) .. ")", 2 ) end
|
||||
if type( endY ) ~= "number" then error( "bad argument #4 (expected number, got " .. type( endY ) .. ")", 2 ) end
|
||||
if nColour ~= nil and type( nColour ) ~= "number" then error( "bad argument #5 (expected number, got " .. type( nColour ) .. ")", 2 ) end
|
||||
|
||||
startX = math.floor(startX)
|
||||
startY = math.floor(startY)
|
||||
endX = math.floor(endX)
|
||||
endY = math.floor(endY)
|
||||
|
||||
if nColour then
|
||||
term.setBackgroundColor( nColour )
|
||||
end
|
||||
if startX == endX and startY == endY then
|
||||
drawPixelInternal( startX, startY )
|
||||
return
|
||||
end
|
||||
|
||||
local minX = math.min( startX, endX )
|
||||
local maxX, minY, maxY
|
||||
if minX == startX then
|
||||
minY = startY
|
||||
maxX = endX
|
||||
maxY = endY
|
||||
else
|
||||
minY = endY
|
||||
maxX = startX
|
||||
maxY = startY
|
||||
end
|
||||
|
||||
-- TODO: clip to screen rectangle?
|
||||
|
||||
local xDiff = maxX - minX
|
||||
local yDiff = maxY - minY
|
||||
|
||||
if xDiff > math.abs(yDiff) then
|
||||
local y = minY
|
||||
local dy = yDiff / xDiff
|
||||
for x=minX,maxX do
|
||||
drawPixelInternal( x, math.floor( y + 0.5 ) )
|
||||
y = y + dy
|
||||
end
|
||||
else
|
||||
local x = minX
|
||||
local dx = xDiff / yDiff
|
||||
if maxY >= minY then
|
||||
for y=minY,maxY do
|
||||
drawPixelInternal( math.floor( x + 0.5 ), y )
|
||||
x = x + dx
|
||||
end
|
||||
else
|
||||
for y=minY,maxY,-1 do
|
||||
drawPixelInternal( math.floor( x + 0.5 ), y )
|
||||
x = x - dx
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function drawBox( startX, startY, endX, endY, nColour )
|
||||
if type( startX ) ~= "number" then error( "bad argument #1 (expected number, got " .. type( startX ) .. ")", 2 ) end
|
||||
if type( startY ) ~= "number" then error( "bad argument #2 (expected number, got " .. type( startY ) .. ")", 2 ) end
|
||||
if type( endX ) ~= "number" then error( "bad argument #3 (expected number, got " .. type( endX ) .. ")", 2 ) end
|
||||
if type( endY ) ~= "number" then error( "bad argument #4 (expected number, got " .. type( endY ) .. ")", 2 ) end
|
||||
if nColour ~= nil and type( nColour ) ~= "number" then error( "bad argument #5 (expected number, got " .. type( nColour ) .. ")", 2 ) end
|
||||
|
||||
startX = math.floor(startX)
|
||||
startY = math.floor(startY)
|
||||
endX = math.floor(endX)
|
||||
endY = math.floor(endY)
|
||||
|
||||
if nColour then
|
||||
term.setBackgroundColor( nColour )
|
||||
end
|
||||
if startX == endX and startY == endY then
|
||||
drawPixelInternal( startX, startY )
|
||||
return
|
||||
end
|
||||
|
||||
local minX = math.min( startX, endX )
|
||||
local maxX, minY, maxY
|
||||
if minX == startX then
|
||||
minY = startY
|
||||
maxX = endX
|
||||
maxY = endY
|
||||
else
|
||||
minY = endY
|
||||
maxX = startX
|
||||
maxY = startY
|
||||
end
|
||||
|
||||
for x=minX,maxX do
|
||||
drawPixelInternal( x, minY )
|
||||
drawPixelInternal( x, maxY )
|
||||
end
|
||||
|
||||
if (maxY - minY) >= 2 then
|
||||
for y=(minY+1),(maxY-1) do
|
||||
drawPixelInternal( minX, y )
|
||||
drawPixelInternal( maxX, y )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function drawFilledBox( startX, startY, endX, endY, nColour )
|
||||
if type( startX ) ~= "number" then error( "bad argument #1 (expected number, got " .. type( startX ) .. ")", 2 ) end
|
||||
if type( startY ) ~= "number" then error( "bad argument #2 (expected number, got " .. type( startY ) .. ")", 2 ) end
|
||||
if type( endX ) ~= "number" then error( "bad argument #3 (expected number, got " .. type( endX ) .. ")", 2 ) end
|
||||
if type( endY ) ~= "number" then error( "bad argument #4 (expected number, got " .. type( endY ) .. ")", 2 ) end
|
||||
if nColour ~= nil and type( nColour ) ~= "number" then error( "bad argument #5 (expected number, got " .. type( nColour ) .. ")", 2 ) end
|
||||
|
||||
startX = math.floor(startX)
|
||||
startY = math.floor(startY)
|
||||
endX = math.floor(endX)
|
||||
endY = math.floor(endY)
|
||||
|
||||
if nColour then
|
||||
term.setBackgroundColor( nColour )
|
||||
end
|
||||
if startX == endX and startY == endY then
|
||||
drawPixelInternal( startX, startY )
|
||||
return
|
||||
end
|
||||
|
||||
local minX = math.min( startX, endX )
|
||||
local maxX, minY, maxY
|
||||
if minX == startX then
|
||||
minY = startY
|
||||
maxX = endX
|
||||
maxY = endY
|
||||
else
|
||||
minY = endY
|
||||
maxX = startX
|
||||
maxY = startY
|
||||
end
|
||||
|
||||
for x=minX,maxX do
|
||||
for y=minY,maxY do
|
||||
drawPixelInternal( x, y )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function drawImage( tImage, xPos, yPos )
|
||||
if type( tImage ) ~= "table" then error( "bad argument #1 (expected table, got " .. type( tImage ) .. ")", 2 ) end
|
||||
if type( xPos ) ~= "number" then error( "bad argument #2 (expected number, got " .. type( xPos ) .. ")", 2 ) end
|
||||
if type( yPos ) ~= "number" then error( "bad argument #3 (expected number, got " .. type( yPos ) .. ")", 2 ) end
|
||||
for y=1,#tImage do
|
||||
local tLine = tImage[y]
|
||||
for x=1,#tLine do
|
||||
if tLine[x] > 0 then
|
||||
term.setBackgroundColor( tLine[x] )
|
||||
drawPixelInternal( x + xPos - 1, y + yPos - 1 )
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,66 @@
|
||||
|
||||
local function create( ... )
|
||||
local tFns = table.pack(...)
|
||||
local tCos = {}
|
||||
for i = 1, tFns.n, 1 do
|
||||
local fn = tFns[i]
|
||||
if type( fn ) ~= "function" then
|
||||
error( "bad argument #" .. i .. " (expected function, got " .. type( fn ) .. ")", 3 )
|
||||
end
|
||||
|
||||
tCos[i] = coroutine.create(fn)
|
||||
end
|
||||
|
||||
return tCos
|
||||
end
|
||||
|
||||
local function runUntilLimit( _routines, _limit )
|
||||
local count = #_routines
|
||||
local living = count
|
||||
|
||||
local tFilters = {}
|
||||
local eventData = { n = 0 }
|
||||
while true do
|
||||
for n=1,count do
|
||||
local r = _routines[n]
|
||||
if r then
|
||||
if tFilters[r] == nil or tFilters[r] == eventData[1] or eventData[1] == "terminate" then
|
||||
local ok, param = coroutine.resume( r, table.unpack( eventData, 1, eventData.n ) )
|
||||
if not ok then
|
||||
error( param, 0 )
|
||||
else
|
||||
tFilters[r] = param
|
||||
end
|
||||
if coroutine.status( r ) == "dead" then
|
||||
_routines[n] = nil
|
||||
living = living - 1
|
||||
if living <= _limit then
|
||||
return n
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
for n=1,count do
|
||||
local r = _routines[n]
|
||||
if r and coroutine.status( r ) == "dead" then
|
||||
_routines[n] = nil
|
||||
living = living - 1
|
||||
if living <= _limit then
|
||||
return n
|
||||
end
|
||||
end
|
||||
end
|
||||
eventData = table.pack( os.pullEventRaw() )
|
||||
end
|
||||
end
|
||||
|
||||
function waitForAny( ... )
|
||||
local routines = create( ... )
|
||||
return runUntilLimit( routines, #routines - 1 )
|
||||
end
|
||||
|
||||
function waitForAll( ... )
|
||||
local routines = create( ... )
|
||||
runUntilLimit( routines, 0 )
|
||||
end
|
||||
@@ -0,0 +1,124 @@
|
||||
local native = peripheral
|
||||
|
||||
function getNames()
|
||||
local tResults = {}
|
||||
for n,sSide in ipairs( rs.getSides() ) do
|
||||
if native.isPresent( sSide ) then
|
||||
table.insert( tResults, sSide )
|
||||
if native.getType( sSide ) == "modem" and not native.call( sSide, "isWireless" ) then
|
||||
local tRemote = native.call( sSide, "getNamesRemote" )
|
||||
for n,sName in ipairs( tRemote ) do
|
||||
table.insert( tResults, sName )
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return tResults
|
||||
end
|
||||
|
||||
function isPresent( _sSide )
|
||||
if type( _sSide ) ~= "string" then
|
||||
error( "bad argument #1 (expected string, got " .. type( _sSide ) .. ")", 2 )
|
||||
end
|
||||
if native.isPresent( _sSide ) then
|
||||
return true
|
||||
end
|
||||
for n,sSide in ipairs( rs.getSides() ) do
|
||||
if native.getType( sSide ) == "modem" and not native.call( sSide, "isWireless" ) then
|
||||
if native.call( sSide, "isPresentRemote", _sSide ) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function getType( _sSide )
|
||||
if type( _sSide ) ~= "string" then
|
||||
error( "bad argument #1 (expected string, got " .. type( _sSide ) .. ")", 2 )
|
||||
end
|
||||
if native.isPresent( _sSide ) then
|
||||
return native.getType( _sSide )
|
||||
end
|
||||
for n,sSide in ipairs( rs.getSides() ) do
|
||||
if native.getType( sSide ) == "modem" and not native.call( sSide, "isWireless" ) then
|
||||
if native.call( sSide, "isPresentRemote", _sSide ) then
|
||||
return native.call( sSide, "getTypeRemote", _sSide )
|
||||
end
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function getMethods( _sSide )
|
||||
if type( _sSide ) ~= "string" then
|
||||
error( "bad argument #1 (expected string, got " .. type( _sSide ) .. ")", 2 )
|
||||
end
|
||||
if native.isPresent( _sSide ) then
|
||||
return native.getMethods( _sSide )
|
||||
end
|
||||
for n,sSide in ipairs( rs.getSides() ) do
|
||||
if native.getType( sSide ) == "modem" and not native.call( sSide, "isWireless" ) then
|
||||
if native.call( sSide, "isPresentRemote", _sSide ) then
|
||||
return native.call( sSide, "getMethodsRemote", _sSide )
|
||||
end
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function call( _sSide, _sMethod, ... )
|
||||
if type( _sSide ) ~= "string" then
|
||||
error( "bad argument #1 (expected string, got " .. type( _sSide ) .. ")", 2 )
|
||||
end
|
||||
if type( _sSide ) ~= "string" then
|
||||
error( "bad argument #2 (expected string, got " .. type( _sMethod ) .. ")", 2 )
|
||||
end
|
||||
if native.isPresent( _sSide ) then
|
||||
return native.call( _sSide, _sMethod, ... )
|
||||
end
|
||||
for n,sSide in ipairs( rs.getSides() ) do
|
||||
if native.getType( sSide ) == "modem" and not native.call( sSide, "isWireless" ) then
|
||||
if native.call( sSide, "isPresentRemote", _sSide ) then
|
||||
return native.call( sSide, "callRemote", _sSide, _sMethod, ... )
|
||||
end
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function wrap( _sSide )
|
||||
if type( _sSide ) ~= "string" then
|
||||
error( "bad argument #1 (expected string, got " .. type( _sSide ) .. ")", 2 )
|
||||
end
|
||||
if peripheral.isPresent( _sSide ) then
|
||||
local tMethods = peripheral.getMethods( _sSide )
|
||||
local tResult = {}
|
||||
for n,sMethod in ipairs( tMethods ) do
|
||||
tResult[sMethod] = function( ... )
|
||||
return peripheral.call( _sSide, sMethod, ... )
|
||||
end
|
||||
end
|
||||
return tResult
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function find( sType, fnFilter )
|
||||
if type( sType ) ~= "string" then
|
||||
error( "bad argument #1 (expected string, got " .. type( sType ) .. ")", 2 )
|
||||
end
|
||||
if fnFilter ~= nil and type( fnFilter ) ~= "function" then
|
||||
error( "bad argument #2 (expected function, got " .. type( fnFilter ) .. ")", 2 )
|
||||
end
|
||||
local tResults = {}
|
||||
for n,sName in ipairs( peripheral.getNames() ) do
|
||||
if peripheral.getType( sName ) == sType then
|
||||
local wrapped = peripheral.wrap( sName )
|
||||
if fnFilter == nil or fnFilter( sName, wrapped ) then
|
||||
table.insert( tResults, wrapped )
|
||||
end
|
||||
end
|
||||
end
|
||||
return table.unpack( tResults )
|
||||
end
|
||||
289
src/main/resources/data/computercraft/lua/rom/apis/rednet.lua
Normal file
289
src/main/resources/data/computercraft/lua/rom/apis/rednet.lua
Normal file
@@ -0,0 +1,289 @@
|
||||
|
||||
CHANNEL_BROADCAST = 65535
|
||||
CHANNEL_REPEAT = 65533
|
||||
|
||||
local tReceivedMessages = {}
|
||||
local tReceivedMessageTimeouts = {}
|
||||
local tHostnames = {}
|
||||
|
||||
function open( sModem )
|
||||
if type( sModem ) ~= "string" then
|
||||
error( "bad argument #1 (expected string, got " .. type( sModem ) .. ")", 2 )
|
||||
end
|
||||
if peripheral.getType( sModem ) ~= "modem" then
|
||||
error( "No such modem: "..sModem, 2 )
|
||||
end
|
||||
peripheral.call( sModem, "open", os.getComputerID() )
|
||||
peripheral.call( sModem, "open", CHANNEL_BROADCAST )
|
||||
end
|
||||
|
||||
function close( sModem )
|
||||
if sModem then
|
||||
-- Close a specific modem
|
||||
if type( sModem ) ~= "string" then
|
||||
error( "bad argument #1 (expected string, got " .. type( sModem ) .. ")", 2 )
|
||||
end
|
||||
if peripheral.getType( sModem ) ~= "modem" then
|
||||
error( "No such modem: "..sModem, 2 )
|
||||
end
|
||||
peripheral.call( sModem, "close", os.getComputerID() )
|
||||
peripheral.call( sModem, "close", CHANNEL_BROADCAST )
|
||||
else
|
||||
-- Close all modems
|
||||
for n,sModem in ipairs( peripheral.getNames() ) do
|
||||
if isOpen( sModem ) then
|
||||
close( sModem )
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function isOpen( sModem )
|
||||
if sModem then
|
||||
-- Check if a specific modem is open
|
||||
if type( sModem ) ~= "string" then
|
||||
error( "bad argument #1 (expected string, got " .. type( sModem ) .. ")", 2 )
|
||||
end
|
||||
if peripheral.getType( sModem ) == "modem" then
|
||||
return peripheral.call( sModem, "isOpen", os.getComputerID() ) and peripheral.call( sModem, "isOpen", CHANNEL_BROADCAST )
|
||||
end
|
||||
else
|
||||
-- Check if any modem is open
|
||||
for n,sModem in ipairs( peripheral.getNames() ) do
|
||||
if isOpen( sModem ) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function send( nRecipient, message, sProtocol )
|
||||
if type( nRecipient ) ~= "number" then
|
||||
error( "bad argument #1 (expected number, got " .. type( nRecipient ) .. ")", 2 )
|
||||
end
|
||||
if sProtocol ~= nil and type( sProtocol ) ~= "string" then
|
||||
error( "bad argument #3 (expected string, got " .. type( sProtocol ) .. ")", 2 )
|
||||
end
|
||||
-- Generate a (probably) unique message ID
|
||||
-- We could do other things to guarantee uniqueness, but we really don't need to
|
||||
-- Store it to ensure we don't get our own messages back
|
||||
local nMessageID = math.random( 1, 2147483647 )
|
||||
tReceivedMessages[ nMessageID ] = true
|
||||
tReceivedMessageTimeouts[ os.startTimer( 30 ) ] = nMessageID
|
||||
|
||||
-- Create the message
|
||||
local nReplyChannel = os.getComputerID()
|
||||
local tMessage = {
|
||||
nMessageID = nMessageID,
|
||||
nRecipient = nRecipient,
|
||||
message = message,
|
||||
sProtocol = sProtocol,
|
||||
}
|
||||
|
||||
local sent = false
|
||||
if nRecipient == os.getComputerID() then
|
||||
-- Loopback to ourselves
|
||||
os.queueEvent( "rednet_message", nReplyChannel, message, sProtocol )
|
||||
sent = true
|
||||
else
|
||||
-- Send on all open modems, to the target and to repeaters
|
||||
for n,sModem in ipairs( peripheral.getNames() ) do
|
||||
if isOpen( sModem ) then
|
||||
peripheral.call( sModem, "transmit", nRecipient, nReplyChannel, tMessage );
|
||||
peripheral.call( sModem, "transmit", CHANNEL_REPEAT, nReplyChannel, tMessage );
|
||||
sent = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return sent
|
||||
end
|
||||
|
||||
function broadcast( message, sProtocol )
|
||||
if sProtocol ~= nil and type( sProtocol ) ~= "string" then
|
||||
error( "bad argument #2 (expected string, got " .. type( sProtocol ) .. ")", 2 )
|
||||
end
|
||||
send( CHANNEL_BROADCAST, message, sProtocol )
|
||||
end
|
||||
|
||||
function receive( sProtocolFilter, nTimeout )
|
||||
-- The parameters used to be ( nTimeout ), detect this case for backwards compatibility
|
||||
if type(sProtocolFilter) == "number" and nTimeout == nil then
|
||||
sProtocolFilter, nTimeout = nil, sProtocolFilter
|
||||
end
|
||||
if sProtocolFilter ~= nil and type( sProtocolFilter ) ~= "string" then
|
||||
error( "bad argument #1 (expected string, got " .. type( sProtocolFilter ) .. ")", 2 )
|
||||
end
|
||||
if nTimeout ~= nil and type( nTimeout ) ~= "number" then
|
||||
error( "bad argument #2 (expected number, got " .. type( nTimeout ) .. ")", 2 )
|
||||
end
|
||||
|
||||
-- Start the timer
|
||||
local timer = nil
|
||||
local sFilter = nil
|
||||
if nTimeout then
|
||||
timer = os.startTimer( nTimeout )
|
||||
sFilter = nil
|
||||
else
|
||||
sFilter = "rednet_message"
|
||||
end
|
||||
|
||||
-- Wait for events
|
||||
while true do
|
||||
local sEvent, p1, p2, p3 = os.pullEvent( sFilter )
|
||||
if sEvent == "rednet_message" then
|
||||
-- Return the first matching rednet_message
|
||||
local nSenderID, message, sProtocol = p1, p2, p3
|
||||
if sProtocolFilter == nil or sProtocol == sProtocolFilter then
|
||||
return nSenderID, message, sProtocol
|
||||
end
|
||||
elseif sEvent == "timer" then
|
||||
-- Return nil if we timeout
|
||||
if p1 == timer then
|
||||
return nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function host( sProtocol, sHostname )
|
||||
if type( sProtocol ) ~= "string" then
|
||||
error( "bad argument #1 (expected string, got " .. type( sProtocol ) .. ")", 2 )
|
||||
end
|
||||
if type( sHostname ) ~= "string" then
|
||||
error( "bad argument #2 (expected string, got " .. type( sHostname ) .. ")", 2 )
|
||||
end
|
||||
if sHostname == "localhost" then
|
||||
error( "Reserved hostname", 2 )
|
||||
end
|
||||
if tHostnames[ sProtocol ] ~= sHostname then
|
||||
if lookup( sProtocol, sHostname ) ~= nil then
|
||||
error( "Hostname in use", 2 )
|
||||
end
|
||||
tHostnames[ sProtocol ] = sHostname
|
||||
end
|
||||
end
|
||||
|
||||
function unhost( sProtocol )
|
||||
if type( sProtocol ) ~= "string" then
|
||||
error( "bad argument #1 (expected string, got " .. type( sProtocol ) .. ")", 2 )
|
||||
end
|
||||
tHostnames[ sProtocol ] = nil
|
||||
end
|
||||
|
||||
function lookup( sProtocol, sHostname )
|
||||
if type( sProtocol ) ~= "string" then
|
||||
error( "bad argument #1 (expected string, got " .. type( sProtocol ) .. ")", 2 )
|
||||
end
|
||||
if sHostname ~= nil and type( sHostname ) ~= "string" then
|
||||
error( "bad argument #2 (expected string, got " .. type( sHostname ) .. ")", 2 )
|
||||
end
|
||||
|
||||
-- Build list of host IDs
|
||||
local tResults = nil
|
||||
if sHostname == nil then
|
||||
tResults = {}
|
||||
end
|
||||
|
||||
-- Check localhost first
|
||||
if tHostnames[ sProtocol ] then
|
||||
if sHostname == nil then
|
||||
table.insert( tResults, os.getComputerID() )
|
||||
elseif sHostname == "localhost" or sHostname == tHostnames[ sProtocol ] then
|
||||
return os.getComputerID()
|
||||
end
|
||||
end
|
||||
|
||||
if not isOpen() then
|
||||
if tResults then
|
||||
return table.unpack( tResults )
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Broadcast a lookup packet
|
||||
broadcast( {
|
||||
sType = "lookup",
|
||||
sProtocol = sProtocol,
|
||||
sHostname = sHostname,
|
||||
}, "dns" )
|
||||
|
||||
-- Start a timer
|
||||
local timer = os.startTimer( 2 )
|
||||
|
||||
-- Wait for events
|
||||
while true do
|
||||
local event, p1, p2, p3 = os.pullEvent()
|
||||
if event == "rednet_message" then
|
||||
-- Got a rednet message, check if it's the response to our request
|
||||
local nSenderID, tMessage, sMessageProtocol = p1, p2, p3
|
||||
if sMessageProtocol == "dns" and type(tMessage) == "table" and tMessage.sType == "lookup response" then
|
||||
if tMessage.sProtocol == sProtocol then
|
||||
if sHostname == nil then
|
||||
table.insert( tResults, nSenderID )
|
||||
elseif tMessage.sHostname == sHostname then
|
||||
return nSenderID
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
-- Got a timer event, check it's the end of our timeout
|
||||
if p1 == timer then
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
if tResults then
|
||||
return table.unpack( tResults )
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
local bRunning = false
|
||||
function run()
|
||||
if bRunning then
|
||||
error( "rednet is already running", 2 )
|
||||
end
|
||||
bRunning = true
|
||||
|
||||
while bRunning do
|
||||
local sEvent, p1, p2, p3, p4 = os.pullEventRaw()
|
||||
if sEvent == "modem_message" then
|
||||
-- Got a modem message, process it and add it to the rednet event queue
|
||||
local sModem, nChannel, nReplyChannel, tMessage = p1, p2, p3, p4
|
||||
if isOpen( sModem ) and ( nChannel == os.getComputerID() or nChannel == CHANNEL_BROADCAST ) then
|
||||
if type( tMessage ) == "table" and tMessage.nMessageID then
|
||||
if not tReceivedMessages[ tMessage.nMessageID ] then
|
||||
tReceivedMessages[ tMessage.nMessageID ] = true
|
||||
tReceivedMessageTimeouts[ os.startTimer( 30 ) ] = tMessage.nMessageID
|
||||
os.queueEvent( "rednet_message", nReplyChannel, tMessage.message, tMessage.sProtocol )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
elseif sEvent == "rednet_message" then
|
||||
-- Got a rednet message (queued from above), respond to dns lookup
|
||||
local nSenderID, tMessage, sProtocol = p1, p2, p3
|
||||
if sProtocol == "dns" and type(tMessage) == "table" and tMessage.sType == "lookup" then
|
||||
local sHostname = tHostnames[ tMessage.sProtocol ]
|
||||
if sHostname ~= nil and (tMessage.sHostname == nil or tMessage.sHostname == sHostname) then
|
||||
rednet.send( nSenderID, {
|
||||
sType = "lookup response",
|
||||
sHostname = sHostname,
|
||||
sProtocol = tMessage.sProtocol,
|
||||
}, "dns" )
|
||||
end
|
||||
end
|
||||
|
||||
elseif sEvent == "timer" then
|
||||
-- Got a timer event, use it to clear the event queue
|
||||
local nTimer = p1
|
||||
local nMessage = tReceivedMessageTimeouts[ nTimer ]
|
||||
if nMessage then
|
||||
tReceivedMessageTimeouts[ nTimer ] = nil
|
||||
tReceivedMessages[ nMessage ] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
103
src/main/resources/data/computercraft/lua/rom/apis/settings.lua
Normal file
103
src/main/resources/data/computercraft/lua/rom/apis/settings.lua
Normal file
@@ -0,0 +1,103 @@
|
||||
|
||||
local tSettings = {}
|
||||
|
||||
function set( sName, value )
|
||||
if type( sName ) ~= "string" then error( "bad argument #1 (expected string, got " .. type( sName ) .. ")", 2 ) end
|
||||
|
||||
local sValueTy = type(value)
|
||||
if sValueTy ~= "number" and sValueTy ~= "string" and sValueTy ~= "boolean" and sValueTy ~= "table" then
|
||||
error( "bad argument #2 (expected value, got " .. sValueTy .. ")", 2 )
|
||||
end
|
||||
if sValueTy == "table" then
|
||||
-- Ensure value is serializeable
|
||||
value = textutils.unserialize( textutils.serialize(value) )
|
||||
end
|
||||
tSettings[ sName ] = value
|
||||
end
|
||||
|
||||
local copy
|
||||
function copy( value )
|
||||
if type(value) == "table" then
|
||||
local result = {}
|
||||
for k,v in pairs(value) do
|
||||
result[k] = copy(v)
|
||||
end
|
||||
return result
|
||||
else
|
||||
return value
|
||||
end
|
||||
end
|
||||
|
||||
function get( sName, default )
|
||||
if type(sName) ~= "string" then
|
||||
error( "bad argument #1 (expected string, got " .. type( sName ) .. ")", 2 )
|
||||
end
|
||||
local result = tSettings[ sName ]
|
||||
if result ~= nil then
|
||||
return copy(result)
|
||||
else
|
||||
return default
|
||||
end
|
||||
end
|
||||
|
||||
function unset( sName )
|
||||
if type(sName) ~= "string" then
|
||||
error( "bad argument #1 (expected string, got " .. type( sName ) .. ")", 2 )
|
||||
end
|
||||
tSettings[ sName ] = nil
|
||||
end
|
||||
|
||||
function clear()
|
||||
tSettings = {}
|
||||
end
|
||||
|
||||
function getNames()
|
||||
local result = {}
|
||||
for k,v in pairs( tSettings ) do
|
||||
result[ #result + 1 ] = k
|
||||
end
|
||||
table.sort(result)
|
||||
return result
|
||||
end
|
||||
|
||||
function load( sPath )
|
||||
if type(sPath) ~= "string" then
|
||||
error( "bad argument #1 (expected string, got " .. type( sPath ) .. ")", 2 )
|
||||
end
|
||||
local file = fs.open( sPath, "r" )
|
||||
if not file then
|
||||
return false
|
||||
end
|
||||
|
||||
local sText = file.readAll()
|
||||
file.close()
|
||||
|
||||
local tFile = textutils.unserialize( sText )
|
||||
if type(tFile) ~= "table" then
|
||||
return false
|
||||
end
|
||||
|
||||
for k,v in pairs(tFile) do
|
||||
if type(k) == "string" and
|
||||
(type(v) == "string" or type(v) == "number" or type(v) == "boolean" or type(v) == "table") then
|
||||
set( k, v )
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function save( sPath )
|
||||
if type(sPath) ~= "string" then
|
||||
error( "bad argument #1 (expected string, got " .. type( sPath ) .. ")", 2 )
|
||||
end
|
||||
local file = fs.open( sPath, "w" )
|
||||
if not file then
|
||||
return false
|
||||
end
|
||||
|
||||
file.write( textutils.serialize( tSettings ) )
|
||||
file.close()
|
||||
|
||||
return true
|
||||
end
|
||||
61
src/main/resources/data/computercraft/lua/rom/apis/term.lua
Normal file
61
src/main/resources/data/computercraft/lua/rom/apis/term.lua
Normal file
@@ -0,0 +1,61 @@
|
||||
|
||||
local native = (term.native and term.native()) or term
|
||||
local redirectTarget = native
|
||||
|
||||
local function wrap( _sFunction )
|
||||
return function( ... )
|
||||
return redirectTarget[ _sFunction ]( ... )
|
||||
end
|
||||
end
|
||||
|
||||
local term = {}
|
||||
|
||||
term.redirect = function( target )
|
||||
if type( target ) ~= "table" then
|
||||
error( "bad argument #1 (expected table, got " .. type( target ) .. ")", 2 )
|
||||
end
|
||||
if target == term then
|
||||
error( "term is not a recommended redirect target, try term.current() instead", 2 )
|
||||
end
|
||||
for k,v in pairs( native ) do
|
||||
if type( k ) == "string" and type( v ) == "function" then
|
||||
if type( target[k] ) ~= "function" then
|
||||
target[k] = function()
|
||||
error( "Redirect object is missing method "..k..".", 2 )
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
local oldRedirectTarget = redirectTarget
|
||||
redirectTarget = target
|
||||
return oldRedirectTarget
|
||||
end
|
||||
|
||||
term.current = function()
|
||||
return redirectTarget
|
||||
end
|
||||
|
||||
term.native = function()
|
||||
-- NOTE: please don't use this function unless you have to.
|
||||
-- If you're running in a redirected or multitasked enviorment, term.native() will NOT be
|
||||
-- the current terminal when your program starts up. It is far better to use term.current()
|
||||
return native
|
||||
end
|
||||
|
||||
-- Some methods shouldn't go through redirects, so we move them to the main
|
||||
-- term API.
|
||||
for _, method in ipairs { "nativePaletteColor", "nativePaletteColour"} do
|
||||
term[method] = native[method]
|
||||
native[method] = nil
|
||||
end
|
||||
|
||||
for k,v in pairs( native ) do
|
||||
if type( k ) == "string" and type( v ) == "function" and term[k] == nil then
|
||||
term[k] = wrap( k )
|
||||
end
|
||||
end
|
||||
|
||||
local env = _ENV
|
||||
for k,v in pairs( term ) do
|
||||
env[k] = v
|
||||
end
|
||||
455
src/main/resources/data/computercraft/lua/rom/apis/textutils.lua
Normal file
455
src/main/resources/data/computercraft/lua/rom/apis/textutils.lua
Normal file
@@ -0,0 +1,455 @@
|
||||
|
||||
function slowWrite( sText, nRate )
|
||||
if nRate ~= nil and type( nRate ) ~= "number" then
|
||||
error( "bad argument #2 (expected number, got " .. type( nRate ) .. ")", 2 )
|
||||
end
|
||||
nRate = nRate or 20
|
||||
if nRate < 0 then
|
||||
error( "Rate must be positive", 2 )
|
||||
end
|
||||
local nSleep = 1 / nRate
|
||||
|
||||
sText = tostring( sText )
|
||||
local x,y = term.getCursorPos()
|
||||
local len = string.len( sText )
|
||||
|
||||
for n=1,len do
|
||||
term.setCursorPos( x, y )
|
||||
sleep( nSleep )
|
||||
local nLines = write( string.sub( sText, 1, n ) )
|
||||
local newX, newY = term.getCursorPos()
|
||||
y = newY - nLines
|
||||
end
|
||||
end
|
||||
|
||||
function slowPrint( sText, nRate )
|
||||
slowWrite( sText, nRate )
|
||||
print()
|
||||
end
|
||||
|
||||
function formatTime( nTime, bTwentyFourHour )
|
||||
if type( nTime ) ~= "number" then
|
||||
error( "bad argument #1 (expected number, got " .. type( nTime ) .. ")", 2 )
|
||||
end
|
||||
if bTwentyFourHour ~= nil and type( bTwentyFourHour ) ~= "boolean" then
|
||||
error( "bad argument #2 (expected boolean, got " .. type( bTwentyFourHour ) .. ")", 2 )
|
||||
end
|
||||
local sTOD = nil
|
||||
if not bTwentyFourHour then
|
||||
if nTime >= 12 then
|
||||
sTOD = "PM"
|
||||
else
|
||||
sTOD = "AM"
|
||||
end
|
||||
if nTime >= 13 then
|
||||
nTime = nTime - 12
|
||||
end
|
||||
end
|
||||
|
||||
local nHour = math.floor(nTime)
|
||||
local nMinute = math.floor((nTime - nHour)*60)
|
||||
if sTOD then
|
||||
return string.format( "%d:%02d %s", nHour, nMinute, sTOD )
|
||||
else
|
||||
return string.format( "%d:%02d", nHour, nMinute )
|
||||
end
|
||||
end
|
||||
|
||||
local function makePagedScroll( _term, _nFreeLines )
|
||||
local nativeScroll = _term.scroll
|
||||
local nFreeLines = _nFreeLines or 0
|
||||
return function( _n )
|
||||
for n=1,_n do
|
||||
nativeScroll( 1 )
|
||||
|
||||
if nFreeLines <= 0 then
|
||||
local w,h = _term.getSize()
|
||||
_term.setCursorPos( 1, h )
|
||||
_term.write( "Press any key to continue" )
|
||||
os.pullEvent( "key" )
|
||||
_term.clearLine()
|
||||
_term.setCursorPos( 1, h )
|
||||
else
|
||||
nFreeLines = nFreeLines - 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function pagedPrint( _sText, _nFreeLines )
|
||||
if _nFreeLines ~= nil and type( _nFreeLines ) ~= "number" then
|
||||
error( "bad argument #2 (expected number, got " .. type( _nFreeLines ) .. ")", 2 )
|
||||
end
|
||||
-- Setup a redirector
|
||||
local oldTerm = term.current()
|
||||
local newTerm = {}
|
||||
for k,v in pairs( oldTerm ) do
|
||||
newTerm[k] = v
|
||||
end
|
||||
newTerm.scroll = makePagedScroll( oldTerm, _nFreeLines )
|
||||
term.redirect( newTerm )
|
||||
|
||||
-- Print the text
|
||||
local result
|
||||
local ok, err = pcall( function()
|
||||
if _sText ~= nil then
|
||||
result = print( _sText )
|
||||
else
|
||||
result = print()
|
||||
end
|
||||
end )
|
||||
|
||||
-- Removed the redirector
|
||||
term.redirect( oldTerm )
|
||||
|
||||
-- Propogate errors
|
||||
if not ok then
|
||||
error( err, 0 )
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
local function tabulateCommon( bPaged, ... )
|
||||
local tAll = { ... }
|
||||
for k,v in ipairs( tAll ) do
|
||||
if type( v ) ~= "number" and type( v ) ~= "table" then
|
||||
error( "bad argument #"..k.." (expected number or table, got " .. type( v ) .. ")", 3 )
|
||||
end
|
||||
end
|
||||
|
||||
local w,h = term.getSize()
|
||||
local nMaxLen = w / 8
|
||||
for n, t in ipairs( tAll ) do
|
||||
if type(t) == "table" then
|
||||
for nu, sItem in pairs(t) do
|
||||
if type( sItem ) ~= "string" then
|
||||
error( "bad argument #"..n.."."..nu.." (expected string, got " .. type( sItem ) .. ")", 3 )
|
||||
end
|
||||
nMaxLen = math.max( string.len( sItem ) + 1, nMaxLen )
|
||||
end
|
||||
end
|
||||
end
|
||||
local nCols = math.floor( w / nMaxLen )
|
||||
local nLines = 0
|
||||
local function newLine()
|
||||
if bPaged and nLines >= (h-3) then
|
||||
pagedPrint()
|
||||
else
|
||||
print()
|
||||
end
|
||||
nLines = nLines + 1
|
||||
end
|
||||
|
||||
local function drawCols( _t )
|
||||
local nCol = 1
|
||||
for n, s in ipairs( _t ) do
|
||||
if nCol > nCols then
|
||||
nCol = 1
|
||||
newLine()
|
||||
end
|
||||
|
||||
local cx, cy = term.getCursorPos()
|
||||
cx = 1 + ((nCol - 1) * nMaxLen)
|
||||
term.setCursorPos( cx, cy )
|
||||
term.write( s )
|
||||
|
||||
nCol = nCol + 1
|
||||
end
|
||||
print()
|
||||
end
|
||||
for n, t in ipairs( tAll ) do
|
||||
if type(t) == "table" then
|
||||
if #t > 0 then
|
||||
drawCols( t )
|
||||
end
|
||||
elseif type(t) == "number" then
|
||||
term.setTextColor( t )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function tabulate( ... )
|
||||
tabulateCommon( false, ... )
|
||||
end
|
||||
|
||||
function pagedTabulate( ... )
|
||||
tabulateCommon( true, ... )
|
||||
end
|
||||
|
||||
local g_tLuaKeywords = {
|
||||
[ "and" ] = true,
|
||||
[ "break" ] = true,
|
||||
[ "do" ] = true,
|
||||
[ "else" ] = true,
|
||||
[ "elseif" ] = true,
|
||||
[ "end" ] = true,
|
||||
[ "false" ] = true,
|
||||
[ "for" ] = true,
|
||||
[ "function" ] = true,
|
||||
[ "if" ] = true,
|
||||
[ "in" ] = true,
|
||||
[ "local" ] = true,
|
||||
[ "nil" ] = true,
|
||||
[ "not" ] = true,
|
||||
[ "or" ] = true,
|
||||
[ "repeat" ] = true,
|
||||
[ "return" ] = true,
|
||||
[ "then" ] = true,
|
||||
[ "true" ] = true,
|
||||
[ "until" ] = true,
|
||||
[ "while" ] = true,
|
||||
}
|
||||
|
||||
local function serializeImpl( t, tTracking, sIndent )
|
||||
local sType = type(t)
|
||||
if sType == "table" then
|
||||
if tTracking[t] ~= nil then
|
||||
error( "Cannot serialize table with recursive entries", 0 )
|
||||
end
|
||||
tTracking[t] = true
|
||||
|
||||
if next(t) == nil then
|
||||
-- Empty tables are simple
|
||||
return "{}"
|
||||
else
|
||||
-- Other tables take more work
|
||||
local sResult = "{\n"
|
||||
local sSubIndent = sIndent .. " "
|
||||
local tSeen = {}
|
||||
for k,v in ipairs(t) do
|
||||
tSeen[k] = true
|
||||
sResult = sResult .. sSubIndent .. serializeImpl( v, tTracking, sSubIndent ) .. ",\n"
|
||||
end
|
||||
for k,v in pairs(t) do
|
||||
if not tSeen[k] then
|
||||
local sEntry
|
||||
if type(k) == "string" and not g_tLuaKeywords[k] and string.match( k, "^[%a_][%a%d_]*$" ) then
|
||||
sEntry = k .. " = " .. serializeImpl( v, tTracking, sSubIndent ) .. ",\n"
|
||||
else
|
||||
sEntry = "[ " .. serializeImpl( k, tTracking, sSubIndent ) .. " ] = " .. serializeImpl( v, tTracking, sSubIndent ) .. ",\n"
|
||||
end
|
||||
sResult = sResult .. sSubIndent .. sEntry
|
||||
end
|
||||
end
|
||||
sResult = sResult .. sIndent .. "}"
|
||||
return sResult
|
||||
end
|
||||
|
||||
elseif sType == "string" then
|
||||
return string.format( "%q", t )
|
||||
|
||||
elseif sType == "number" or sType == "boolean" or sType == "nil" then
|
||||
return tostring(t)
|
||||
|
||||
else
|
||||
error( "Cannot serialize type "..sType, 0 )
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
empty_json_array = {}
|
||||
|
||||
local function serializeJSONImpl( t, tTracking, bNBTStyle )
|
||||
local sType = type(t)
|
||||
if t == empty_json_array then
|
||||
return "[]"
|
||||
|
||||
elseif sType == "table" then
|
||||
if tTracking[t] ~= nil then
|
||||
error( "Cannot serialize table with recursive entries", 0 )
|
||||
end
|
||||
tTracking[t] = true
|
||||
|
||||
if next(t) == nil then
|
||||
-- Empty tables are simple
|
||||
return "{}"
|
||||
else
|
||||
-- Other tables take more work
|
||||
local sObjectResult = "{"
|
||||
local sArrayResult = "["
|
||||
local nObjectSize = 0
|
||||
local nArraySize = 0
|
||||
for k,v in pairs(t) do
|
||||
if type(k) == "string" then
|
||||
local sEntry
|
||||
if bNBTStyle then
|
||||
sEntry = tostring(k) .. ":" .. serializeJSONImpl( v, tTracking, bNBTStyle )
|
||||
else
|
||||
sEntry = string.format( "%q", k ) .. ":" .. serializeJSONImpl( v, tTracking, bNBTStyle )
|
||||
end
|
||||
if nObjectSize == 0 then
|
||||
sObjectResult = sObjectResult .. sEntry
|
||||
else
|
||||
sObjectResult = sObjectResult .. "," .. sEntry
|
||||
end
|
||||
nObjectSize = nObjectSize + 1
|
||||
end
|
||||
end
|
||||
for n,v in ipairs(t) do
|
||||
local sEntry = serializeJSONImpl( v, tTracking, bNBTStyle )
|
||||
if nArraySize == 0 then
|
||||
sArrayResult = sArrayResult .. sEntry
|
||||
else
|
||||
sArrayResult = sArrayResult .. "," .. sEntry
|
||||
end
|
||||
nArraySize = nArraySize + 1
|
||||
end
|
||||
sObjectResult = sObjectResult .. "}"
|
||||
sArrayResult = sArrayResult .. "]"
|
||||
if nObjectSize > 0 or nArraySize == 0 then
|
||||
return sObjectResult
|
||||
else
|
||||
return sArrayResult
|
||||
end
|
||||
end
|
||||
|
||||
elseif sType == "string" then
|
||||
return string.format( "%q", t )
|
||||
|
||||
elseif sType == "number" or sType == "boolean" then
|
||||
return tostring(t)
|
||||
|
||||
else
|
||||
error( "Cannot serialize type "..sType, 0 )
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
function serialize( t )
|
||||
local tTracking = {}
|
||||
return serializeImpl( t, tTracking, "" )
|
||||
end
|
||||
|
||||
function unserialize( s )
|
||||
if type( s ) ~= "string" then
|
||||
error( "bad argument #1 (expected string, got " .. type( s ) .. ")", 2 )
|
||||
end
|
||||
local func = load( "return "..s, "unserialize", "t", {} )
|
||||
if func then
|
||||
local ok, result = pcall( func )
|
||||
if ok then
|
||||
return result
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function serializeJSON( t, bNBTStyle )
|
||||
if type( t ) ~= "table" and type( t ) ~= "string" and type( t ) ~= "number" and type( t ) ~= "boolean" then
|
||||
error( "bad argument #1 (expected table/string/number/boolean, got " .. type( t ) .. ")", 2 )
|
||||
end
|
||||
if bNBTStyle ~= nil and type( bNBTStyle ) ~= "boolean" then
|
||||
error( "bad argument #2 (expected boolean, got " .. type( bNBTStyle ) .. ")", 2 )
|
||||
end
|
||||
local tTracking = {}
|
||||
return serializeJSONImpl( t, tTracking, bNBTStyle or false )
|
||||
end
|
||||
|
||||
function urlEncode( str )
|
||||
if type( str ) ~= "string" then
|
||||
error( "bad argument #1 (expected string, got " .. type( str ) .. ")", 2 )
|
||||
end
|
||||
if str then
|
||||
str = string.gsub(str, "\n", "\r\n")
|
||||
str = string.gsub(str, "([^A-Za-z0-9 %-%_%.])", function(c)
|
||||
local n = string.byte(c)
|
||||
if n < 128 then
|
||||
-- ASCII
|
||||
return string.format("%%%02X", n)
|
||||
else
|
||||
-- Non-ASCII (encode as UTF-8)
|
||||
return
|
||||
string.format("%%%02X", 192 + bit32.band( bit32.arshift(n,6), 31 ) ) ..
|
||||
string.format("%%%02X", 128 + bit32.band( n, 63 ) )
|
||||
end
|
||||
end )
|
||||
str = string.gsub(str, " ", "+")
|
||||
end
|
||||
return str
|
||||
end
|
||||
|
||||
local tEmpty = {}
|
||||
function complete( sSearchText, tSearchTable )
|
||||
if type( sSearchText ) ~= "string" then
|
||||
error( "bad argument #1 (expected string, got " .. type( sSearchText ) .. ")", 2 )
|
||||
end
|
||||
if tSearchTable ~= nil and type( tSearchTable ) ~= "table" then
|
||||
error( "bad argument #2 (expected table, got " .. type( tSearchTable ) .. ")", 2 )
|
||||
end
|
||||
|
||||
if g_tLuaKeywords[sSearchText] then return tEmpty end
|
||||
local nStart = 1
|
||||
local nDot = string.find( sSearchText, ".", nStart, true )
|
||||
local tTable = tSearchTable or _ENV
|
||||
while nDot do
|
||||
local sPart = string.sub( sSearchText, nStart, nDot - 1 )
|
||||
local value = tTable[ sPart ]
|
||||
if type( value ) == "table" then
|
||||
tTable = value
|
||||
nStart = nDot + 1
|
||||
nDot = string.find( sSearchText, ".", nStart, true )
|
||||
else
|
||||
return tEmpty
|
||||
end
|
||||
end
|
||||
local nColon = string.find( sSearchText, ":", nStart, true )
|
||||
if nColon then
|
||||
local sPart = string.sub( sSearchText, nStart, nColon - 1 )
|
||||
local value = tTable[ sPart ]
|
||||
if type( value ) == "table" then
|
||||
tTable = value
|
||||
nStart = nColon + 1
|
||||
else
|
||||
return tEmpty
|
||||
end
|
||||
end
|
||||
|
||||
local sPart = string.sub( sSearchText, nStart )
|
||||
local nPartLength = string.len( sPart )
|
||||
|
||||
local tResults = {}
|
||||
local tSeen = {}
|
||||
while tTable do
|
||||
for k,v in pairs( tTable ) do
|
||||
if not tSeen[k] and type(k) == "string" then
|
||||
if string.find( k, sPart, 1, true ) == 1 then
|
||||
if not g_tLuaKeywords[k] and string.match( k, "^[%a_][%a%d_]*$" ) then
|
||||
local sResult = string.sub( k, nPartLength + 1 )
|
||||
if nColon then
|
||||
if type(v) == "function" then
|
||||
table.insert( tResults, sResult .. "(" )
|
||||
elseif type(v) == "table" then
|
||||
local tMetatable = getmetatable( v )
|
||||
if tMetatable and ( type( tMetatable.__call ) == "function" or type( tMetatable.__call ) == "table" ) then
|
||||
table.insert( tResults, sResult .. "(" )
|
||||
end
|
||||
end
|
||||
else
|
||||
if type(v) == "function" then
|
||||
sResult = sResult .. "("
|
||||
elseif type(v) == "table" and next(v) ~= nil then
|
||||
sResult = sResult .. "."
|
||||
end
|
||||
table.insert( tResults, sResult )
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
tSeen[k] = true
|
||||
end
|
||||
local tMetatable = getmetatable( tTable )
|
||||
if tMetatable and type( tMetatable.__index ) == "table" then
|
||||
tTable = tMetatable.__index
|
||||
else
|
||||
tTable = nil
|
||||
end
|
||||
end
|
||||
|
||||
table.sort( tResults )
|
||||
return tResults
|
||||
end
|
||||
|
||||
-- GB versions
|
||||
serialise = serialize
|
||||
unserialise = unserialize
|
||||
serialiseJSON = serializeJSON
|
||||
@@ -0,0 +1,34 @@
|
||||
|
||||
if not turtle then
|
||||
error( "Cannot load turtle API on computer", 2 )
|
||||
end
|
||||
native = turtle.native or turtle
|
||||
|
||||
local function addCraftMethod( object )
|
||||
if peripheral.getType( "left" ) == "workbench" then
|
||||
object.craft = function( ... )
|
||||
return peripheral.call( "left", "craft", ... )
|
||||
end
|
||||
elseif peripheral.getType( "right" ) == "workbench" then
|
||||
object.craft = function( ... )
|
||||
return peripheral.call( "right", "craft", ... )
|
||||
end
|
||||
else
|
||||
object.craft = nil
|
||||
end
|
||||
end
|
||||
|
||||
-- Put commands into environment table
|
||||
local env = _ENV
|
||||
for k,v in pairs( native ) do
|
||||
if k == "equipLeft" or k == "equipRight" then
|
||||
env[k] = function( ... )
|
||||
local result, err = v( ... )
|
||||
addCraftMethod( turtle )
|
||||
return result, err
|
||||
end
|
||||
else
|
||||
env[k] = v
|
||||
end
|
||||
end
|
||||
addCraftMethod( env )
|
||||
@@ -0,0 +1,85 @@
|
||||
|
||||
local vector = {
|
||||
add = function( self, o )
|
||||
return vector.new(
|
||||
self.x + o.x,
|
||||
self.y + o.y,
|
||||
self.z + o.z
|
||||
)
|
||||
end,
|
||||
sub = function( self, o )
|
||||
return vector.new(
|
||||
self.x - o.x,
|
||||
self.y - o.y,
|
||||
self.z - o.z
|
||||
)
|
||||
end,
|
||||
mul = function( self, m )
|
||||
return vector.new(
|
||||
self.x * m,
|
||||
self.y * m,
|
||||
self.z * m
|
||||
)
|
||||
end,
|
||||
div = function( self, m )
|
||||
return vector.new(
|
||||
self.x / m,
|
||||
self.y / m,
|
||||
self.z / m
|
||||
)
|
||||
end,
|
||||
unm = function( self )
|
||||
return vector.new(
|
||||
-self.x,
|
||||
-self.y,
|
||||
-self.z
|
||||
)
|
||||
end,
|
||||
dot = function( self, o )
|
||||
return self.x*o.x + self.y*o.y + self.z*o.z
|
||||
end,
|
||||
cross = function( self, o )
|
||||
return vector.new(
|
||||
self.y*o.z - self.z*o.y,
|
||||
self.z*o.x - self.x*o.z,
|
||||
self.x*o.y - self.y*o.x
|
||||
)
|
||||
end,
|
||||
length = function( self )
|
||||
return math.sqrt( self.x*self.x + self.y*self.y + self.z*self.z )
|
||||
end,
|
||||
normalize = function( self )
|
||||
return self:mul( 1 / self:length() )
|
||||
end,
|
||||
round = function( self, nTolerance )
|
||||
nTolerance = nTolerance or 1.0
|
||||
return vector.new(
|
||||
math.floor( (self.x + (nTolerance * 0.5)) / nTolerance ) * nTolerance,
|
||||
math.floor( (self.y + (nTolerance * 0.5)) / nTolerance ) * nTolerance,
|
||||
math.floor( (self.z + (nTolerance * 0.5)) / nTolerance ) * nTolerance
|
||||
)
|
||||
end,
|
||||
tostring = function( self )
|
||||
return self.x..","..self.y..","..self.z
|
||||
end,
|
||||
}
|
||||
|
||||
local vmetatable = {
|
||||
__index = vector,
|
||||
__add = vector.add,
|
||||
__sub = vector.sub,
|
||||
__mul = vector.mul,
|
||||
__div = vector.div,
|
||||
__unm = vector.unm,
|
||||
__tostring = vector.tostring,
|
||||
}
|
||||
|
||||
function new( x, y, z )
|
||||
local v = {
|
||||
x = tonumber(x) or 0,
|
||||
y = tonumber(y) or 0,
|
||||
z = tonumber(z) or 0
|
||||
}
|
||||
setmetatable( v, vmetatable )
|
||||
return v
|
||||
end
|
||||
480
src/main/resources/data/computercraft/lua/rom/apis/window.lua
Normal file
480
src/main/resources/data/computercraft/lua/rom/apis/window.lua
Normal file
@@ -0,0 +1,480 @@
|
||||
|
||||
local tHex = {
|
||||
[ colors.white ] = "0",
|
||||
[ colors.orange ] = "1",
|
||||
[ colors.magenta ] = "2",
|
||||
[ colors.lightBlue ] = "3",
|
||||
[ colors.yellow ] = "4",
|
||||
[ colors.lime ] = "5",
|
||||
[ colors.pink ] = "6",
|
||||
[ colors.gray ] = "7",
|
||||
[ colors.lightGray ] = "8",
|
||||
[ colors.cyan ] = "9",
|
||||
[ colors.purple ] = "a",
|
||||
[ colors.blue ] = "b",
|
||||
[ colors.brown ] = "c",
|
||||
[ colors.green ] = "d",
|
||||
[ colors.red ] = "e",
|
||||
[ colors.black ] = "f",
|
||||
}
|
||||
|
||||
local type = type
|
||||
local string_rep = string.rep
|
||||
local string_sub = string.sub
|
||||
local table_unpack = table.unpack
|
||||
|
||||
function create( parent, nX, nY, nWidth, nHeight, bStartVisible )
|
||||
if type( parent ) ~= "table" then error( "bad argument #1 (expected table, got " .. type( parent ) .. ")", 2 ) end
|
||||
if type( nX ) ~= "number" then error( "bad argument #2 (expected number, got " .. type( nX ) .. ")", 2 ) end
|
||||
if type( nY ) ~= "number" then error( "bad argument #3 (expected number, got " .. type( nY ) .. ")", 2 ) end
|
||||
if type( nWidth ) ~= "number" then error( "bad argument #4 (expected number, got " .. type( nWidth ) .. ")", 2 ) end
|
||||
if type( nHeight ) ~= "number" then error( "bad argument #5 (expected number, got " .. type( nHeight ) .. ")", 2 ) end
|
||||
if bStartVisible ~= nil and type( bStartVisible ) ~= "boolean" then error( "bad argument #6 (expected boolean, got " .. type( bStartVisible ) .. ")", 2 ) end
|
||||
|
||||
if parent == term then
|
||||
error( "term is not a recommended window parent, try term.current() instead", 2 )
|
||||
end
|
||||
|
||||
local sEmptySpaceLine
|
||||
local tEmptyColorLines = {}
|
||||
local function createEmptyLines( nWidth )
|
||||
sEmptySpaceLine = string_rep( " ", nWidth )
|
||||
for n=0,15 do
|
||||
local nColor = 2^n
|
||||
local sHex = tHex[nColor]
|
||||
tEmptyColorLines[nColor] = string_rep( sHex, nWidth )
|
||||
end
|
||||
end
|
||||
|
||||
createEmptyLines( nWidth )
|
||||
|
||||
-- Setup
|
||||
local bVisible = (bStartVisible ~= false)
|
||||
local nCursorX = 1
|
||||
local nCursorY = 1
|
||||
local bCursorBlink = false
|
||||
local nTextColor = colors.white
|
||||
local nBackgroundColor = colors.black
|
||||
local tLines = {}
|
||||
local tPalette = {}
|
||||
do
|
||||
local sEmptyText = sEmptySpaceLine
|
||||
local sEmptyTextColor = tEmptyColorLines[ nTextColor ]
|
||||
local sEmptyBackgroundColor = tEmptyColorLines[ nBackgroundColor ]
|
||||
for y=1,nHeight do
|
||||
tLines[y] = {
|
||||
text = sEmptyText,
|
||||
textColor = sEmptyTextColor,
|
||||
backgroundColor = sEmptyBackgroundColor,
|
||||
}
|
||||
end
|
||||
|
||||
for i=0,15 do
|
||||
local c = 2 ^ i
|
||||
tPalette[c] = { parent.getPaletteColour( c ) }
|
||||
end
|
||||
end
|
||||
|
||||
-- Helper functions
|
||||
local function updateCursorPos()
|
||||
if nCursorX >= 1 and nCursorY >= 1 and
|
||||
nCursorX <= nWidth and nCursorY <= nHeight then
|
||||
parent.setCursorPos( nX + nCursorX - 1, nY + nCursorY - 1 )
|
||||
else
|
||||
parent.setCursorPos( 0, 0 )
|
||||
end
|
||||
end
|
||||
|
||||
local function updateCursorBlink()
|
||||
parent.setCursorBlink( bCursorBlink )
|
||||
end
|
||||
|
||||
local function updateCursorColor()
|
||||
parent.setTextColor( nTextColor )
|
||||
end
|
||||
|
||||
local function redrawLine( n )
|
||||
local tLine = tLines[ n ]
|
||||
parent.setCursorPos( nX, nY + n - 1 )
|
||||
parent.blit( tLine.text, tLine.textColor, tLine.backgroundColor )
|
||||
end
|
||||
|
||||
local function redraw()
|
||||
for n=1,nHeight do
|
||||
redrawLine( n )
|
||||
end
|
||||
end
|
||||
|
||||
local function updatePalette()
|
||||
for k,v in pairs( tPalette ) do
|
||||
parent.setPaletteColour( k, v[1], v[2], v[3] )
|
||||
end
|
||||
end
|
||||
|
||||
local function internalBlit( sText, sTextColor, sBackgroundColor )
|
||||
local nStart = nCursorX
|
||||
local nEnd = nStart + #sText - 1
|
||||
if nCursorY >= 1 and nCursorY <= nHeight then
|
||||
if nStart <= nWidth and nEnd >= 1 then
|
||||
-- Modify line
|
||||
local tLine = tLines[ nCursorY ]
|
||||
if nStart == 1 and nEnd == nWidth then
|
||||
tLine.text = sText
|
||||
tLine.textColor = sTextColor
|
||||
tLine.backgroundColor = sBackgroundColor
|
||||
else
|
||||
local sClippedText, sClippedTextColor, sClippedBackgroundColor
|
||||
if nStart < 1 then
|
||||
local nClipStart = 1 - nStart + 1
|
||||
local nClipEnd = nWidth - nStart + 1
|
||||
sClippedText = string_sub( sText, nClipStart, nClipEnd )
|
||||
sClippedTextColor = string_sub( sTextColor, nClipStart, nClipEnd )
|
||||
sClippedBackgroundColor = string_sub( sBackgroundColor, nClipStart, nClipEnd )
|
||||
elseif nEnd > nWidth then
|
||||
local nClipEnd = nWidth - nStart + 1
|
||||
sClippedText = string_sub( sText, 1, nClipEnd )
|
||||
sClippedTextColor = string_sub( sTextColor, 1, nClipEnd )
|
||||
sClippedBackgroundColor = string_sub( sBackgroundColor, 1, nClipEnd )
|
||||
else
|
||||
sClippedText = sText
|
||||
sClippedTextColor = sTextColor
|
||||
sClippedBackgroundColor = sBackgroundColor
|
||||
end
|
||||
|
||||
local sOldText = tLine.text
|
||||
local sOldTextColor = tLine.textColor
|
||||
local sOldBackgroundColor = tLine.backgroundColor
|
||||
local sNewText, sNewTextColor, sNewBackgroundColor
|
||||
if nStart > 1 then
|
||||
local nOldEnd = nStart - 1
|
||||
sNewText = string_sub( sOldText, 1, nOldEnd ) .. sClippedText
|
||||
sNewTextColor = string_sub( sOldTextColor, 1, nOldEnd ) .. sClippedTextColor
|
||||
sNewBackgroundColor = string_sub( sOldBackgroundColor, 1, nOldEnd ) .. sClippedBackgroundColor
|
||||
else
|
||||
sNewText = sClippedText
|
||||
sNewTextColor = sClippedTextColor
|
||||
sNewBackgroundColor = sClippedBackgroundColor
|
||||
end
|
||||
if nEnd < nWidth then
|
||||
local nOldStart = nEnd + 1
|
||||
sNewText = sNewText .. string_sub( sOldText, nOldStart, nWidth )
|
||||
sNewTextColor = sNewTextColor .. string_sub( sOldTextColor, nOldStart, nWidth )
|
||||
sNewBackgroundColor = sNewBackgroundColor .. string_sub( sOldBackgroundColor, nOldStart, nWidth )
|
||||
end
|
||||
|
||||
tLine.text = sNewText
|
||||
tLine.textColor = sNewTextColor
|
||||
tLine.backgroundColor = sNewBackgroundColor
|
||||
end
|
||||
|
||||
-- Redraw line
|
||||
if bVisible then
|
||||
redrawLine( nCursorY )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Move and redraw cursor
|
||||
nCursorX = nEnd + 1
|
||||
if bVisible then
|
||||
updateCursorColor()
|
||||
updateCursorPos()
|
||||
end
|
||||
end
|
||||
|
||||
-- Terminal implementation
|
||||
local window = {}
|
||||
|
||||
function window.write( sText )
|
||||
sText = tostring( sText )
|
||||
internalBlit( sText, string_rep( tHex[ nTextColor ], #sText ), string_rep( tHex[ nBackgroundColor ], #sText ) )
|
||||
end
|
||||
|
||||
function window.blit( sText, sTextColor, sBackgroundColor )
|
||||
if type( sText ) ~= "string" then error( "bad argument #1 (expected string, got " .. type( sText ) .. ")", 2 ) end
|
||||
if type( sTextColor ) ~= "string" then error( "bad argument #2 (expected string, got " .. type( sTextColor ) .. ")", 2 ) end
|
||||
if type( sBackgroundColor ) ~= "string" then error( "bad argument #3 (expected string, got " .. type( sBackgroundColor ) .. ")", 2 ) end
|
||||
if #sTextColor ~= #sText or #sBackgroundColor ~= #sText then
|
||||
error( "Arguments must be the same length", 2 )
|
||||
end
|
||||
internalBlit( sText, sTextColor, sBackgroundColor )
|
||||
end
|
||||
|
||||
function window.clear()
|
||||
local sEmptyText = sEmptySpaceLine
|
||||
local sEmptyTextColor = tEmptyColorLines[ nTextColor ]
|
||||
local sEmptyBackgroundColor = tEmptyColorLines[ nBackgroundColor ]
|
||||
for y=1,nHeight do
|
||||
tLines[y] = {
|
||||
text = sEmptyText,
|
||||
textColor = sEmptyTextColor,
|
||||
backgroundColor = sEmptyBackgroundColor,
|
||||
}
|
||||
end
|
||||
if bVisible then
|
||||
redraw()
|
||||
updateCursorColor()
|
||||
updateCursorPos()
|
||||
end
|
||||
end
|
||||
|
||||
function window.clearLine()
|
||||
if nCursorY >= 1 and nCursorY <= nHeight then
|
||||
local sEmptyText = sEmptySpaceLine
|
||||
local sEmptyTextColor = tEmptyColorLines[ nTextColor ]
|
||||
local sEmptyBackgroundColor = tEmptyColorLines[ nBackgroundColor ]
|
||||
tLines[ nCursorY ] = {
|
||||
text = sEmptyText,
|
||||
textColor = sEmptyTextColor,
|
||||
backgroundColor = sEmptyBackgroundColor,
|
||||
}
|
||||
if bVisible then
|
||||
redrawLine( nCursorY )
|
||||
updateCursorColor()
|
||||
updateCursorPos()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function window.getCursorPos()
|
||||
return nCursorX, nCursorY
|
||||
end
|
||||
|
||||
function window.setCursorPos( x, y )
|
||||
if type( x ) ~= "number" then error( "bad argument #1 (expected number, got " .. type( x ) .. ")", 2 ) end
|
||||
if type( y ) ~= "number" then error( "bad argument #2 (expected number, got " .. type( y ) .. ")", 2 ) end
|
||||
nCursorX = math.floor( x )
|
||||
nCursorY = math.floor( y )
|
||||
if bVisible then
|
||||
updateCursorPos()
|
||||
end
|
||||
end
|
||||
|
||||
function window.setCursorBlink( blink )
|
||||
if type( blink ) ~= "boolean" then error( "bad argument #1 (expected boolean, got " .. type( blink ) .. ")", 2 ) end
|
||||
bCursorBlink = blink
|
||||
if bVisible then
|
||||
updateCursorBlink()
|
||||
end
|
||||
end
|
||||
|
||||
function window.getCursorBlink()
|
||||
return bCursorBlink
|
||||
end
|
||||
|
||||
local function isColor()
|
||||
return parent.isColor()
|
||||
end
|
||||
|
||||
function window.isColor()
|
||||
return isColor()
|
||||
end
|
||||
|
||||
function window.isColour()
|
||||
return isColor()
|
||||
end
|
||||
|
||||
local function setTextColor( color )
|
||||
if type( color ) ~= "number" then
|
||||
error( "bad argument #1 (expected number, got " .. type( color ) .. ")", 2 )
|
||||
elseif tHex[color] == nil then
|
||||
error( "Invalid color (got " .. color .. ")" , 2 )
|
||||
end
|
||||
nTextColor = color
|
||||
if bVisible then
|
||||
updateCursorColor()
|
||||
end
|
||||
end
|
||||
|
||||
window.setTextColor = setTextColor
|
||||
window.setTextColour = setTextColor
|
||||
|
||||
function window.setPaletteColour( colour, r, g, b )
|
||||
if type( colour ) ~= "number" then error( "bad argument #1 (expected number, got " .. type( colour ) .. ")", 2 ) end
|
||||
|
||||
if tHex[colour] == nil then
|
||||
error( "Invalid color (got " .. colour .. ")" , 2 )
|
||||
end
|
||||
|
||||
local tCol
|
||||
if type(r) == "number" and g == nil and b == nil then
|
||||
tCol = { colours.unpackRGB( r ) }
|
||||
tPalette[ colour ] = tCol
|
||||
else
|
||||
if type( r ) ~= "number" then error( "bad argument #2 (expected number, got " .. type( r ) .. ")", 2 ) end
|
||||
if type( g ) ~= "number" then error( "bad argument #3 (expected number, got " .. type( g ) .. ")", 2 ) end
|
||||
if type( b ) ~= "number" then error( "bad argument #4 (expected number, got " .. type( b ) .. ")", 2 ) end
|
||||
|
||||
tCol = tPalette[ colour ]
|
||||
tCol[1] = r
|
||||
tCol[2] = g
|
||||
tCol[3] = b
|
||||
end
|
||||
|
||||
if bVisible then
|
||||
return parent.setPaletteColour( colour, tCol[1], tCol[2], tCol[3] )
|
||||
end
|
||||
end
|
||||
|
||||
window.setPaletteColor = window.setPaletteColour
|
||||
|
||||
function window.getPaletteColour( colour )
|
||||
if type( colour ) ~= "number" then error( "bad argument #1 (expected number, got " .. type( colour ) .. ")", 2 ) end
|
||||
if tHex[colour] == nil then
|
||||
error( "Invalid color (got " .. colour .. ")" , 2 )
|
||||
end
|
||||
local tCol = tPalette[ colour ]
|
||||
return tCol[1], tCol[2], tCol[3]
|
||||
end
|
||||
|
||||
window.getPaletteColor = window.getPaletteColour
|
||||
|
||||
local function setBackgroundColor( color )
|
||||
if type( color ) ~= "number" then
|
||||
error( "bad argument #1 (expected number, got " .. type( color ) .. ")", 2 )
|
||||
elseif tHex[color] == nil then
|
||||
error( "Invalid color (got " .. color .. ")", 2 )
|
||||
end
|
||||
nBackgroundColor = color
|
||||
end
|
||||
|
||||
window.setBackgroundColor = setBackgroundColor
|
||||
window.setBackgroundColour = setBackgroundColor
|
||||
|
||||
function window.getSize()
|
||||
return nWidth, nHeight
|
||||
end
|
||||
|
||||
function window.scroll( n )
|
||||
if type( n ) ~= "number" then error( "bad argument #1 (expected number, got " .. type( n ) .. ")", 2 ) end
|
||||
if n ~= 0 then
|
||||
local tNewLines = {}
|
||||
local sEmptyText = sEmptySpaceLine
|
||||
local sEmptyTextColor = tEmptyColorLines[ nTextColor ]
|
||||
local sEmptyBackgroundColor = tEmptyColorLines[ nBackgroundColor ]
|
||||
for newY=1,nHeight do
|
||||
local y = newY + n
|
||||
if y >= 1 and y <= nHeight then
|
||||
tNewLines[newY] = tLines[y]
|
||||
else
|
||||
tNewLines[newY] = {
|
||||
text = sEmptyText,
|
||||
textColor = sEmptyTextColor,
|
||||
backgroundColor = sEmptyBackgroundColor,
|
||||
}
|
||||
end
|
||||
end
|
||||
tLines = tNewLines
|
||||
if bVisible then
|
||||
redraw()
|
||||
updateCursorColor()
|
||||
updateCursorPos()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function window.getTextColor()
|
||||
return nTextColor
|
||||
end
|
||||
|
||||
function window.getTextColour()
|
||||
return nTextColor
|
||||
end
|
||||
|
||||
function window.getBackgroundColor()
|
||||
return nBackgroundColor
|
||||
end
|
||||
|
||||
function window.getBackgroundColour()
|
||||
return nBackgroundColor
|
||||
end
|
||||
|
||||
-- Other functions
|
||||
function window.setVisible( bVis )
|
||||
if type( bVis ) ~= "boolean" then error( "bad argument #1 (expected boolean, got " .. type( bVis ) .. ")", 2 ) end
|
||||
if bVisible ~= bVis then
|
||||
bVisible = bVis
|
||||
if bVisible then
|
||||
window.redraw()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function window.redraw()
|
||||
if bVisible then
|
||||
redraw()
|
||||
updatePalette()
|
||||
updateCursorBlink()
|
||||
updateCursorColor()
|
||||
updateCursorPos()
|
||||
end
|
||||
end
|
||||
|
||||
function window.restoreCursor()
|
||||
if bVisible then
|
||||
updateCursorBlink()
|
||||
updateCursorColor()
|
||||
updateCursorPos()
|
||||
end
|
||||
end
|
||||
|
||||
function window.getPosition()
|
||||
return nX, nY
|
||||
end
|
||||
|
||||
function window.reposition( nNewX, nNewY, nNewWidth, nNewHeight )
|
||||
if type( nNewX ) ~= "number" then error( "bad argument #1 (expected number, got " .. type( nNewX ) .. ")", 2 ) end
|
||||
if type( nNewY ) ~= "number" then error( "bad argument #2 (expected number, got " .. type( nNewY ) .. ")", 2 ) end
|
||||
if nNewWidth ~= nil or nNewHeight ~= nil then
|
||||
if type( nNewWidth ) ~= "number" then error( "bad argument #3 (expected number, got " .. type( nNewWidth ) .. ")", 2 ) end
|
||||
if type( nNewHeight ) ~= "number" then error( "bad argument #4 (expected number, got " .. type( nNewHeight ) .. ")", 2 ) end
|
||||
end
|
||||
|
||||
nX = nNewX
|
||||
nY = nNewY
|
||||
if nNewWidth and nNewHeight then
|
||||
local tNewLines = {}
|
||||
createEmptyLines( nNewWidth )
|
||||
local sEmptyText = sEmptySpaceLine
|
||||
local sEmptyTextColor = tEmptyColorLines[ nTextColor ]
|
||||
local sEmptyBackgroundColor = tEmptyColorLines[ nBackgroundColor ]
|
||||
for y=1,nNewHeight do
|
||||
if y > nHeight then
|
||||
tNewLines[y] = {
|
||||
text = sEmptyText,
|
||||
textColor = sEmptyTextColor,
|
||||
backgroundColor = sEmptyBackgroundColor
|
||||
}
|
||||
else
|
||||
local tOldLine = tLines[y]
|
||||
if nNewWidth == nWidth then
|
||||
tNewLines[y] = tOldLine
|
||||
elseif nNewWidth < nWidth then
|
||||
tNewLines[y] = {
|
||||
text = string_sub( tOldLine.text, 1, nNewWidth ),
|
||||
textColor = string_sub( tOldLine.textColor, 1, nNewWidth ),
|
||||
backgroundColor = string_sub( tOldLine.backgroundColor, 1, nNewWidth ),
|
||||
}
|
||||
else
|
||||
tNewLines[y] = {
|
||||
text = tOldLine.text .. string_sub( sEmptyText, nWidth + 1, nNewWidth ),
|
||||
textColor = tOldLine.textColor .. string_sub( sEmptyTextColor, nWidth + 1, nNewWidth ),
|
||||
backgroundColor = tOldLine.backgroundColor .. string_sub( sEmptyBackgroundColor, nWidth + 1, nNewWidth ),
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
nWidth = nNewWidth
|
||||
nHeight = nNewHeight
|
||||
tLines = tNewLines
|
||||
end
|
||||
if bVisible then
|
||||
window.redraw()
|
||||
end
|
||||
end
|
||||
|
||||
if bVisible then
|
||||
window.redraw()
|
||||
end
|
||||
return window
|
||||
end
|
||||
@@ -0,0 +1,4 @@
|
||||
--[[
|
||||
Alright then, don't ignore me. This file is to ensure the existence of the "autorun" folder, files placed in this folder
|
||||
using resource packs will always run when computers startup.
|
||||
]]
|
||||
@@ -0,0 +1 @@
|
||||
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"
|
||||
@@ -0,0 +1,6 @@
|
||||
alias assigns shell commands to run other programs.
|
||||
|
||||
ex:
|
||||
"alias dir ls" will make the "dir" command run the "ls" program
|
||||
"alias dir" will remove the alias set on "dir"
|
||||
"alias" will list all current aliases.
|
||||
@@ -0,0 +1,4 @@
|
||||
apis lists the currently loaded APIs available to programs in CraftOS.
|
||||
|
||||
Type "help <api>" to see help for a specific api.
|
||||
Call os.loadAPI( path ) to load extra apis.
|
||||
@@ -0,0 +1,5 @@
|
||||
bg is a program for Advanced Computers which opens a new tab in the background.
|
||||
|
||||
ex:
|
||||
"bg" will open a background tab running the shell
|
||||
"bg worm" will open a background tab running the "worm" program
|
||||
@@ -0,0 +1,7 @@
|
||||
Functions in the bit manipulation API (NOTE: This API will be removed in a future version. Use bit32 instead):
|
||||
bit.bnot(n) -- bitwise not (~n)
|
||||
bit.band(m, n) -- bitwise and (m & n)
|
||||
bit.bor(m, n) -- bitwise or (m | n)
|
||||
bit.bxor(m, n) -- bitwise xor (m ^ n)
|
||||
bit.brshift(n, bits) -- right shift (n >> bits)
|
||||
bit.blshift(n, bits) -- left shift (n << bits)
|
||||
@@ -0,0 +1,15 @@
|
||||
To set bundled outputs:
|
||||
c = colors.combine( colors.red, colors.blue )
|
||||
rs.setBundledOutput( "left", c )
|
||||
|
||||
c = colors.combine( c, colors.green )
|
||||
rs.setBundledOutput( "left", c )
|
||||
|
||||
c = colors.subtract( c, colors.blue )
|
||||
rs.setBundledOutput( "left", c )
|
||||
|
||||
To get bundled inputs:
|
||||
c = rs.getBundledInput( "right" )
|
||||
red = colors.test( c, colors.red )
|
||||
|
||||
Type "help colors" for the list of wire colors.
|
||||
@@ -0,0 +1,6 @@
|
||||
cd changes the directory you're in.
|
||||
|
||||
ex:
|
||||
"cd rom" will move to "rom" folder.
|
||||
"cd .." will move up one folder.
|
||||
"cd /" will move to the root.
|
||||
368
src/main/resources/data/computercraft/lua/rom/help/changelog.txt
Normal file
368
src/main/resources/data/computercraft/lua/rom/help/changelog.txt
Normal file
@@ -0,0 +1,368 @@
|
||||
New Features in ComputerCraft 1.80:
|
||||
|
||||
* Added .getResponseHeaders() to HTTP responses.
|
||||
* Return a HTTP response when a HTTP error occurs.
|
||||
* Added a GUI to change ComputerCraft config options.
|
||||
* os.time() and os.day() now accept parameters to give the real world time.
|
||||
* Added os.epoch()
|
||||
* Monitor text now glows in the dark.
|
||||
* Added a "Pocket Computer upgrade API" so mod developers can add their own pocket upgrades.
|
||||
* Added pocket.equipBack()/pocket.unequipBack() to add/remove pocket upgrades.
|
||||
* Added term.setPaletteColor()/term.getPaletteColor() to change/check colors
|
||||
* Added colors.rgb8()/colours.rgb8()
|
||||
* Performance improvements to fs.find
|
||||
* Requires the player to be interacting with the computer when typing
|
||||
* Disk labels are limited to 32 characters
|
||||
* Labels can now only include characters within the printable range ( to ~)
|
||||
* Various model improvements
|
||||
* There is now a configurable file descriptor limit
|
||||
* Threads are now daemon threads
|
||||
* Termination signals are now sent unless the computer is off
|
||||
* Fixed compilation errors
|
||||
* Now handles tile entity changes
|
||||
* GPS coordinates now have to be numbers
|
||||
* Turtle upgrades now act as tools and peripherals
|
||||
* The Filesystem.list result is now sorted
|
||||
* The number of values to unpack can now be manually specified
|
||||
* Small terminal & monitor rendering improvements
|
||||
* General improvements to the documentation
|
||||
* Redstone inputs are no longer reset when adding peripherals
|
||||
* Turtles now use tinting
|
||||
* shell.resolveProgram now picks up on *.lua files
|
||||
* Fixed a handful of bugs in ComputerCraft
|
||||
* Added speaker block, turtle upgrade, pocket upgrade, and peripheral api
|
||||
* Startup can now be a directory containing multiple startup files
|
||||
* Added .getLabel to the computer peripheral
|
||||
|
||||
New Features in ComputerCraft 1.79:
|
||||
|
||||
* Ported ComputerCraftEdu to Minecraft 1.8.9
|
||||
* Fixed a handful of bugs in ComputerCraft
|
||||
|
||||
New Features in ComputerCraft 1.77:
|
||||
|
||||
* Ported to Minecraft 1.8.9
|
||||
* Added "settings" API
|
||||
* Added "set" and "wget" programs
|
||||
* Added settings to disable multishell, startup scripts, and tab completion on a per-computer basis. The default values for these settings can be customised in ComputerCraft.cfg
|
||||
* All Computer and Turtle items except Command Computers can now be mounted in Disk Drives
|
||||
|
||||
New Features in ComputerCraft 1.76:
|
||||
|
||||
* Ported to Minecraft 1.8
|
||||
* Added Ender Modems for cross-dimensional communication
|
||||
* Fixed handling of 8-bit characters. All the characters in the ISO 8859-1 codepage can now be displayed
|
||||
* Added some extra graphical characters in the unused character positions, including a suite of characters for Teletext style drawing
|
||||
* Added support for the new commands in Minecraft 1.8 to the Command Computer
|
||||
* The return values of turtle.inspect() and commands.getBlockInfo() now include blockstate information
|
||||
* Added commands.getBlockInfos() function for Command Computers
|
||||
* Added new "peripherals" program
|
||||
* Replaced the "_CC_VERSION" and "_MC_VERSION" constants with a new "_HOST" constant
|
||||
* Shortened the length of time that "Ctrl+T", "Ctrl+S" and "Ctrl+R" must be held down for to terminate, shutdown and reboot the computer
|
||||
* textutils.serialiseJSON() now takes an optional parameter allowing it to produce JSON text with unquoted object keys. This is used by all autogenerated methods in the "commands" api except for "title" and "tellraw"
|
||||
* Fixed many bugs
|
||||
|
||||
New Features in ComputerCraft 1.75:
|
||||
|
||||
* Fixed monitors sometimes rendering without part of their text.
|
||||
* Fixed a regression in the "bit" API.
|
||||
|
||||
New Features in ComputerCraft 1.74:
|
||||
|
||||
* Added tab completion to "edit", "lua" and the shell.
|
||||
* Added textutils.complete(), fs.complete(), shell.complete(), shell.setCompletionFunction() and help.complete().
|
||||
* Added tab completion options to read().
|
||||
* Added "key_up" and "mouse_up" events.
|
||||
* Non-advanced terminals now accept both grey colours.
|
||||
* Added term.getTextColour(), term.getBackgroundColour() and term.blit().
|
||||
* Improved the performance of text rendering on Advanced Computers.
|
||||
* Added a "Run" button to the edit program on Advanced Computers.
|
||||
* Turtles can now push players and entities (configurable).
|
||||
* Turtles now respect server spawn protection (configurable).
|
||||
* Added a turtle permissions API for mod authors.
|
||||
* Implemented a subset of the Lua 5.2 API so programs can be written against it now, ahead of a future Lua version upgrade.
|
||||
* Added a config option to disable parts of the Lua 5.1 API which will be removed when a future Lua version upgrade happens.
|
||||
* Command Computers can no longer be broken by survival players.
|
||||
* Fixed the "pick block" key not working on ComputerCraft items in creative mode.
|
||||
* Fixed the "edit" program being hard to use on certain European keyboards.
|
||||
* Added "_CC_VERSION" and "_MC_VERSION" constants.
|
||||
|
||||
New Features in ComputerCraft 1.73:
|
||||
|
||||
* The "exec" program, commands.exec() and all related Command Computer functions now return the console output of the command.
|
||||
* Fixed two multiplayer crash bugs.
|
||||
|
||||
New Features in ComputerCraft 1.7:
|
||||
|
||||
* Added Command Computers
|
||||
* Added new API: commands
|
||||
* Added new programs: commands, exec
|
||||
* Added textutils.serializeJSON()
|
||||
* Added ILuaContext.executeMainThreadTask() for peripheral developers
|
||||
* Disk Drives and Printers can now be renamed with Anvils
|
||||
* Fixed various bugs, crashes and exploits
|
||||
* Fixed problems with HD texture packs
|
||||
* Documented the new features in the in-game help
|
||||
|
||||
New Features in ComputerCraft 1.65:
|
||||
|
||||
* Fixed a multiplayer-only crash with turtle.place()
|
||||
* Fixed some problems with http.post()
|
||||
* Fixed fs.getDrive() returning incorrect results on remote peripherals
|
||||
|
||||
New Features in ComputerCraft 1.64:
|
||||
|
||||
* Ported to Minecraft 1.7.10
|
||||
* New turtle functions: turtle.inspect(), turtle.inspectUp(), turtle.inspectDown(), turtle.getItemDetail()
|
||||
* Lots of bug and crash fixes, a huge stability improvement over previous versions
|
||||
|
||||
New Features in ComputerCraft 1.63:
|
||||
|
||||
* Turtles can now be painted with dyes, and cleaned with water buckets
|
||||
* Added a new game: Redirection - ComputerCraft Edition
|
||||
* Turtle label nameplates now only show when the Turtle is moused-over
|
||||
* The HTTP API is now enabled by default, and can be configured with a whitelist of permitted domains
|
||||
* http.get() and http.post() now accept parameters to control the request headers
|
||||
* New fs function: fs.getDir( path )
|
||||
* Fixed some bugs
|
||||
|
||||
New Features in ComputerCraft 1.62:
|
||||
|
||||
* Added IRC-style commands to the "chat" program
|
||||
* Fixed some bugs and crashes
|
||||
|
||||
New Features in ComputerCraft 1.6:
|
||||
|
||||
* Added Pocket Computers
|
||||
* Added a multi-tasking system for Advanced Computers and Turtles
|
||||
* Turtles can now swap out their tools and peripherals at runtime
|
||||
* Turtles can now carry two tools or peripherals at once in any combination
|
||||
* Turtles and Computers can now be labelled using Name Tags and Anvils
|
||||
* Added a configurable fuel limit for Turtles
|
||||
* Added hostnames, protocols and long distance routing to the rednet API
|
||||
* Added a peer-to-peer chat program to demonstrate new rednet capabilities
|
||||
* Added a new game, only on Pocket Computers: "falling" by GopherATL
|
||||
* File system commands in the shell now accept wildcard arguments
|
||||
* The shell now accepts long arguments in quotes
|
||||
* Terminal redirection now no longer uses a stack-based system. Instead: term.current() gets the current terminal object and term.redirect() replaces it. term.restore() has been removed.
|
||||
* Added a new Windowing API for addressing sub-areas of the terminal
|
||||
* New programs: fg, bg, multishell, chat, repeat, redstone, equip, unequip
|
||||
* Improved programs: copy, move, delete, rename, paint, shell
|
||||
* Removed programs: redset, redprobe, redpulse
|
||||
* New APIs: window, multishell
|
||||
* New turtle functions: turtle.equipLeft() and turtle.equipRight()
|
||||
* New peripheral functions: peripheral.find( [type] )
|
||||
* New rednet functions: rednet.host( protocol, hostname ), rednet.unhost( protocol ), rednet.locate( protocol, [hostname] )
|
||||
* New fs function: fs.find( wildcard )
|
||||
* New shell functions: shell.openTab(), shell.switchTab( [number] )
|
||||
* New event "term_resize" fired when the size of a terminal changes
|
||||
* Improved rednet functions: rednet.send(), rednet.broadcast() and rednet.receive() now take optional protocol parameters
|
||||
* turtle.craft(0) and turtle.refuel(0) now return true if there is a valid recipe or fuel item, but do not craft of refuel anything
|
||||
* turtle.suck( [limit] ) can now be used to limit the number of items picked up
|
||||
* Users of turtle.dig() and turtle.attack() can now specify which side of the turtle to look for a tool to use (by default, both will be considered)
|
||||
* textutils.serialise( text ) now produces human-readable output
|
||||
* Refactored most of the codebase and fixed many old bugs and instabilities, turtles should never ever lose their content now
|
||||
* Fixed the "turtle_inventory" event firing when it shouldn't have
|
||||
* Added error messages to many more turtle functions after they return false
|
||||
* Documented all new programs and API changes in the "help" system
|
||||
|
||||
New Features in ComputerCraft 1.58:
|
||||
|
||||
* Fixed a long standing bug where turtles could lose their identify if they travel too far away
|
||||
* Fixed use of deprecated code, ensuring mod compatibility with the latest versions of Minecraft Forge, and world compatibility with future versions of Minecraft
|
||||
|
||||
New Features in ComputerCraft 1.57:
|
||||
|
||||
* Ported to Minecraft 1.6.4
|
||||
* Added two new Treasure Disks: Conway's Game of Life by vilsol and Protector by fredthead
|
||||
* Fixed a very nasty item duplication bug
|
||||
|
||||
New Features in ComputerCraft 1.56:
|
||||
|
||||
* Added Treasure Disks: Floppy Disks in dungeons which contain interesting community made programs. Find them all!
|
||||
* All turtle functions now return additional error messages when they fail.
|
||||
* Resource Packs with Lua Programs can now be edited when extracted to a folder, for easier editing.
|
||||
|
||||
New Features in ComputerCraft 1.55:
|
||||
|
||||
* Ported to Minecraft 1.6.2
|
||||
* Added Advanced Turtles
|
||||
* Added "turtle_inventory" event. Fires when any change is made to the inventory of a turtle
|
||||
* Added missing functions io.close, io.flush, io.input, io.lines, io.output
|
||||
* Tweaked the screen colours used by Advanced Computers, Monitors and Turtles
|
||||
* Added new features for Peripheral authors
|
||||
* Lua programs can now be included in Resource Packs
|
||||
|
||||
New Features in ComputerCraft 1.52:
|
||||
|
||||
* Ported to Minecraft 1.5.1
|
||||
|
||||
New Features in ComputerCraft 1.51:
|
||||
|
||||
* Ported to Minecraft 1.5
|
||||
* Added Wired Modems
|
||||
* Added Networking Cables
|
||||
* Made Wireless Modems more expensive to craft
|
||||
* New redstone API functions: getAnalogInput(), setAnalogOutput(), getAnalogOutput()
|
||||
* Peripherals can now be controlled remotely over wired networks. New peripheral API function: getNames()
|
||||
* New event: "monitor_resize" when the size of a monitor changes
|
||||
* Except for labelled computers and turtles, ComputerCraft blocks no longer drop items in creative mode
|
||||
* The pick block function works in creative mode now works for all ComputerCraft blocks
|
||||
* All blocks and items now use the IDs numbers assigned by FTB by default
|
||||
* Fixed turtles sometimes placing blocks with incorrect orientations
|
||||
* Fixed Wireless modems being able to send messages to themselves
|
||||
* Fixed turtle.attack() having a very short range
|
||||
* Various bugfixes
|
||||
|
||||
New Features in ComputerCraft 1.5:
|
||||
|
||||
* 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
|
||||
* Floppy Disks can now be dyed with multiple dyes, just like armour
|
||||
* The "excavate" program now retains fuel in it's inventory, so can run unattended
|
||||
* turtle.place() now tries all possible block orientations before failing
|
||||
* turtle.refuel(0) returns true if a fuel item is selected
|
||||
* turtle.craft(0) returns true if the inventory is a valid recipe
|
||||
* The in-game help system now has documentation for all the peripherals and their methods, including the new modem functionality
|
||||
* A romantic surprise
|
||||
|
||||
New Features in ComputerCraft 1.48:
|
||||
|
||||
* Ported to Minecraft 1.4.6
|
||||
* Advanced Monitors now emit a "monitor_touch" event when right clicked
|
||||
* Advanced Monitors are now cheaper to craft
|
||||
* Turtles now get slightly less fuel from items
|
||||
* Computers can now interact with Command Blocks (if enabled in ComputerCraft.cfg)
|
||||
* New API function: os.day()
|
||||
* A christmas surprise
|
||||
|
||||
New Features in ComputerCraft 1.45:
|
||||
|
||||
* Added Advanced Computers
|
||||
* Added Advanced Monitors
|
||||
* New program: paint by nitrogenfingers
|
||||
* New API: paintutils
|
||||
* New term functions: term.setBackgroundColor, term.setTextColor, term.isColor
|
||||
* New turtle function: turtle.transferTo
|
||||
|
||||
New Features in ComputerCraft 1.43:
|
||||
|
||||
* Added Printed Pages
|
||||
* Added Printed Books
|
||||
* Fixed incompatibility with Forge 275 and above
|
||||
* Labelled Turtles now keep their fuel when broken
|
||||
|
||||
New Features in ComputerCraft 1.42:
|
||||
|
||||
* Ported to Minecraft 1.3.2
|
||||
* Added Printers
|
||||
* Floppy Disks can be dyed different colours
|
||||
* Wireless Crafty Turtles can now be crafted
|
||||
* New textures
|
||||
* New forge config file
|
||||
* Bug fixes
|
||||
|
||||
New Features in ComputerCraft 1.4:
|
||||
|
||||
* Ported to Forge Mod Loader. ComputerCraft can now be ran directly from the .zip without extraction
|
||||
* Added Farming Turtles
|
||||
* Added Felling Turtles
|
||||
* Added Digging Turtles
|
||||
* Added Melee Turtles
|
||||
* Added Crafty Turtles
|
||||
* Added 14 new Turtle Combinations accessible by combining the turtle upgrades above
|
||||
* Labelled computers and turtles can now be crafted into turtles or other turtle types without losing their ID, label and data
|
||||
* Added a "Turtle Upgrade API" for mod developers to create their own tools and peripherals for turtles
|
||||
* Turtles can now attack entities with turtle.attack(), and collect their dropped items
|
||||
* Turtles can now use turtle.place() with any item the player can, and can interact with entities
|
||||
* Turtles can now craft items with turtle.craft()
|
||||
* Turtles can now place items into inventories with turtle.drop()
|
||||
* Changed the behaviour of turtle.place() and turtle.drop() to only consider the currently selected slot
|
||||
* Turtles can now pick up items from the ground, or from inventories, with turtle.suck()
|
||||
* Turtles can now compare items in their inventories
|
||||
* Turtles can place signs with text on them with turtle.place( [signText] )
|
||||
* Turtles now optionally require fuel items to move, and can refuel themselves
|
||||
* The size of the the turtle inventory has been increased to 16
|
||||
* The size of the turtle screen has been increased
|
||||
* New turtle functions: turtle.compareTo( [slotNum] ), turtle.craft(), turtle.attack(), turtle.attackUp(), turtle.attackDown(), turtle.dropUp(), turtle.dropDown(), turtle.getFuelLevel(), turtle.refuel()
|
||||
* New disk function: disk.getID()
|
||||
* New turtle programs: craft, refuel
|
||||
* "excavate" program now much smarter: Will return items to a chest when full, attack mobs, and refuel itself automatically
|
||||
* New API: keys
|
||||
* Added optional Floppy Disk and Hard Drive space limits for computers and turtles
|
||||
* New fs function: fs.getFreeSpace( path ), also fs.getDrive() works again
|
||||
* The send and receive range of wireless modems now increases with altitude, allowing long range networking from high-altitude computers (great for GPS networks)
|
||||
* http.request() now supports https:// URLs
|
||||
* Right clicking a Disk Drive with a Floppy Disk or a Record when sneaking will insert the item into the Disk Drive automatically
|
||||
* The default size of the computer screen has been increased
|
||||
* 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.
|
||||
|
||||
New Features in ComputerCraft 1.31:
|
||||
|
||||
* Ported to Minecraft 1.2.3
|
||||
* Added Monitors (thanks to Cloudy)
|
||||
* Updated LuaJ to a newer, less memory hungry version
|
||||
* rednet_message event now has a third parameter, "distance", to support position triangulation.
|
||||
* New programs: gps, monitor, pastebin.
|
||||
* Added a secret program. Use with large monitors!
|
||||
* New apis: gps, vector
|
||||
* New turtle functions: turtle.compare(), turtle.compareUp(), turtle.compareDown(), turtle.drop( quantity )
|
||||
* New http functions: http.post().
|
||||
* New term functions: term.redirect(), term.restore()
|
||||
* New textutils functions: textutils.urlEncode()
|
||||
* New rednet functions: rednet.isOpen()
|
||||
* New config options: modem_range, modem_rangeDuringStorm
|
||||
* Bug fixes, program tweaks, and help updates
|
||||
|
||||
New Features in ComputerCraft 1.3:
|
||||
|
||||
* Ported to Minecraft Forge
|
||||
* Added Turtles
|
||||
* Added Wireless Modems
|
||||
* Added Mining Turtles
|
||||
* Added Wireless Turtles
|
||||
* Added Wireless Mining Turtles
|
||||
* Computers and Disk Drives no longer get destroyed by water.
|
||||
* Computers and Turtles can now be labelled with the label program, and labelled devices keep their state when destroyed.
|
||||
* Computers/Turtles can connect to adjacent devices, and turn them on and off
|
||||
* User programs now give line numbers in their error messages
|
||||
* New APIs: turtle, peripheral
|
||||
* New programs for turtles: tunnel, excavate, go, turn, dance
|
||||
* New os functions: os.getComputerLabel(), os.setComputerLabel()
|
||||
* Added "filter" parameter to os.pullEvent()
|
||||
* New shell function: shell.getCurrentProgram()
|
||||
* New textutils functions: textutils.serialize(), textutils.unserialize(), textutils.tabulate(), textutils.pagedTabulate(), textutils.slowWrite()
|
||||
* New io file function: file:lines()
|
||||
* New fs function: fs.getSize()
|
||||
* Disk Drives can now play records from other mods
|
||||
* Bug fixes, program tweaks, and help updates
|
||||
|
||||
New Features in ComputerCraft 1.2:
|
||||
|
||||
* Added Disk Drives and Floppy Disks
|
||||
* Added Ctrl+T shortcut to terminate the current program (hold)
|
||||
* Added Ctrl+S shortcut to shutdown the computer (hold)
|
||||
* Added Ctrl+R shortcut to reboot the computer (hold)
|
||||
* New Programs: alias, apis, copy, delete, dj, drive, eject, id, label, list, move, reboot, redset, rename, time, worm.
|
||||
* New APIs: bit, colours, disk, help, rednet, parallel, textutils.
|
||||
* New color functions: colors.combine(), colors.subtract(), colors.test()
|
||||
* New fs functions: fs.getName(), new modes for fs.open()
|
||||
* New os functions: os.loadAPI(), os.unloadAPI(),
|
||||
os.clock(), os.time(), os.setAlarm(),
|
||||
os.reboot(), os.queueEvent()
|
||||
* New redstone function: redstone.getSides()
|
||||
* New shell functions: shell.setPath(), shell.programs(), shell.resolveProgram(), shell.setAlias()
|
||||
* Lots of updates to the help pages
|
||||
* Bug fixes
|
||||
|
||||
New Features in ComputerCraft 1.1:
|
||||
|
||||
* Added Multiplayer support throughout.
|
||||
* Added connectivity with RedPower bundled cables
|
||||
* Added HTTP api, enabled via the mod config, to allow computers to access the real world internet
|
||||
* Added command history to the shell.
|
||||
* Programs which spin in an infinite loop without yielding will no longer freeze minecraft
|
||||
* Help updates and bug fixes
|
||||
|
||||
New Features in ComputerCraft 1.0:
|
||||
|
||||
* First Release!
|
||||
@@ -0,0 +1,5 @@
|
||||
Surf the rednet superhighway with "chat", the networked chat program for CraftOS! Host chatrooms and invite your friends! Requires a Wired or Wireless Modem on each computer. When running chat, type "/help" to see a list of available commands.
|
||||
|
||||
ex:
|
||||
"chat host forgecraft" will create a chatroom with the name "forgecraft"
|
||||
"chat join forgecraft direwolf20" will connect to the chatroom with the name "forgecraft", using the nickname "direwolf20"
|
||||
@@ -0,0 +1 @@
|
||||
clear clears the screen.
|
||||
@@ -0,0 +1,9 @@
|
||||
Functions in the colors api
|
||||
(used for redstone.setBundledOutput):
|
||||
colors.combine( color1, color2, color3, ... )
|
||||
colors.subtract( colors, color1, color2, ... )
|
||||
colors.test( colors, color )
|
||||
colors.rgb8( r, g, b )
|
||||
|
||||
Color constants in the colors api, in ascending bit order:
|
||||
colors.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.
|
||||
@@ -0,0 +1,9 @@
|
||||
Functions in the colours api
|
||||
(used for redstone.setBundledOutput):
|
||||
colours.combine( colour1, colour2, colour3, ...)
|
||||
colours.subtract( colours, colour1, colour2, ...)
|
||||
colours.test( colours, colour )
|
||||
colours.rgb8( r, g, b )
|
||||
|
||||
Colour constants in the colours api, in ascending bit order:
|
||||
colours.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.
|
||||
@@ -0,0 +1,2 @@
|
||||
On a Command Computer, "commands" will list all the commands available for use. Use "exec" to execute them.
|
||||
Type "help commandsapi" for help using commands in lua programs.
|
||||
@@ -0,0 +1,15 @@
|
||||
Functions in the commands API:
|
||||
commands.exec( command )
|
||||
commands.execAsync( command )
|
||||
commands.list()
|
||||
commands.getBlockPosition()
|
||||
commands.getBlockInfo( x, y, z )
|
||||
commands.getBlockInfos( minx, miny, minz, maxx, maxy, maxz )
|
||||
|
||||
The commands API can also be used to invoke commands directly, like so:
|
||||
commands.say( "Hello World" )
|
||||
commands.give( "dan200", "minecraft:diamond", 64 )
|
||||
This works with any command. Use "commands.async" instead of "commands" to execute asynchronously.
|
||||
|
||||
The commands API is only available on Command Computers.
|
||||
Visit http://minecraft.gamepedia.com/Commands for documentation on all commands.
|
||||
@@ -0,0 +1,6 @@
|
||||
cp copies a file or directory from one location to another.
|
||||
|
||||
ex:
|
||||
"cp rom myrom" copies "rom" to "myrom".
|
||||
"cp rom mystuff/rom" copies "rom" to "mystuff/rom".
|
||||
"cp disk/* disk2" copies the contents of one disk to another
|
||||
@@ -0,0 +1,2 @@
|
||||
coroutine is a standard Lua5.1 API.
|
||||
Refer to http://www.lua.org/manual/5.1/ for more information.
|
||||
@@ -0,0 +1,5 @@
|
||||
craft is a program for Crafty Turtles. Craft will craft a stack of items using the current inventory.
|
||||
|
||||
ex:
|
||||
"craft" will craft as many items as possible
|
||||
"craft 5" will craft at most 5 times
|
||||
@@ -0,0 +1,16 @@
|
||||
|
||||
ComputerCraft was created by Daniel "dan200" Ratcliffe, with additional code by Aaron "Cloudy" Mills.
|
||||
Thanks to nitrogenfingers, GopherATL and RamiLego for program contributions.
|
||||
Thanks to Mojang, the Forge team, and the MCP team.
|
||||
Uses LuaJ from http://luaj.sourceforge.net/
|
||||
|
||||
The ComputerCraft 1.76 update was sponsored by MinecraftU and Deep Space.
|
||||
Visit http://www.minecraftu.org and http://www.deepspace.me/space-cadets to find out more.
|
||||
|
||||
Join the ComputerCraft community online at http://www.computercraft.info
|
||||
Follow @DanTwoHundred on Twitter!
|
||||
|
||||
To help contribute to ComputerCraft, browse the source code at https://github.com/dan200/ComputerCraft.
|
||||
|
||||
GitHub Contributors:
|
||||
${gitcontributors}
|
||||
@@ -0,0 +1 @@
|
||||
dance is a program for Turtles. Turtles love to get funky.
|
||||
@@ -0,0 +1,5 @@
|
||||
rm deletes a file or a directory and its contents.
|
||||
|
||||
ex:
|
||||
"rm foo" will delete the file foo.
|
||||
"rm disk/*" will delete the contents of a disk.
|
||||
17
src/main/resources/data/computercraft/lua/rom/help/disk.txt
Normal file
17
src/main/resources/data/computercraft/lua/rom/help/disk.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
Functions in the disk API. These functions are for interacting with disk drives:
|
||||
disk.isPresent( drive )
|
||||
disk.setLabel( drive, label )
|
||||
disk.getLabel( drive )
|
||||
disk.hasData( drive )
|
||||
disk.getMountPath( drive )
|
||||
disk.hasAudio( drive )
|
||||
disk.getAudioTitle( drive )
|
||||
disk.playAudio( drive )
|
||||
disk.stopAudio( )
|
||||
disk.eject( drive )
|
||||
disk.getID( drive )
|
||||
|
||||
Events fired by the disk API:
|
||||
"disk" when a disk or other item is inserted into a disk drive. Argument is the name of the drive
|
||||
"disk_eject" when a disk is removed from a disk drive. Argument is the name of the drive
|
||||
Type "help events" to learn about the event system.
|
||||
@@ -0,0 +1,6 @@
|
||||
dj plays Music Discs from disk drives attached to the computer.
|
||||
|
||||
ex:
|
||||
"dj" or "dj play" plays a random disc.
|
||||
"dj play left" plays the disc in the drive on the left of the computer.
|
||||
"dj stop" stops the current disc.
|
||||
@@ -0,0 +1,5 @@
|
||||
drive tells you which disk drive the current or specified directory is located in.
|
||||
|
||||
ex:
|
||||
"drive" tell you the disk drive of the current directory.
|
||||
"drive foo" tells you the disk drive of the subdirectory "foo"
|
||||
@@ -0,0 +1,19 @@
|
||||
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".
|
||||
|
||||
Methods exposed by the Disk Drive:
|
||||
isDiskPresent()
|
||||
getDiskLabel()
|
||||
setDiskLabel( label )
|
||||
hasData()
|
||||
getMountPath()
|
||||
hasAudio()
|
||||
getAudioTitle()
|
||||
playAudio()
|
||||
stopAudio()
|
||||
ejectDisk()
|
||||
getDiskID()
|
||||
|
||||
Events fired by the Disk Drive:
|
||||
"disk" when a disk or other item is inserted into the drive. Argument is the name of the drive.
|
||||
"disk_eject" when a disk is removed from a drive. Argument is the name of the drive.
|
||||
Type "help events" to learn about the event system.
|
||||
@@ -0,0 +1 @@
|
||||
Mostly harmless.
|
||||
@@ -0,0 +1,4 @@
|
||||
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.
|
||||
|
||||
ex:
|
||||
"edit hello" opens a file called "hello" for editing.
|
||||
@@ -0,0 +1,4 @@
|
||||
eject ejects the contents of an attached disk drive.
|
||||
|
||||
ex:
|
||||
"eject left" ejects the contents of the disk drive to the left of the computer.
|
||||
@@ -0,0 +1,5 @@
|
||||
equip is a program for Turtles and Pocket Computer. equip will equip an item from the Turtle's inventory for use as a tool of peripheral. On a Pocket Computer you don't need to write a side.
|
||||
|
||||
ex:
|
||||
"equip 5 left" will equip the item from slot 5 of the turtle onto the left side of the turtle
|
||||
"equip" on a Pocket Computer will equip the first item from your inventory.
|
||||
@@ -0,0 +1,15 @@
|
||||
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.
|
||||
|
||||
Some events which can occur are:
|
||||
"char" when text is typed on the keyboard. Argument is the character typed.
|
||||
"key" when a key is pressed on the keyboard. Arguments are the keycode and whether the key is a repeat. Compare the keycode to the values in keys API to see which key was pressed.
|
||||
"key_up" when a key is released on the keyboard. Argument is the numerical keycode. Compare to the values in keys API to see which key was released.
|
||||
"paste" when text is pasted from the users keyboard. Argument is the line of text pasted.
|
||||
|
||||
Events only on advanced computers:
|
||||
"mouse_click" when a user clicks the mouse. Arguments are button, xPos, yPos.
|
||||
"mouse_drag" when a user moves the mouse when held. Arguments are button, xPos, yPos.
|
||||
"mouse_up" when a user releases the mouse button. Arguments are button, xPos, yPos.
|
||||
"mouse_scroll" when a user uses the scrollwheel on the mouse. Arguments are direction, xPos, yPos.
|
||||
|
||||
Other APIs and peripherals will emit their own events. See their respective help pages for details.
|
||||
@@ -0,0 +1,4 @@
|
||||
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.
|
||||
|
||||
ex:
|
||||
"excavate 3" will mine a 3x3 shaft.
|
||||
@@ -0,0 +1,7 @@
|
||||
On a Command Computer, "exec" will execute a command as if entered on a command block. Use "commands" to list all the available commands.
|
||||
|
||||
ex:
|
||||
"exec say Hello World"
|
||||
"exec setblock ~0 ~1 ~0 minecraft:dirt"
|
||||
|
||||
Type "help commandsapi" for help using commands in lua programs.
|
||||
@@ -0,0 +1 @@
|
||||
exit will exit the current shell.
|
||||
@@ -0,0 +1 @@
|
||||
"From Russia with Fun" comes a fun, new, suspiciously-familiar falling block game for CraftOS. Only on Pocket Computers!
|
||||
@@ -0,0 +1,5 @@
|
||||
fg is a program for Advanced Computers which opens a new tab in the foreground.
|
||||
|
||||
ex:
|
||||
"fg" will open a foreground tab running the shell
|
||||
"fg worm" will open a foreground tab running the "worm" program
|
||||
40
src/main/resources/data/computercraft/lua/rom/help/fs.txt
Normal file
40
src/main/resources/data/computercraft/lua/rom/help/fs.txt
Normal file
@@ -0,0 +1,40 @@
|
||||
Functions in the Filesystem API:
|
||||
fs.list( path )
|
||||
fs.find( wildcard )
|
||||
fs.exists( path )
|
||||
fs.isDir( path )
|
||||
fs.isReadOnly( path )
|
||||
fs.getDir( path )
|
||||
fs.getName( path )
|
||||
fs.getSize( path )
|
||||
fs.getDrive( path )
|
||||
fs.getFreeSpace( path )
|
||||
fs.makeDir( path )
|
||||
fs.move( path, path )
|
||||
fs.copy( path, path )
|
||||
fs.delete( path )
|
||||
fs.combine( path, localpath )
|
||||
fs.open( path, mode )
|
||||
fs.complete( path, location )
|
||||
Available fs.open() modes are "r", "w", "a", "rb", "wb" and "ab".
|
||||
|
||||
Functions on files opened with mode "r":
|
||||
readLine()
|
||||
readAll()
|
||||
close()
|
||||
read( number )
|
||||
|
||||
Functions on files opened with mode "w" or "a":
|
||||
write( string )
|
||||
writeLine( string )
|
||||
flush()
|
||||
close()
|
||||
|
||||
Functions on files opened with mode "rb":
|
||||
read()
|
||||
close()
|
||||
|
||||
Functions on files opened with mode "wb" or "ab":
|
||||
write( byte )
|
||||
flush()
|
||||
close()
|
||||
@@ -0,0 +1,6 @@
|
||||
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.
|
||||
|
||||
ex:
|
||||
"go forward" moves the turtle 1 space forward.
|
||||
"go forward 3" moves the turtle 3 spaces forward.
|
||||
"go forward 3 up left 2" moves the turtle 3 spaces forward, 1 spaces up, then left 180 degrees.
|
||||
10
src/main/resources/data/computercraft/lua/rom/help/gps.txt
Normal file
10
src/main/resources/data/computercraft/lua/rom/help/gps.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
gps can be used to host a GPS server, or to determine a position using trilateration.
|
||||
Type "help gpsapi" for help using GPS functions in lua programs.
|
||||
|
||||
ex:
|
||||
"gps locate" will connect to nearby GPS servers, and try to determine the position of the computer or turtle.
|
||||
"gps host" will try to determine the position, and host a GPS server if successful.
|
||||
"gps host 10 20 30" will host a GPS server, using the manually entered position 10,20,30.
|
||||
|
||||
Take care when manually entering host positions. If the positions entered into multiple GPS hosts
|
||||
are not consistent, the results of locate calls will be incorrect.
|
||||
@@ -0,0 +1,4 @@
|
||||
Functions in the GPS API:
|
||||
gps.locate( timeout )
|
||||
|
||||
The 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.
|
||||
@@ -0,0 +1 @@
|
||||
hello prints the text "Hello World!" to the screen.
|
||||
@@ -0,0 +1,4 @@
|
||||
help is the help tool you're currently using.
|
||||
Type "help index" to see all help topics.
|
||||
Type "help" to see the help intro.
|
||||
Type "help helpapi" for information on the help Lua API.
|
||||
@@ -0,0 +1,5 @@
|
||||
Functions in the help API:
|
||||
help.setPath( path )
|
||||
help.lookup( topic )
|
||||
help.topics()
|
||||
help.completeTopic( topic )
|
||||
@@ -0,0 +1,9 @@
|
||||
Functions in the HTTP API:
|
||||
http.checkURL( url )
|
||||
http.checkURLAsync( url )
|
||||
http.request( url, [postData], [headers] )
|
||||
http.get( url, [headers] )
|
||||
http.post( url, postData, [headers] )
|
||||
|
||||
The HTTP API may be disabled in ComputerCraft.cfg
|
||||
A period of time after a http.request() call is made, a "http_success" or "http_failure" event will be raised. Arguments are the url and a file handle if successful. Arguments are nil, an error message, and (optionally) a file handle if the request failed. http.get() and http.post() block until this event fires instead.
|
||||
@@ -0,0 +1,5 @@
|
||||
id prints the unique identifier of this computer, or a Disk in an attached Disk Drive.
|
||||
|
||||
ex:
|
||||
"id" will print this Computers ID and label
|
||||
"id left" will print the ID and label of the disk in the Disk Drive on the left
|
||||
@@ -0,0 +1,7 @@
|
||||
Welcome to CraftOS!
|
||||
Type "programs" to see the programs you can run.
|
||||
Type "help <program>" to see help for a specific program.
|
||||
Type "help programming" to learn about programming.
|
||||
Type "help whatsnew" to find out about new features.
|
||||
Type "help credits" to learn who made all this.
|
||||
Type "help index" to see all help topics.
|
||||
@@ -0,0 +1,2 @@
|
||||
io is a standard Lua5.1 API, reimplemented for CraftOS. Not all the features are availiable.
|
||||
Refer to http://www.lua.org/manual/5.1/ for more information.
|
||||
@@ -0,0 +1,9 @@
|
||||
The keys API contains constants for all the key codes that can be returned by the "key" event:
|
||||
|
||||
Example usage:
|
||||
local sEvent, nKey = os.pullEvent()
|
||||
if sEvent == "key" and nKey == keys.enter then
|
||||
-- Do something
|
||||
end
|
||||
|
||||
See http://www.minecraftwiki.net/wiki/Key_codes, or the source code, for a complete reference.
|
||||
@@ -0,0 +1,9 @@
|
||||
label gets or sets the label of the Computer, or of Floppy Disks in attached disk drives.
|
||||
|
||||
ex:
|
||||
"label get" prints the label of the computer.
|
||||
"label get left" prints the label of the disk in the left drive.
|
||||
"label set "My Computer"" set the label of the computer to "My Computer".
|
||||
"label set left "My Programs"" - sets the label of the disk in the left drive to "My Programs".
|
||||
"label clear" clears the label of the computer.
|
||||
"label clear left" clears the label of the disk in the left drive.
|
||||
@@ -0,0 +1 @@
|
||||
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.
|
||||
@@ -0,0 +1 @@
|
||||
lua is an interactive prompt for the lua programming language. It's a useful tool for learning the language.
|
||||
@@ -0,0 +1,2 @@
|
||||
math is a standard Lua5.1 API.
|
||||
Refer to http://www.lua.org/manual/5.1/ for more information.
|
||||
@@ -0,0 +1,5 @@
|
||||
mkdir creates a directory in the current location.
|
||||
|
||||
ex:
|
||||
"mkdir foo" creates a directory named "foo".
|
||||
"mkdir ../foo" creates a directory named "foo" in the directory above the current directory.
|
||||
@@ -0,0 +1,12 @@
|
||||
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".
|
||||
|
||||
Methods exposed by Modems:
|
||||
open( channel )
|
||||
isOpen( channel )
|
||||
close( channel )
|
||||
closeAll()
|
||||
transmit( channel, replyChannel, message )
|
||||
isWireless()
|
||||
|
||||
Events fired by Modems:
|
||||
"modem_message" when a message is received on an open channel. Arguments are name, channel, replyChannel, message, distance
|
||||
@@ -0,0 +1,6 @@
|
||||
monitor will connect to an attached Monitor peripheral, and run a program on its display.
|
||||
Type "help monitors" for help using monitors as peripherals in lua programs.
|
||||
|
||||
ex:
|
||||
"monitor left hello" will run the "hello" program on the monitor to the left of the computer.
|
||||
"monitor top edit foo" will run the edit program on the top monitor, editing the file "foo".
|
||||
@@ -0,0 +1,23 @@
|
||||
The Monitor is a peripheral device available for CraftOS. Type "help peripheral" to learn about using the Peripheral API to connect with peripherals. When a Monitor is connected, peripheral.getType() will return "monitor". A wrapped monitor can be used with term.redirect() to send all terminal output to the monitor.
|
||||
|
||||
Methods exposed by the Monitor:
|
||||
write( text )
|
||||
blit( text, textColor, backgroundColor )
|
||||
clear()
|
||||
clearLine()
|
||||
getCursorPos()
|
||||
setCursorPos( x, y )
|
||||
setCursorBlink( blink )
|
||||
isColor()
|
||||
setTextColor( color )
|
||||
setBackgroundColor( color )
|
||||
getTextColor()
|
||||
getBackgroundColor()
|
||||
getSize()
|
||||
scroll( n )
|
||||
setPaletteColor( color, r, g, b )
|
||||
getPaletteColor( color )
|
||||
|
||||
Events fired by the Monitor:
|
||||
"monitor_touch" when an Advanced Monitor is touched by the player. Arguments are name, x, y
|
||||
"monitor_resize" when the size of a Monitor changes. Argument is the name of the monitor.
|
||||
@@ -0,0 +1,6 @@
|
||||
mv moves a file or directory from one location to another.
|
||||
|
||||
ex:
|
||||
"mv foo bar" renames the file "foo" to "bar".
|
||||
"mv foo bar/foo" moves the file "foo" to a folder called "bar".
|
||||
"mv disk/* disk2" moves the contents of one disk to another
|
||||
@@ -0,0 +1,2 @@
|
||||
multishell is the toplevel program on Advanced Computers which manages background tabs.
|
||||
Type "help shellapi" for information about the shell lua api.
|
||||
26
src/main/resources/data/computercraft/lua/rom/help/os.txt
Normal file
26
src/main/resources/data/computercraft/lua/rom/help/os.txt
Normal file
@@ -0,0 +1,26 @@
|
||||
Functions in the os (Operating System) API:
|
||||
os.version()
|
||||
os.getComputerID()
|
||||
os.getComputerLabel()
|
||||
os.setComputerLabel()
|
||||
os.run( environment, programpath, arguments )
|
||||
os.loadAPI( path )
|
||||
os.unloadAPI( name )
|
||||
os.pullEvent( [filter] )
|
||||
os.queueEvent( event, arguments )
|
||||
os.clock()
|
||||
os.startTimer( timeout )
|
||||
os.cancelTimer( token )
|
||||
os.sleep( timeout )
|
||||
os.time( [source] )
|
||||
os.day( [source] )
|
||||
os.epoch( [source] )
|
||||
os.setAlarm( time )
|
||||
os.cancelAlarm( token )
|
||||
os.shutdown()
|
||||
os.reboot()
|
||||
|
||||
Events emitted by the os API:
|
||||
"timer" when a timeout started by os.startTimer() completes. Argument is the token returned by os.startTimer().
|
||||
"alarm" when a time passed to os.setAlarm() is reached. Argument is the token returned by os.setAlarm().
|
||||
Type "help events" to learn about the event system.
|
||||
@@ -0,0 +1,4 @@
|
||||
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.
|
||||
|
||||
ex:
|
||||
"edit mario" opens an image called "mario" for editing.
|
||||
@@ -0,0 +1,7 @@
|
||||
Functions in the Paint Utilities API:
|
||||
paintutils.drawPixel( x, y, colour )
|
||||
paintutils.drawLine( startX, startY, endX, endY, colour )
|
||||
paintutils.drawBox( startX, startY, endX, endY, colour )
|
||||
paintutils.drawFilledBox( startX, startY, endX, endY, colour )
|
||||
paintutils.loadImage( path )
|
||||
paintutils.drawImage( image, x, y )
|
||||
@@ -0,0 +1,4 @@
|
||||
Functions in the Parallel API:
|
||||
parallel.waitForAny( function1, function2, ... )
|
||||
parallel.waitForAll( function1, function2, ... )
|
||||
These methods provide an easy way to run multiple lua functions simultaneously.
|
||||
@@ -0,0 +1,7 @@
|
||||
pastebin is a program for uploading files to and downloading files from pastebin.com. This is useful for sharing programs with other players.
|
||||
The HTTP API must be enabled in ComputerCraft.cfg to use this program.
|
||||
|
||||
ex:
|
||||
"pastebin put foo" will upload the file "foo" to pastebin.com, and print the URL.
|
||||
"pastebin get xq5gc7LB foo" will download the file from the URL http://pastebin.com/xq5gc7LB, and save it as "foo".
|
||||
"pastebin run CxaWmPrX" will download the file from the URL http://pastebin.com/CxaWmPrX, and immediately run it.
|
||||
@@ -0,0 +1,15 @@
|
||||
The peripheral API is for interacting with external peripheral devices. Type "help peripherals" to learn about the peripherals available.
|
||||
|
||||
Functions in the peripheral API:
|
||||
peripheral.getNames()
|
||||
peripheral.isPresent( name )
|
||||
peripheral.getType( name )
|
||||
peripheral.getMethods( name )
|
||||
peripheral.call( name, methodName, param1, param2, etc )
|
||||
peripheral.wrap( name )
|
||||
peripheral.find( type, [fnFilter] )
|
||||
|
||||
Events fired by the peripheral API:
|
||||
"peripheral" when a new peripheral is attached. Argument is the name.
|
||||
"peripheral_detach" when a peripheral is removed. Argument is the name.
|
||||
Type "help events" to learn about the event system.
|
||||
@@ -0,0 +1,7 @@
|
||||
The "peripherals" program will list all of the peripheral devices accessible from this computer.
|
||||
Peripherals are external devices which CraftOS Computers and Turtles can interact with using the peripheral API.
|
||||
Type "help peripheral" to learn about using the peripheral API.
|
||||
Type "help drives" to learn about using Disk Drives.
|
||||
Type "help modems" to learn about using Modems.
|
||||
Type "help monitors" to learn about using Monitors.
|
||||
Type "help printers" to learn about using Printers.
|
||||
@@ -0,0 +1,6 @@
|
||||
pocket is an API available on pocket computers, which allows modifying its upgrades.
|
||||
Functions in the pocket API:
|
||||
pocket.equipBack()
|
||||
pocket.unequipBack()
|
||||
|
||||
When equipping upgrades, it will search your inventory for a suitable upgrade, starting in the selected slot. If one cannot be found then it will check your offhand.
|
||||
@@ -0,0 +1,12 @@
|
||||
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".
|
||||
|
||||
Methods exposed by the Printer:
|
||||
getInkLevel()
|
||||
getPaperLevel()
|
||||
newPage()
|
||||
setPageTitle( title )
|
||||
getPageSize()
|
||||
setCursorPos( x, y )
|
||||
getCursorPos()
|
||||
write( text )
|
||||
endPage()
|
||||
@@ -0,0 +1,11 @@
|
||||
To learn the lua programming language, visit http://lua-users.org/wiki/TutorialDirectory.
|
||||
|
||||
To experiment with lua in CraftOS, run the "lua" program and start typing code.
|
||||
To 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.
|
||||
|
||||
To terminate a program stuck in a loop, hold Ctrl+T for 1 second.
|
||||
To quickly shutdown a computer, hold Ctrl+S for 1 second.
|
||||
To quickly reboot a computer, hold Ctrl+R for 1 second.
|
||||
|
||||
To learn about the programming APIs availiable, type "apis" or "help apis".
|
||||
If you get stuck, visit the forums at http://www.computercraft.info/ for advice and tutorials.
|
||||
@@ -0,0 +1 @@
|
||||
programs lists all the programs on the rom of the computer.
|
||||
@@ -0,0 +1,2 @@
|
||||
reboot will turn the computer off and on again.
|
||||
You can also hold Ctrl+R at any time to quickly reboot.
|
||||
@@ -0,0 +1,2 @@
|
||||
Redirection ComputerCraft Edition is the CraftOS version of a fun new puzzle game by Dan200, the author of ComputerCraft.
|
||||
Play it on any Advanced Computer, then visit http://www.redirectiongame.com to play the full game!
|
||||
@@ -0,0 +1,18 @@
|
||||
The rednet API provides a simple computer networking model using modems.
|
||||
|
||||
Functions in the rednet API:
|
||||
rednet.open( side )
|
||||
rednet.close( [side] )
|
||||
rednet.isOpen( [side] )
|
||||
rednet.send( receiverID, message, [protocol] ) -- Send to a specific computer
|
||||
rednet.broadcast( message, [protocol] ) -- Send to all computers
|
||||
rednet.receive( [protocol], [timeout] ) -- Returns: senderID, message, protocol
|
||||
rednet.host( protocol, hostname )
|
||||
rednet.unhost( protocol )
|
||||
rednet.lookup( protocol, [hostname] ) -- Returns: ID
|
||||
|
||||
Events fired by the rednet API:
|
||||
"rednet_message" when a message is received. Arguments are senderID, message, protocol
|
||||
Type "help events" to learn about the event system.
|
||||
|
||||
Rednet is not the only way to use modems for networking. Interfacing with the modem directly using the peripheral API and listening for the "modem_message" event allows for lower level control, at the expense of powerful high level networking features.
|
||||
@@ -0,0 +1,9 @@
|
||||
The redstone program can be used to get, set or pulse redstone inputs and outputs from the computer.
|
||||
|
||||
ex:
|
||||
"redstone probe" will list all the redstone inputs to the computer
|
||||
"redstone set left true" turns on the left redstone output.
|
||||
"redstone set right blue false" turns off the blue wire in the bundled cable on the right redstone output.
|
||||
"redstone pulse front 10 1" emits 10 one second redstone pulses on the front redstone output.
|
||||
|
||||
Type "help redstoneapi" or "help rs" for information on the redstone Lua API.
|
||||
@@ -0,0 +1,19 @@
|
||||
Functions in the Redstone API:
|
||||
redstone.getSides( )
|
||||
redstone.getInput( side )
|
||||
redstone.setOutput( side, boolean )
|
||||
redstone.getOutput( side )
|
||||
redstone.getAnalogInput( side )
|
||||
redstone.setAnalogOutput( side, number )
|
||||
redstone.getAnalogOutput( side )
|
||||
|
||||
Functions in the Redstone API for working with bundled cables:
|
||||
redstone.getBundledInput( side )
|
||||
redstone.testBundledInput( side, color )
|
||||
redstone.setBundledOutput( side, colors )
|
||||
redstone.getBundledOutput( side )
|
||||
Type "help bundled" for usage examples.
|
||||
|
||||
Events emitted by the redstone API:
|
||||
"redstone", when the state of any redstone input changes. Use getInput() or getBundledInput() to inspect the changes
|
||||
Type "help events" to learn about the event system.
|
||||
@@ -0,0 +1,6 @@
|
||||
refuel is a program for Turtles. Refuel will consume items from the inventory as fuel for turtle.
|
||||
|
||||
ex:
|
||||
"refuel" will refuel with at most one fuel item
|
||||
"refuel 10" will refuel with at most 10 fuel items
|
||||
"refuel all" will refuel with as many fuel items as possible
|
||||
@@ -0,0 +1,4 @@
|
||||
rename renames a file or directory.
|
||||
|
||||
ex:
|
||||
"rename foo bar" renames the file "foo" to "bar".
|
||||
@@ -0,0 +1 @@
|
||||
repeat is a program for repeating rednet messages across long distances. To use, connect 2 or more modems to a computer and run the "repeat" program; from then on, any rednet message sent from any computer in wireless range or connected by networking cable to either of the modems will be repeated to those on the other side.
|
||||
19
src/main/resources/data/computercraft/lua/rom/help/rs.txt
Normal file
19
src/main/resources/data/computercraft/lua/rom/help/rs.txt
Normal file
@@ -0,0 +1,19 @@
|
||||
Functions in the Redstone API:
|
||||
rs.getSides( )
|
||||
rs.getInput( side )
|
||||
rs.setOutput( side, boolean )
|
||||
rs.getOutput( side )
|
||||
rs.getAnalogInput( side )
|
||||
rs.setAnalogOutput( side, number )
|
||||
rs.getAnalogOutput( side )
|
||||
|
||||
Functions in the Redstone API for working with RedPower bundled cables:
|
||||
rs.getBundledInput( side )
|
||||
rs.testBundledInput( side, color )
|
||||
rs.setBundledOutput( side, colors )
|
||||
rs.getBundledOutput( side )
|
||||
Type "help bundled" for usage examples.
|
||||
|
||||
Events emitted by the redstone API:
|
||||
"redstone", when the state of any redstone input changes. Use getInput() or getBundledInput() to inspect the changes
|
||||
Type "help events" to learn about the event system.
|
||||
@@ -0,0 +1,6 @@
|
||||
The set program can be used to inspect and change system settings.
|
||||
|
||||
Usage:
|
||||
"set" will print all the system settings and their values
|
||||
"set foo" will print the value of the system setting "foo"
|
||||
"set foo bar" will set the value of the system setting "foo" to "bar"
|
||||
@@ -0,0 +1,19 @@
|
||||
Functions in the Settings API:
|
||||
settings.get( name, [default] )
|
||||
settings.set( name, value )
|
||||
settings.unset( name )
|
||||
settings.load( path )
|
||||
settings.save( path )
|
||||
settings.clear()
|
||||
settings.getNames()
|
||||
|
||||
Default Settings:
|
||||
shell.autocomplete - enables auto-completion in the Shell.
|
||||
lua.autocomplete - enables auto-completion in the Lua program.
|
||||
edit.autocomplete - enables auto-completion in the Edit program.
|
||||
edit.default_extension - sets the default file extension for files created with the Edit program
|
||||
paint.default_extension - sets the default file extension for files created with the Paint program
|
||||
bios.use_multishell - enables Multishell on Advanced Computers, Turtles, Pocket Computers and Command Computers.
|
||||
shell.allow_disk_startup - if a Disk Drive with a Disk inside that has a 'startup' script is attached to a computer, this setting allows to automatically run that script when the computer starts.
|
||||
shell.allow_startup - if there is a 'startup' script in a computer's root, this setting allow to automatically run that script when the computer runs.
|
||||
list.show_hidden - determines, whether the List program will list hidden files or not.
|
||||
@@ -0,0 +1,2 @@
|
||||
shell is the toplevel program which interprets commands and runs program.
|
||||
Type "help shellapi" for information about the shell lua api.
|
||||
@@ -0,0 +1,19 @@
|
||||
Functions in the Shell API:
|
||||
shell.exit()
|
||||
shell.dir()
|
||||
shell.setDir( path )
|
||||
shell.path()
|
||||
shell.setPath( path )
|
||||
shell.resolve( localpath )
|
||||
shell.resolveProgram( name )
|
||||
shell.aliases()
|
||||
shell.setAlias( alias, command )
|
||||
shell.clearAlias( alias )
|
||||
shell.programs()
|
||||
shell.run( program, arguments )
|
||||
shell.getRunningProgram()
|
||||
shell.complete( line )
|
||||
shell.completeProgram( program )
|
||||
shell.setCompletionFunction( program, fnComplete )
|
||||
shell.openTab( program, arguments ) (Advanced Computer required)
|
||||
shell.switchTab( n ) (Advanced Computer required)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user