aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lua/src/lua/ULuaCore.pas90
-rw-r--r--Lua/src/lua/ULuaParty.pas8
-rw-r--r--Lua/src/lua/ULuaUsdx.pas42
-rw-r--r--Lua/src/lua/ULuaUtils.pas35
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);