From eab0940bcf7577a9542b474848ee376c581d898c Mon Sep 17 00:00:00 2001 From: whiteshark0 Date: Mon, 20 Apr 2009 12:47:39 +0000 Subject: hookable event nearly finished(unhook function missing) plugin Id now written to the lua states registry Usdx.Version added, Usdx.Hook added git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/branches/experimental@1689 b956fd51-792f-4845-bead-9b4dfca2ff2c --- Lua/src/base/UMain.pas | 4 +- Lua/src/lua/UHookableEvent.pas | 86 +++++++++++++++++++++++++++--------------- Lua/src/lua/ULuaCore.pas | 7 +++- Lua/src/lua/ULuaUsdx.pas | 65 ++++++++++++++++++++++++++++--- 4 files changed, 122 insertions(+), 40 deletions(-) (limited to 'Lua/src') diff --git a/Lua/src/base/UMain.pas b/Lua/src/base/UMain.pas index e1226c4d..b37d698b 100644 --- a/Lua/src/base/UMain.pas +++ b/Lua/src/base/UMain.pas @@ -423,10 +423,8 @@ begin LuaCore.RegisterModule('Log', ULuaLog_Lib_f); - LuaCore.BrowseDir(PluginPath); - LuaCore.DumpPlugins; - + LuaCore.DumpPlugins; //------------------------------ diff --git a/Lua/src/lua/UHookableEvent.pas b/Lua/src/lua/UHookableEvent.pas index cc7cc443..d6ec2807 100644 --- a/Lua/src/lua/UHookableEvent.pas +++ b/Lua/src/lua/UHookableEvent.pas @@ -42,12 +42,14 @@ type Handle: Integer; //< Handle to identify the hook, e.g. for unhooking by plugin Parent: Integer; //< Lua Core Handle this hook belongs to + Func: String; //< Name of the global that holds the function + Next: PHook; //< Next Hook in list (nil for the first) end; { procedure is called before each call to the hooking lua functions, to push values on stack returns the number of pushed arguments} - PrepareStackProc = Function: Integer; + PrepareStackProc = Function(L: PLua_State): Integer; { class representing a hookable event } THookableEvent = class @@ -65,7 +67,7 @@ type property Name: String read sName; //< returns the events name property Handle: Integer read iHandle; //< returns the events name - procedure Hook(L: Plua_State; Parent: Integer; Proc: String); //< pushes hook object/table to the lua stack + procedure Hook(L: Plua_State; Parent: Integer; Func: String); //< pushes hook object/table to the lua stack procedure UnHook(L: Plua_State; hHook: Integer); //< unhook by plugin. push true or error string to lua stack procedure UnHookByParent(Parent: Integer); //< deletes all hooks by a specified parent (unhook by core) @@ -76,7 +78,7 @@ type end; { the default function for THookableEvent.PrepareStack it don't pass any arguments } -function PrepareStack_Dummy: Integer; +function PrepareStack_Dummy(L: PLua_State): Integer; { function in resulting hook table. it calls the unhook command of the event on plugins demand } function LuaHook_UnHook(L: Plua_State): Integer; cdecl; @@ -124,44 +126,50 @@ begin end; { adds hook to events list and pushes hook object/table to the lua stack } -procedure THookableEvent.Hook(L: Plua_State; Parent: Integer; Proc: String); +procedure THookableEvent.Hook(L: PLua_State; Parent: Integer; Func: String); var Item: PHook; + P: TLuaPlugin; begin - // get mem and fill it w/ data - New(Item); - Item.Handle := NextHookHandle; - Inc(NextHookHandle); + P := LuaCore.GetPluginById(Parent); + if (P <> nil) then + begin + // get mem and fill it w/ data + New(Item); + Item.Handle := NextHookHandle; + Inc(NextHookHandle); - Item.Parent := Parent; + Item.Parent := Parent; + Item.Func := Func; - // add at front of the hook chain - Item.Next := LastHook; - LastHook := Item; + // add at front of the hook chain + Item.Next := LastHook; + LastHook := Item; - //we need 2 free stack slots - lua_checkstack(L, 2); + //we need 2 free stack slots + lua_checkstack(L, 2); - //create the hook table, we need 2 elements (event name and unhook function) - lua_createtable(L, 0, 2); + //create the hook table, we need 2 elements (event name and unhook function) + lua_createtable(L, 0, 2); - //push events name - lua_pushstring(L, PAnsiChar(Name)); + //push events name + lua_pushstring(L, PAnsiChar(Name)); - //add the name to the table - lua_setfield(L, -2, 'Event'); + //add the name to the table + lua_setfield(L, -2, 'Event'); - //push hook id to the stack - lua_pushinteger(L, Item.Handle); + //push hook id to the stack + lua_pushinteger(L, Item.Handle); - //create a c closure, append one value from stack(the id) - //this will pop both, the function and the id - lua_pushcclosure(L, LuaHook_UnHook, 1); + //create a c closure, append one value from stack(the id) + //this will pop both, the function and the id + lua_pushcclosure(L, LuaHook_UnHook, 1); - //add the function to our table - lua_setfield(L, -2, 'Unhook'); + //add the function to our table + lua_setfield(L, -2, 'Unhook'); - //the table is left on the stack, it is our result + //the table is left on the stack, it is our result + end; end; { unhook by plugin. push true or error string to lua stack } @@ -231,19 +239,37 @@ begin end; { calls the events hookchain. if breakable, plugin can breake the chain - by returning a value other than 0 or false or nil + by returning a value breakable is pushed as the first parameter to the hooking functions if chain is broken the LuaStack is returned, with all results left you may call lua_clearstack } function THookableEvent.CallHookChain(Breakable: Boolean): Plua_State; var Cur: PHook; + P: TLuaPlugin; begin + Result := nil; + + Cur := LastHook; + While (Cur <> nil) do + begin + P := LuaCore.GetPluginById(Cur.Parent); + lua_pushboolean(P.LuaState, Breakable); + + if (P.CallFunctionByName(Cur.Func, 1 + PrepareStack(P.LuaState), LUA_MULTRET)) + and Breakable + and (lua_gettop(P.LuaState) > 0) then + begin //Chain Broken + Result := P.LuaState; + Break; + end; + Cur := Cur.Next; + end; end; { the default function for THookableEvent.PrepareStack it don't pass any arguments } -function PrepareStack_Dummy: Integer; +function PrepareStack_Dummy(L: PLua_State): Integer; begin Result := 0; end; diff --git a/Lua/src/lua/ULuaCore.pas b/Lua/src/lua/ULuaCore.pas index 9f965567..403709dd 100644 --- a/Lua/src/lua/ULuaCore.pas +++ b/Lua/src/lua/ULuaCore.pas @@ -655,7 +655,12 @@ begin lua_checkstack(State, 2); lua_pushinteger(State, Id); lua_pushcclosure(State, TLuaPlugin_Register, 1); - lua_setglobal(State, PChar('register')); + lua_setglobal(State, PChar('register')); + + // write plugin id to registry + lua_pushinteger(State, iId); + lua_setfield (State, LUA_REGISTRYINDEX, '_USDX_STATE_ID'); + lua_pop(State, Lua_GetTop(State)); // now run the plugin_init function // plugin_init() if false or nothing is returned plugin init is aborted diff --git a/Lua/src/lua/ULuaUsdx.pas b/Lua/src/lua/ULuaUsdx.pas index 558a47cd..4bbb64ea 100644 --- a/Lua/src/lua/ULuaUsdx.pas +++ b/Lua/src/lua/ULuaUsdx.pas @@ -37,19 +37,28 @@ uses ULua; { some basic lua c functions from usdx table } -{ usdx.time - returns sdl_time to have time numbers comparable with - ultrastar delux ones. No Arguments } +{ Usdx.Time - returns sdl_time to have time numbers comparable with + ultrastar delux ones. no arguments } function ULuaUsdx_Time(L: Plua_State): Integer; cdecl; -function ULuaUsdx_(L: Plua_State): Integer; cdecl; + +{ Usdx.Version - returns Usdx version string (the same that US_Version + language-constant does). no arguments } +function ULuaUsdx_Version(L: Plua_State): Integer; cdecl; + +{ Usdx.Hook - returns an hook table with name and Unhook function + arguments: event_name: string } +function ULuaUsdx_Hook(L: Plua_State): Integer; cdecl; const - ULuaUsdx_Lib_f: array [0..1] of lual_reg = ( + ULuaUsdx_Lib_f: array [0..3] of lual_reg = ( + (name:'Version'; func:ULuaUsdx_Version), (name:'Time'; func:ULuaUsdx_Time), + (name:'Hook'; func:ULuaUsdx_Hook), (name:nil; func:nil) ); implementation -uses SDL; +uses SDL, ULuaCore, UHookableEvent, UConfig; function ULuaUsdx_Time(L: Plua_State): Integer; cdecl; var top: Integer; @@ -65,9 +74,53 @@ begin Result := 1; //one result end; -function ULuaUsdx_(L: Plua_State): Integer; cdecl; +{ Usdx.Version - returns Usdx version string (the same that US_Version + language-constant does). no arguments } +function ULuaUsdx_Version(L: Plua_State): Integer; cdecl; + var top: Integer; begin + //remove arguments (if any) + top := lua_gettop(L); + + If (top > 0) then + lua_pop(L, top); + + //push result + lua_pushstring(L, PChar(USDXVersionStr())); + Result := 1; //one result +end; + +{ Usdx.Hook - returns an hook table with name and Unhook function + arguments: event_name: string; function_name: string } +function ULuaUsdx_Hook(L: Plua_State): Integer; cdecl; +var + EventName: String; + FunctionName: String; + ParentId: Integer; + Event: THookableEvent; +begin + EventName := luaL_checkstring(L, 1); + FunctionName := luaL_checkstring(L, 2); + + lua_checkstack(L, 1); + + lua_getfield (L, LUA_REGISTRYINDEX, '_USDX_STATE_ID'); + if (not lua_isNumber(L, -1)) then + luaL_error(L, 'unable to get _USDX_STATE_ID in ULuaUsdx_Hook'); + + ParentId := lua_toInteger(L, -1); + + lua_pop(L, lua_gettop(L)); //clear stack + + Result := 1; + Event := LuaCore.GetEventByName(EventName); + if (Event <> nil) then + begin + Event.Hook(L, ParentId, FunctionName); + end + else + luaL_error(L, PChar('event does not exist: ' + EventName)); end; end. \ No newline at end of file -- cgit v1.2.3