Skip to content
Permalink
Browse files
Updated to ComputerCraft 1.66pr3
  • Loading branch information
Brokolis committed Jan 31, 2015
1 parent c76fb21 commit ed7a593
Show file tree
Hide file tree
Showing 14 changed files with 254 additions and 15 deletions.
@@ -406,16 +406,17 @@ function os.run( _tEnv, _sPath, ... )
return false
end

-- Prevent access to metatables of strings, as these are global between all computers
-- Prevent access to metatables or environments of strings, as these are global between all computers
do
local nativegetfenv = getfenv
local nativegetmetatable = getmetatable
local nativeerror = error
local nativetype = type
local string_metatable = nativegetfenv(("").gsub)
local string_metatable = nativegetmetatable("")
local string_env = nativegetfenv(("").gsub)
function getmetatable( t )
local mt = nativegetmetatable( t )
if mt == string_metatable then
if mt == string_metatable or mt == string_env then
nativeerror( "Attempt to access string metatable", 2 )
else
return mt
@@ -428,7 +429,7 @@ do
env = env + 1
end
local fenv = nativegetfenv(env)
if fenv == string_metatable then
if fenv == string_metatable or fenv == string_env then
--nativeerror( "Attempt to access string metatable", 2 )
return nativegetfenv( 0 )
else
@@ -542,6 +543,7 @@ for n,sFile in ipairs( tApis ) do
end

if turtle then
-- Land turtle APIs
local tApis = fs.list( "rom/apis/turtle" )
for n,sFile in ipairs( tApis ) do
if string.sub( sFile, 1, 1 ) ~= "." then
@@ -554,6 +556,7 @@ if turtle then
end

if pocket and fs.isDir( "rom/apis/pocket" ) then
-- Load pocket APIs
local tApis = fs.list( "rom/apis/pocket" )
for n,sFile in ipairs( tApis ) do
if string.sub( sFile, 1, 1 ) ~= "." then
@@ -565,6 +568,38 @@ if pocket and fs.isDir( "rom/apis/pocket" ) then
end
end

if commands and fs.isDir( "rom/apis/command" ) then
-- Land Command APIs
local tApis = fs.list( "rom/apis/command" )
for n,sFile in ipairs( tApis ) do
if string.sub( sFile, 1, 1 ) ~= "." then
local sPath = fs.combine( "rom/apis/command", sFile )
if not fs.isDir( sPath ) then
os.loadAPI( sPath )
end
end
end

-- Add a special case-insensitive metatable to the commands api
local tCaseInsensitiveIndex = {
__index = function( table, key )
local value = rawget( table, key )
if value ~= nil then
return value
end
if type(key) == "string" then
local value = rawget( table, string.lower(key) )
if value ~= nil then
return value
end
end
return nil
end
}
setmetatable( commands, tCaseInsensitiveIndex )
setmetatable( commands.async, tCaseInsensitiveIndex )
end

-- Run the shell
local ok, err = pcall( function()
parallel.waitForAny(
@@ -0,0 +1,41 @@

if not commands then
error( "Cannot load command API on normal computer", 2 )
end
native = commands.native or commands

local function collapseArgs( errorDepth, arg1, ... )
if arg1 ~= nil then
if type(arg1) == "boolean" or type(arg1) == "number" or type(arg1) == "string" then
return tostring(arg1) .. " " .. collapseArgs( errorDepth + 1, ... )
elseif type(arg1) == "table" then
return textutils.serialiseJSON(arg1) .. " " .. collapseArgs( errorDepth + 1, ... )
else
error( "Expected string, number, boolean or table", errorDepth )
end
end
return ""
end

-- Put native functions into the environment
local env = getfenv()
for k,v in pairs( native ) do
env[k] = v
end

-- Create wrapper functions for all the commands
local tCommands = native.list()
local tAsync = {}
for n,sCommandName in ipairs(tCommands) do
if env[ sCommandName ] == nil then
env[ sCommandName ] = function( ... )
local sCommand = sCommandName .. " " .. collapseArgs( 3, ... )
return native.exec( sCommand )
end
tAsync[ sCommandName ] = function( ... )
local sCommand = sCommandName .. " " .. collapseArgs( 3, ... )
return native.execAsync( sCommand )
end
end
end
env.async = tAsync
@@ -199,6 +199,69 @@ local function serializeImpl( t, tTracking, sIndent )
end
end

EMPTY_ARRAY = {}

local function serializeJSONImpl( t, tTracking )
local sType = type(t)
if t == EMPTY_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 = serializeJSONImpl( k, tTracking ) .. ":" .. serializeJSONImpl( v, tTracking )
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 )
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, "" )
@@ -216,6 +279,11 @@ function unserialize( s )
return nil
end

function serializeJSON( t )
local tTracking = {}
return serializeJSONImpl( t, tTracking )
end

function urlEncode( str )
if str then
str = string.gsub(str, "\n", "\r\n")
@@ -230,3 +298,4 @@ end
-- GB versions
serialise = serialize
unserialise = unserialize
serialiseJSON = serializeJSON
@@ -21,6 +21,20 @@ local vector = {
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,
@@ -55,7 +69,8 @@ local vmetatable = {
__add = vector.add,
__sub = vector.sub,
__mul = vector.mul,
__unm = function( v ) return v:mul(-1) end,
__div = vector.div,
__unm = vector.unm,
__tostring = vector.tostring,
}

@@ -1,3 +1,13 @@
New Features in ComputerCraft 1.66:

* 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 be renamed with Anvils
* Fixed some bugs and crashes

New Features in ComputerCraft 1.65:

* Fixed a multiplayer-only crash with turtle.place()
@@ -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,14 @@
Functions in the commands API:
commands.exec( command )
commands.execAsync( command )
commands.list()
commands.getBlockPosition()
commands.getBlockInfo( x, y, z )

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,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.
@@ -5,4 +5,5 @@ textutils.pagedTabulate( table, table2, ... )
textutils.formatTime( time, bTwentyFourHour )
textutils.serialize( table )
textutils.unserialize( string )
textutils.serializeJSON( table )
textutils.urlEncode( string )
@@ -1,7 +1,11 @@
New Features in ComputerCraft 1.65:
New Features in ComputerCraft 1.66:

* Fixed a multiplayer-only crash with turtle.place()
* Fixed some problems with http.post()
* Fixed fs.getDrive() returning incorrect results on remote peripherals
* 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 be renamed with Anvils
* Fixed some bugs and crashes

Type "help changelog" to see the full version history.
@@ -0,0 +1,9 @@

if not commands then
printError( "Requires a Command Computer." )
return
end

local tCommands = commands.list()
table.sort( tCommands )
textutils.pagedTabulate( tCommands )
@@ -0,0 +1,23 @@

local tArgs = { ... }
if #tArgs == 0 then
printError( "Usage: exec <command>" )
return
end
if not commands then
printError( "Requires a Command Computer." )
return
end

local sCommand = tArgs[1]
local fnCommand = commands[sCommand]
if fnCommand then
local bResult = fnCommand( select( 2, ... ) )
if bResult then
print( "Success" )
else
print( "Failed" )
end
else
printError( "No such command" )
end
@@ -49,6 +49,9 @@ else
end

local sStatus = "Press Ctrl to access menu"
if string.len( sStatus ) > w - 5 then
sStatus = "Press Ctrl for menu"
end

local function load( _sPath )
tLines = {}
@@ -15,6 +15,9 @@ end
if pocket then
sPath = sPath..":/rom/programs/pocket"
end
if commands then
sPath = sPath..":/rom/programs/command"
end
if http then
sPath = sPath..":/rom/programs/http"
end
@@ -51,12 +54,15 @@ end

-- Run the user created startup, either from disk drives or the root
local sUserStartup = shell.resolveProgram( "/startup" )
for n,sName in pairs( peripheral.getNames() ) do
if disk.isPresent( sName ) and disk.hasData( sName ) then
local sDiskStartup = shell.resolveProgram( "/" .. disk.getMountPath( sName ) .. "/startup" )
if sDiskStartup then
sUserStartup = sDiskStartup
break
local bEnableDiskStartup = (commands == nil) and not fs.exists( ".no_disk_startup" )
if bEnableDiskStartup then
for n,sName in pairs( peripheral.getNames() ) do
if disk.isPresent( sName ) and disk.hasData( sName ) then
local sDiskStartup = shell.resolveProgram( "/" .. disk.getMountPath( sName ) .. "/startup" )
if sDiskStartup then
sUserStartup = sDiskStartup
break
end
end
end
end

0 comments on commit ed7a593

Please sign in to comment.