예제 #1
0
        public override void Init(LuaMachine machine)
        {
            base.Init(machine);
            machine.DoString(@"
                -- Locals
                local type = type
                local error = error
                local function expect( value, sExpectedType, index )
                    local sFoundType = type( value )
                    if sExpectedType and sFoundType ~= sExpectedType then
                        error( ""Expected "" .. sExpectedType .. "" at argument #"" .. index .. "", got "" .. sFoundType, 3 )
                    end
                    return value
                end

				-- System API methods
				local coroutine_yield = coroutine.yield
                local table_unpack = table.unpack

                function system.pullEvent( a, ... )
                    local tEvent
                    if a ~= nil then
                        tEvent = { coroutine_yield( ""terminate"", a, ... ) }
                    else
                        tEvent = { coroutine_yield() }
                    end
                    local sEvent = tEvent[1]
                    if sEvent == ""terminate"" then
                        error( ""Terminated"", 0 )
                    else
                        return table_unpack( tEvent )
                    end
                end

                function system.pullEventRaw( ... )
                    return coroutine_yield( ... )
                end

				local system_getDevice = system.getDevice
                local system_pullEvent = system.pullEvent
                function system.sleep( nSeconds )
                    expect( nSeconds, ""number"", 1 )
                    local clock = system_getDevice( ""clock"" )
                    if not clock then
                        error( ""Error sleeping: No clock detected"", 2 )
                    end
                    local nTimer = clock.startTimer( nSeconds )
                    while true do
                        local sEvent, p1 = system_pullEvent( ""timer"" )
                        if p1 == nTimer then
                            break
                        end
                    end
                end",
                             "=SystemAPI.Init"
                             );
        }
예제 #2
0
 public LuaCPUDevice(string description)
 {
     m_description   = description;
     m_computer      = null;
     m_isMainCPU     = false;
     m_machine       = null;
     m_mainRoutine   = null;
     m_fileSystem    = new FileSystem();
     m_eventFilter   = new HashSet <string>();
     m_nextBootMount = new LuaObjectRef <LuaMount>();
 }
예제 #3
0
 public static void UnloadAll()
 {
     if (s_animMachine != null)
     {
         s_loadedAnims.Clear();
         s_animMachine.Dispose();
         s_animMachine       = null;
         s_install_animation = null;
         s_call_animation    = null;
     }
 }
예제 #4
0
        private void Halt()
        {
            if (m_machine == null)
            {
                throw new InvalidOperationException();
            }

            // Shutdown lua machine
            m_machine.Dispose();
            m_machine     = null;
            m_mainRoutine = null;
            m_eventFilter.Clear();

            // Shutdown file system
            m_fileSystem.UnmountAll();
        }
예제 #5
0
 internal LuaCoroutine(LuaMachine machine, int id)
 {
     Machine = machine;
     ID      = id;
 }
예제 #6
0
        public override void Init(LuaMachine machine)
        {
            base.Init(machine);
            machine.DoString(@"
				-- Locals
				local type = type
				local error = error
				local function expect( value, sExpectedType, index )
				    local sFoundType = type( value )
				    if sExpectedType and sFoundType ~= sExpectedType then
			            error( ""Expected "" .. sExpectedType .. "" at argument #"" .. index .. "", got "" .. sFoundType, 3 )
				    end
				    return value
				end

				-- IO API
				local io_open = io.open
				local io_input = io.input
				local io_output = io.output
				local tostring = tostring
				local load = load

				function loadfile( sPath, sMode, _env )
					if sPath ~= nil then
						expect( sPath, ""string"", 1 )
					end
					local file, sChunkName
					if sPath then
						file = io_open( sPath )
						sChunkName = ""@"" .. sPath
					else
						file = io_input()
						sChunkName = ""=stdin""
					end
					if file then
						local sFile = file:read( ""a"" )
						file:close()
				        if _env ~= nil then
				            return load( sFile, sChunkName, sMode, _env )
				        else
				            return load( sFile, sChunkName, sMode )
				        end
					end
					return nil, ""File not found: "" .. sPath
				end

				local loadfile = loadfile
				function dofile( sPath )
					if sPath ~= nil then
						expect( sPath, ""string"", 1 )
					end
					local fnFile, sError = loadfile( sPath )
					if fnFile then
						return fnFile()
					else
						error( sError, 2 )
					end
				end

				local select = select
				function print( ... )
					local nArgs = select( ""#"", ... )
					local output = io_output()
					for n=1,nArgs do
						local arg = select( n, ... )
						output:write( tostring(arg) )
						if n<nArgs then
							output:write( ""\t"" )
						end
					end
					output:write( ""\n"" )
				end"                ,
                             "=IOAPI.Init"
                             );
        }
예제 #7
0
        private CPUUpdateResult ReallyBoot(LuaMount bootMount)
        {
            if (m_machine != null)
            {
                throw new InvalidOperationException();
            }

            // Check if the system has any RAM
            if (m_computer.Memory.TotalMemory == 0)
            {
                m_computer.ErrorOutput.WriteLine("Error starting CPU: No RAM");
                return(m_isMainCPU ? CPUUpdateResult.Shutdown : CPUUpdateResult.Continue);
            }

            // Mount the ROM
            m_fileSystem.Mount(bootMount, FilePath.Empty, FilePath.Empty, true);

            // Check if the boot path exists
            var bootPath = new FilePath("boot.lua");

            if (!m_fileSystem.Exists(bootPath) || m_fileSystem.IsDir(bootPath))
            {
                m_computer.ErrorOutput.WriteLine("Error starting CPU: ROM does not countain {0}", bootPath);
                m_fileSystem.UnmountAll();
                return(m_isMainCPU ? CPUUpdateResult.Shutdown : CPUUpdateResult.Continue);
            }

            // Init lua machine
            m_machine = new LuaMachine(m_computer.Memory);
            m_machine.AllowByteCodeLoading = false;
            m_machine.EnforceTimeLimits    = true;
            try
            {
                // Remove default APIs we don't want
                m_machine.RemoveUnsafeGlobals();

                // Install basic APIs
                if (m_computer.Host != null)
                {
                    m_machine.SetGlobal("_HOST", m_computer.Host);
                }
                InstallAPI(new IOAPI(m_computer, m_fileSystem));
                InstallAPI(new OSAPI(m_computer, this, m_fileSystem));
                InstallAPI(new PackageAPI(m_computer, m_fileSystem));

                // Install custom APIs
                PreloadAPI(new SystemAPI(m_computer, this));
                PreloadAPI(new FSAPI(m_computer, m_fileSystem));
            }
            catch (LuaError e)
            {
                m_computer.ErrorOutput.WriteLine("Error starting CPU: {0}", e.Message);
                Halt();
                return(m_isMainCPU ? CPUUpdateResult.Shutdown : CPUUpdateResult.Continue);
            }

            // Load the boot script
            try
            {
                string bootScript;
                using (var reader = m_fileSystem.OpenForRead(bootPath))
                {
                    bootScript = reader.ReadToEnd();
                }
                var bootFunction = m_machine.LoadString(bootScript, "@" + bootPath);
                m_mainRoutine = m_machine.CreateCoroutine(bootFunction);
                m_eventFilter.Clear();
            }
            catch (IOException e)
            {
                m_computer.ErrorOutput.WriteLine("Error loading {0}: {1}", bootPath, e.Message);
                Halt();
                return(m_isMainCPU ? CPUUpdateResult.Shutdown : CPUUpdateResult.Continue);
            }
            catch (LuaError e)
            {
                m_computer.ErrorOutput.WriteLine("Error parsing {0}: {1}", bootPath, e.Message);
                Halt();
                return(m_isMainCPU ? CPUUpdateResult.Shutdown : CPUUpdateResult.Continue);
            }

            // Start the boot script
            m_eventFilter.Clear();
            return(Resume(LuaArgs.Empty));
        }
예제 #8
0
        public override void Init(LuaMachine machine)
        {
            base.Init(machine);
            machine.DoString(@"
				-- Locals
				local type = type
				local error = error
				local function expect( value, sExpectedType, index )
				    local sFoundType = type( value )
				    if sExpectedType and sFoundType ~= sExpectedType then
			            error( ""Expected "" .. sExpectedType .. "" at argument #"" .. index .. "", got "" .. sFoundType, 3 )
				    end
				    return value
				end

				-- Package API 
				local package_preload = package.preload
				local package_searchpath = package.searchpath
				local package_loaded = package.loaded
				local package_searchers = package.searchers
				local pcall = pcall
				local loadfile = loadfile

				table.insert(
					package.searchers,
					function( sName )
						-- Load from preload
						expect( sName, ""string"", 1 )
						if package_preload[ sName ] ~= nil then
							return package_preload[ sName ]
						else
							return ""no field package.preload['"" .. sName .. ""']""
						end
					end
				)

				table.insert(
					package.searchers,
					function( sName )
						-- Load from path
						expect( sName, ""string"", 1 )
						if type( package.path ) ~= ""string"" then
							error( ""package.path must be a string"", 0 )
						end
						local sPath, sError = package_searchpath( sName, package.path )
						if sPath ~= nil then
							local fnFile, sError = loadfile( sPath )
							if fnFile then
								return fnFile, sPath
							else
								return sError
							end
						else
							return sError
						end
					end
				)
				
				local require_in_progress = {}
				function require( sName )
					expect( sName, ""string"", 1 )
					if package_loaded[ sName ] ~= nil then
						return package_loaded[ sName ]
					end
					if require_in_progress[ sName ] then
						error( ""loop detected requiring '"" .. sName .. ""'"", 2 )
					end
					require_in_progress[ sName ] = true
					local ok, result = pcall( function() 
						local sFullError = ""module '"" .. sName .. ""' not found:""
						for n=1,#package_searchers do
							local fnSearcher = package_searchers[n]
							local fnLoader, sExtra = fnSearcher( sName )
							if type(fnLoader) == ""function"" then
								local result = fnLoader( sName, sExtra )
								if result ~= nil then
									package_loaded[ sName ] = result
									return result
								else
									package_loaded[ sName ] = true
									return true
								end
							elseif type(fnLoader) == ""string"" then
								sFullError = sFullError .. ""\n"" .. fnLoader
							end
						end
						error( sFullError, 0 )
					end )
					require_in_progress[ sName ] = false
					if ok then
						return result
					else
						error( result, 0 )
					end
				end"                ,
                             "=PackageAPI.Init"
                             );
        }
예제 #9
0
        public ScriptController(LevelState state)
        {
            m_state   = state;
            m_machine = new LuaMachine();
            m_machine.AllowByteCodeLoading = false;
            m_machine.EnforceTimeLimits    = true;
            m_machine.RemoveUnsafeGlobals();

            m_activeCoroutines = new List <LuaCoroutine>();

            // Install APIs and Globals
            m_machine.SetGlobal("io", new IOAPI(m_state).ToTable());
            m_machine.SetGlobal("level", new LevelAPI(m_state).ToTable());
            if (m_state is InGameState)
            {
                m_machine.SetGlobal("game", new GameAPI((InGameState)m_state).ToTable());
                m_machine.SetGlobal("campaign", new CampaignAPI(m_state).ToTable());

                m_machine.DoString(@"do
                    local game_showDialogue = game.showDialogue
                    function game.showDialogue( character, text, modal, returnImmediately )
                        -- Create dialog
                        game_showDialogue( character, text, modal )
                        if modal ~= false and returnImmediately ~= true then
                            while not game.isDialogueReadyToContinue() do
                                yield()
                            end
                        end
                    end

                    local game_hideDialogue = game.hideDialogue
                    function game.hideDialogue()
                        -- Create dialog
                        game_hideDialogue()
                        while game.isDialogueVisible() do
                            yield()
                        end
                    end
                end", "=ScriptController.ctor");
            }
            else if (m_state is CutsceneState)
            {
                m_machine.SetGlobal("cutscene", new CutsceneAPI((CutsceneState)m_state).ToTable());
                m_machine.SetGlobal("campaign", new CampaignAPI(m_state).ToTable());
            }

            m_machine.SetGlobal("dofile", (LuaCFunction)DoFile);
            m_machine.DoString(@"do
                function expect( value, sExpectedType, nArg )
                    local sFoundType = type( value )
                    if sFoundType ~= sExpectedType then
                        error( ""Expected "" .. sExpectedType .. "" at argument "" .. nArg .. "", got "" .. sFoundType, 3 )
                    end
                end

                local tResults = {}
                function require( s )
                    expect( s, ""string"", 1 )
                    if tResults[s] == nil then
                        local ok, result = pcall( dofile, ""scripts/"" .. s .. "".lua"" )
                        if not ok then
                            error( result, 0 )
                        elseif result == nil then
                            tResults[s] = true
                        else
                            tResults[s] = result
                        end
                    end
                    return tResults[s]
                end

				print = io.print
				yield = coroutine.yield

				function sleep( t )
	                expect( t, ""number"", 1 )
	                local l = io.getTime() + t
	                repeat
	                    yield()
	                until io.getTime() >= l
	            end				
            end", "=ScriptController.ctor");

            // Start the main script
            m_scriptPath = m_state.Level.Info.ScriptPath;
            if (m_scriptPath != null)
            {
                if (Assets.Exists <LuaScript>(m_scriptPath))
                {
                    try
                    {
                        var script = LuaScript.Get(m_scriptPath);
                        m_machine.DoString(script.Code, "@" + AssetPath.GetFileName(m_scriptPath));
                    }
                    catch (LuaError e)
                    {
                        App.Log("Lua Error: {0}", e.Message);
                    }
                }
                else
                {
                    App.Log("Error: Script {0} not found", m_scriptPath);
                }
            }
        }
예제 #10
0
 public void Dispose()
 {
     m_machine.Dispose();
     m_machine = null;
 }
예제 #11
0
        private static void Init()
        {
            if (s_animMachine == null)
            {
                s_animMachine = new LuaMachine();
                s_animMachine.AllowByteCodeLoading = false;
                s_animMachine.EnforceTimeLimits    = true;
                s_animMachine.RemoveUnsafeGlobals();

                s_animMachine.SetGlobal("print", (LuaCFunction) delegate(LuaArgs args)
                {
                    var output = new StringBuilder();
                    for (int i = 0; i < args.Length; ++i)
                    {
                        output.Append(args.ToString(i));
                        if (i < args.Length - 1)
                        {
                            output.Append(", ");
                        }
                    }
                    App.UserLog(output.ToString());
                    return(LuaArgs.Empty);
                });

                s_animMachine.SetGlobal("dofile", (LuaCFunction) delegate(LuaArgs args)
                {
                    var path = args.GetString(0);
                    if (Assets.Assets.Exists <LuaScript>(path))
                    {
                        var script = LuaScript.Get(path);
                        return(s_animMachine.DoString(script.Code, "@" + AssetPath.GetFileName(path)));
                    }
                    throw new LuaError("Script not found: " + path);
                });
                s_animMachine.DoString(
                    @"do
                        function expect( value, sExpectedType, nArg )
                            local sFoundType = type( value )
                            if sFoundType ~= sExpectedType then
                                error( ""Expected "" .. sExpectedType .. "" at argument "" .. nArg .. "", got "" .. sFoundType, 3 )
                            end
                        end

                        local tResults = {}
                        function require( s )
                            expect( s, ""string"", 1 )
                            if tResults[s] == nil then
                                local ok, result = pcall( dofile, ""scripts/"" .. s .. "".lua"" )
                                if not ok then
                                    error( result, 0 )
                                elseif result == nil then
                                    tResults[s] = true
                                else
                                    tResults[s] = result
                                end
                            end
                            return tResults[s]
                        end

                        abs = math.abs
                        floor = math.floor
                        ceil = math.ceil
                        min = math.min
                        max = math.max
                        pow = math.pow
                        sqrt = math.sqrt
                        pi = math.pi

                        function clamp( x, low, hi )
                            expect( x, ""number"", 1 )
                            expect( low, ""number"", 2 )
                            expect( hi, ""number"", 3 )
                            if x < low then
                                return low
                            elseif x > hi then
                                return hi
                            else
                                return x
                            end
                        end
                        
                        local math_rad, math_deg = math.rad, math.deg
                        local math_sin, math_cos, math_tan = math.sin, math.cos, math.tan
                        local math_asin, math_acos, math_atan = math.asin, math.acos, math.atan

                        function sin( x )
                            expect( x, ""number"", 1 )
                            return math_sin( math_rad( x ) )
                        end

                        function cos( x )
                            expect( x, ""number"", 1 )
                            return math_cos( math_rad( x ) )
                        end

                        function tan( x )
                            expect( x, ""number"", 1 )
                            return math_tan( math_rad( x ) )
                        end

                        function asin( x )
                            expect( x, ""number"", 1 )
                            return math_deg( math_asin( x ) )
                        end

                        function acos( x )
                            expect( x, ""number"", 1 )
                            return math_deg( math_acos( x ) )
                        end

                        function atan( x )
                            expect( x, ""number"", 1 )
                            return math_deg( math_atan( x ) )
                        end

                        function atan2( y, x )
                            expect( y, ""number"", 1 )
                            expect( x, ""number"", 2 )
                            return math_deg( math_atan( y, x ) )
                        end

                        function ease( f )
                            expect( f, ""number"", 1 )
                            f = clamp( f, 0.0, 1.0 )
                            return (3 - 2*f) * f * f
                        end

                        function lerp( a, b, f )
                            expect( a, ""number"", 1 )
                            expect( b, ""number"", 2 )
                            expect( f, ""number"", 3 )
                            return a + (b-a) * f
                        end

                        function lerp3( x0, y0, z0, x1, y1, z1, f )
                            expect( x0, ""number"", 1 )
                            expect( y0, ""number"", 2 )
                            expect( z0, ""number"", 3 )
                            expect( x1, ""number"", 4 )
                            expect( y1, ""number"", 5 )
                            expect( z1, ""number"", 6 )
                            expect( f, ""number"", 7 )
	                        return lerp(x0, x1, f), lerp(y0, y1, f), lerp(z0, z1, f)
                        end

                        function step( a, x )
                            expect( a, ""number"", 1 )
                            expect( x, ""number"", 2 )
                            return (x >= a) and 1 or 0
                        end

                        function smoothstep( a, b, x )
                            expect( a, ""number"", 1 )
                            expect( b, ""number"", 2 )
                            expect( x, ""number"", 3 )
                            local f = clamp( (x - a) / (b - a), 0, 1 )
                            return ease(f)
                        end

                        function rot2D( x, y, a, xo, yo )
                            expect( x, ""number"", 1 )
                            expect( y, ""number"", 2 )
                            expect( a, ""number"", 3 )
                            if xo then
                                expect( xo, ""number"", 4 )
                            end
                            if yo then
                                expect( yo, ""number"", 5 )
                            end
                            xo = xo or 0
                            yo = yo or 0
                            local ar = -math_rad(a)
                            local ca, sa = math_cos(ar), math_sin(ar)
                            return
                                xo + (x - xo) * ca - (y - yo) * sa,
                                yo + (x - xo) * sa + (y - yo) * ca
                        end

                        function setpos( part, x, y, z )
                            expect( part, ""table"", 1 )
                            expect( x, ""number"", 2 )
                            expect( y, ""number"", 3 )
                            expect( z, ""number"", 4 )
                            part.x = x
                            part.y = y
                            part.z = z
                        end

                        function lookat( part, x, y, z )
                            expect( part, ""table"", 1 )
                            expect( x, ""number"", 2 )
                            expect( y, ""number"", 3 )
                            expect( z, ""number"", 4 )
	                        local dx = x - part.x
	                        local dy = y - part.y
	                        local dz = z - part.z
	                        local dxz = sqrt( dx*dx + dz*dz )
	                        part.ry = -atan2( dx, -dz )
	                        part.rx = atan2( dy, dxz )
	                        part.rz = 0
                        end

                        local tAnimations = {}
                        function install_animation( sAnimName, sAnimCode, sChunkName )
                            local tAnimEnv = {}
                            setmetatable( tAnimEnv, { __index = _ENV } )

                            local fnAnim, sError = load( sAnimCode, sChunkName, ""t"", tAnimEnv )
                            if fnAnim then
                                local ok, sError = pcall( fnAnim )
                                if ok then
                                    tAnimations[ sAnimName ] = tAnimEnv.animate
                                else
                                    tAnimations[ sAnimName ] = nil
                                    error( sError, 0 )
                                end
                            else
                                tAnimations[ sAnimName ] = nil
                                error( sError, 0 )
                            end
                        end

                        local tPart = {}
                        function call_animation( sAnimName, sPartName, nTime )
                            tPart.name = sPartName
                            tPart.hide = false
                            tPart.x, tPart.y, tPart.z = 0,0,0
                            tPart.rx, tPart.ry, tPart.rz = 0,0,0
                            tPart.sx, tPart.sy, tPart.sz = 1,1,1
                            tPart.u, tPart.v = 0,0
                            tPart.su, tPart.sv = 1,1
                            tPart.r, tPart.g, tPart.b, tPart.a = 1,1,1,1
                            tPart.fov = nil
                            local fnAnimate = tAnimations[sAnimName]
                            if fnAnimate then
                                fnAnimate( tPart, nTime )
                            end
                            return
                                tPart.hide,
                                tPart.x, tPart.y, tPart.z,
                                tPart.rx, tPart.ry, tPart.rz,
                                tPart.sx, tPart.sy, tPart.sz,
                                tPart.u, tPart.v,
                                tPart.su, tPart.sv,
                                tPart.r, tPart.g, tPart.b, tPart.a,
                                tPart.fov
                        end
                    end",
                    "=LuaAnimation.Init"
                    );

                s_install_animation = s_animMachine.GetGlobal("install_animation").GetFunction();
                s_call_animation    = s_animMachine.GetGlobal("call_animation").GetFunction();
            }
        }
예제 #12
0
 public virtual void Init(LuaMachine machine)
 {
     machine.SetGlobal(Name, GetMethodTable());
 }
예제 #13
0
 internal LuaFunction(LuaMachine machine, int id)
 {
     Machine = machine;
     ID      = id;
 }