diff options
author | whiteshark0 <whiteshark0@b956fd51-792f-4845-bead-9b4dfca2ff2c> | 2009-05-16 13:06:57 +0000 |
---|---|---|
committer | whiteshark0 <whiteshark0@b956fd51-792f-4845-bead-9b4dfca2ff2c> | 2009-05-16 13:06:57 +0000 |
commit | 1b2346740c8b23f56a29bcbb646266667a911f6b (patch) | |
tree | a79112a4ff1c0ec22fca5b7d5234693cc640504a | |
parent | 0612fdf8fd4badc25e4f1faab24f73c93b690389 (diff) | |
download | usdx-1b2346740c8b23f56a29bcbb646266667a911f6b.tar.gz usdx-1b2346740c8b23f56a29bcbb646266667a911f6b.tar.xz usdx-1b2346740c8b23f56a29bcbb646266667a911f6b.zip |
add Lua_GetOwner to ULuaUtils (function returns plugin by lua state)
use new function in ULuaParty and ULuaUsdx
new lua function: Usdx.ShutMeDown to give plugins the ability to unload
git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/branches/experimental@1732 b956fd51-792f-4845-bead-9b4dfca2ff2c
-rw-r--r-- | Lua/src/lua/ULuaCore.pas | 90 | ||||
-rw-r--r-- | Lua/src/lua/ULuaParty.pas | 8 | ||||
-rw-r--r-- | Lua/src/lua/ULuaUsdx.pas | 42 | ||||
-rw-r--r-- | Lua/src/lua/ULuaUtils.pas | 35 |
4 files changed, 121 insertions, 54 deletions
diff --git a/Lua/src/lua/ULuaCore.pas b/Lua/src/lua/ULuaCore.pas index cdb41f22..986974bb 100644 --- a/Lua/src/lua/ULuaCore.pas +++ b/Lua/src/lua/ULuaCore.pas @@ -63,6 +63,7 @@ type State: Plua_State; //< all functions of this plugin are called with this Lua state
bPaused: Boolean; //< If true no lua functions from this state are called
ErrorCount: Integer; //< counts the errors that occured during function calls of this plugin
+ ShutDown: Boolean; //< for self shutdown by plugin. true if plugin wants to be unloaded after execution of current function
sName: String;
sVersion: String;
@@ -92,6 +93,8 @@ type procedure PausePlugin(doPause: Boolean);
property Paused: boolean read bPaused write PausePlugin;
+ procedure ShutMeDown;
+
{ calls the lua function in the global w/ the given name.
the arguments to the function have to be pushed to the stack
before calling this function.
@@ -183,7 +186,7 @@ var LuaCore: TLuaCore;
implementation
-uses ULog, UPlatform, ULuaUsdx, UMain;
+uses ULog, UPlatform, ULuaUsdx, UMain, StrUtils;
constructor TLuaCore.Create;
begin
@@ -664,6 +667,7 @@ begin Self.ErrorCount := 0;
Self.sName := 'not registred';
Self.sStatus := psNone;
+ Self.ShutDown := False;
State := nil; //< to prevent calls to unopened state
end;
@@ -714,7 +718,7 @@ begin // plugin_init() if false or nothing is returned plugin init is aborted
if (CallFunctionByName('plugin_init', 0, 1)) then
begin
- If (HasRegistred) AND (lua_toBoolean(State, 1)) then
+ If (HasRegistred) AND (sStatus = psNone) AND (lua_toBoolean(State, 1)) then
begin
sStatus := psRunning;
ClearStack;
@@ -764,6 +768,12 @@ begin bPaused := doPause;
end;
+{ unload plugin after execution of the current function }
+procedure TLuaPlugin.ShutMeDown;
+begin
+ ShutDown := True;
+end;
+
{ calls the lua function in the global w/ the given name.
the arguments to the function have to be pushed to the stack
before calling this function.
@@ -775,59 +785,73 @@ end; function TLuaPlugin.CallFunctionByName(Name: String; const nArgs: Integer; const nResults: Integer; const ReportErrors: Boolean): Boolean;
begin
Result := false;
- if (not bPaused) and (State <> nil) then
+ if (State <> nil) then
begin
- // we need at least one stack slot free
- lua_checkstack(State, 1);
-
- // lua_getglobal(State, PChar(Name)); //this is just a macro:
- lua_getfield(State, LUA_GLOBALSINDEX, PChar(Name));
-
- If (lua_isfunction(State, -1)) then
- begin //we got a function
- // move function in front of the arguments (if any)
- if (nArgs > 0) then
- lua_insert(State, -(nArgs + 1));
-
- // call it!
- if (lua_pcall(State, nArgs, nResults, 0) = 0) then
- Result := true //called w/o errors
- else //increase error counter
- Inc (ErrorCount);
+ if (not bPaused) then
+ begin
+ // we need at least one stack slot free
+ lua_checkstack(State, 1);
+
+ // lua_getglobal(State, PChar(Name)); //this is just a macro:
+ lua_getfield(State, LUA_GLOBALSINDEX, PChar(Name));
+
+ if (lua_isfunction(State, -1)) then
+ begin //we got a function
+ // move function in front of the arguments (if any)
+ if (nArgs > 0) then
+ lua_insert(State, -(nArgs + 1));
+
+ // call it!
+ if (lua_pcall(State, nArgs, nResults, 0) = 0) then
+ Result := true //called w/o errors
+ else //increase error counter
+ Inc (ErrorCount);
+ end
+ else
+ begin //we have to pop the args and the field we pushed from stack
+ lua_pop(State, nArgs + 1);
+ //leave an errormessage on stack
+ lua_pushstring(State, Pchar('could not find function named ' + Name));
+ end;
end
else
- begin //we have to pop the args and the field we pushed from stack
- lua_pop(State, nArgs + 1);
+ begin //we have to pop the args from stack
+ lua_pop(State, nArgs);
//leave an errormessage on stack
- lua_pushstring(State, Pchar('could not find function named ' + Name));
+ lua_pushstring(State, PChar('plugin paused'));
end;
+
+ if (not Result) AND (ReportErrors) then
+ Log.LogError(lua_toString(State, -1), 'lua/' + sName);
+
+ if ShutDown then
+ begin // plugin indicates self shutdown
+ ShutDown := False;
+ Unload;
+ Result := False;
+ end
end
else
- begin //we have to pop the args from stack
- lua_pop(State, nArgs);
- //leave an errormessage on stack
- lua_pushstring(State, PChar('plugin paused'));
+ begin
+ Log.LogError('trying to call function of closed or not opened lua state', IfThen(HasRegistred, Name, Filename));
end;
-
- if (not Result) AND (ReportErrors) then
- Log.LogError(lua_toString(State, -1), 'lua/' + sName);
end;
{ removes all values from stack }
procedure TLuaPlugin.ClearStack;
begin
- if (lua_gettop(State) > 0) then
+ if (State <> nil) and (lua_gettop(State) > 0) then
lua_pop(State, lua_gettop(State));
end;
-{ Destroys the Luastate, and frees as much mem as possible,
+{ destroys the lua state, and frees as much mem as possible,
w/o destroying the class and important information }
procedure TLuaPlugin.Unload;
begin
if (State <> nil) then
begin
if (Status in [psRunning, psErrorOnRun]) then
- CallFunctionByName('plugin_unload', 1, 0, False);
+ CallFunctionByName('plugin_unload');
ClearStack;
lua_close(State);
diff --git a/Lua/src/lua/ULuaParty.pas b/Lua/src/lua/ULuaParty.pas index 41a0d2ae..25cfce94 100644 --- a/Lua/src/lua/ULuaParty.pas +++ b/Lua/src/lua/ULuaParty.pas @@ -101,14 +101,13 @@ function ULuaParty_Register(L: Plua_State): Integer; cdecl; var
Info: TParty_ModeInfo;
Key: String;
+ P: TLuaPlugin;
begin
// check for table on stack
luaL_checkType(L, 1, LUA_TTABLE);
// get parent id
- 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 ULuaParty_Register');
+ P := Lua_GetOwner(L);
// set mode info to default
@@ -116,8 +115,7 @@ begin // set parent in info rec and pop it from stack
- Info.Parent := lua_toInteger(L, -1);
- lua_pop(L, 1);
+ Info.Parent := P.Id;
// go through table elements
lua_pushNil(L);
diff --git a/Lua/src/lua/ULuaUsdx.pas b/Lua/src/lua/ULuaUsdx.pas index d5277161..c38eec4c 100644 --- a/Lua/src/lua/ULuaUsdx.pas +++ b/Lua/src/lua/ULuaUsdx.pas @@ -49,16 +49,20 @@ function ULuaUsdx_Version(L: Plua_State): Integer; cdecl; arguments: event_name: string }
function ULuaUsdx_Hook(L: Plua_State): Integer; cdecl;
+{ Usdx.ShutMeDown - no results, no arguments
+ unloads the calling plugin }
+function ULuaUsdx_ShutMeDown(L: Plua_State): Integer; cdecl;
+
const
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)
+ (name:'ShutMeDown'; func:ULuaUsdx_ShutMeDown)
);
implementation
-uses SDL, ULuaCore, UHookableEvent, UConfig;
+uses SDL, ULuaCore, ULuaUtils, UHookableEvent, UConfig;
{ Usdx.Time - returns sdl_time to have time numbers comparable with
ultrastar deluxe ones. no arguments }
@@ -68,7 +72,7 @@ begin //remove arguments (if any)
top := lua_gettop(L);
- If (top > 0) then
+ if (top > 0) then
lua_pop(L, top);
//push result
@@ -84,7 +88,7 @@ begin //remove arguments (if any)
top := lua_gettop(L);
- If (top > 0) then
+ if (top > 0) then
lua_pop(L, top);
//push result
@@ -98,19 +102,13 @@ function ULuaUsdx_Hook(L: Plua_State): Integer; cdecl; var
EventName: String;
FunctionName: String;
- ParentId: Integer;
+ P: TLuaPlugin;
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);
+ P := Lua_GetOwner(L);
lua_pop(L, lua_gettop(L)); //clear stack
@@ -119,10 +117,28 @@ begin Event := LuaCore.GetEventByName(EventName);
if (Event <> nil) then
begin
- Event.Hook(L, ParentId, FunctionName);
+ Event.Hook(L, P.Id, FunctionName);
end
else
luaL_error(L, PChar('event does not exist: ' + EventName));
end;
+function ULuaUsdx_ShutMeDown(L: Plua_State): Integer; cdecl;
+ var
+ top: Integer;
+ P: TLuaPlugin;
+begin
+ Result := 0;
+
+ //remove arguments (if any)
+ top := lua_gettop(L);
+
+ if (top > 0) then
+ lua_pop(L, top);
+
+ P := Lua_GetOwner(L);
+
+ P.ShutMeDown;
+end;
+
end.
\ No newline at end of file diff --git a/Lua/src/lua/ULuaUtils.pas b/Lua/src/lua/ULuaUtils.pas index 2bcfea68..de3bd15f 100644 --- a/Lua/src/lua/ULuaUtils.pas +++ b/Lua/src/lua/ULuaUtils.pas @@ -33,7 +33,7 @@ interface {$I switches.inc}
-uses ULua;
+uses ULua, ULuaCore;
{ converts a lua table with a structure like:
* = 1 , * = 4 , * = 5
@@ -42,6 +42,13 @@ uses ULua; does not pop anything }
function Lua_ToBinInt(L: PLua_State; idx: Integer): Integer;
+{ returns plugin that is the owner of the given state
+ may raise a lua error if the parent id is not found
+ in states registry, if state owner does not exists
+ or is not loaded. So a check for a nil value is not
+ necessary }
+function Lua_GetOwner(L: PLua_State): TLuaPlugin;
+
{ this is a helper in case an evenet owner don't has no use for the results
returns number of popped elements }
function Lua_ClearStack(L: Plua_State): Integer;
@@ -61,7 +68,7 @@ begin // default: no bits set
Result := 0;
- lua_checkstack(L, 3);
+ lua_checkstack(L, 2);
if (idx < 0) then
dec(idx); // we will push one value before using this
@@ -81,10 +88,32 @@ begin end;
end;
+{ returns plugin that is the owner of the given state
+ may raise a lua error if the parent id is not found
+ in states registry, if state owner does not exists
+ or is not loaded. So a check for a nil value is not
+ necessary }
+function Lua_GetOwner(L: PLua_State): TLuaPlugin;
+begin
+ 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');
+
+ Result := LuaCore.GetPluginById(lua_toInteger(L, -1));
+
+ lua_pop(L, 1); //< remove state id from stack
+
+ if (Result = nil) then
+ luaL_error(L, '_USDX_STATE_ID has invalid value')
+ else if (Result.Status > psRunning) then
+ luaL_error(L, 'owning plugin is not loaded or already unloaded in Lua_GetOwner');
+end;
+
{ this is a helper in case an evenet owner don't has no use for the results
returns number of popped elements }
function Lua_ClearStack(L: Plua_State): Integer;
- var I: Integer;
begin
Result := lua_gettop(L);
lua_pop(L, Result);
|