DEADSOFTWARE

43fe3afc42227e6d453417bc604a2b7e2265de7f
[d2df-sdl.git] / src / game / g_scripts.pas
1 (* Copyright (C) DooM 2D:Forever Developers
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *)
16 {$MODE DELPHI}
17 unit g_scripts;
19 interface
21 uses
22 lua, lualib, lauxlib;
24 const
25 // reset levels
26 RESET_ALL = 0;
27 RESET_SRV = 1;
28 RESET_WAD = 2;
29 RESET_MAP = 3;
31 type
32 PScriptContext = Plua_State;
33 PScriptProc = lua_CFunction;
35 var
36 gScriptCtx: PScriptContext = nil;
37 gScriptInit: Boolean = False;
39 function g_Scripts_Init(): Boolean;
40 procedure g_Scripts_Reset(What: Integer);
41 function g_Scripts_ProcExec(PName: string; const Args: array of const): Integer;
42 function g_Scripts_ProcExists(PName: string): Boolean;
43 function g_Scripts_ProcInstall(PName: string; PPtr: PScriptProc): Boolean;
44 function g_Scripts_Load(Text: string): Boolean;
45 procedure g_Scripts_Free();
47 implementation
49 uses
50 SysUtils, g_console, g_scriptprocs;
52 type
53 POpenFunc = function(L: Plua_State): LongBool; cdecl;
54 TLuaReg = record
55 name: PAnsiChar;
56 func: POpenFunc;
57 end;
59 const
60 LUA_LIBS: array [0..3] of TLuaReg = (
61 (name: ''; func: luaopen_base),
62 (name: LUA_TABLIBNAME; func: luaopen_table),
63 (name: LUA_STRLINAME; func: luaopen_string), // STRLINAME is actually a typo in fpc's lua module
64 (name: LUA_MATHLIBNAME; func: luaopen_math)
65 );
67 function LuaInstallGameFuncs(): Boolean;
68 begin
69 Result := False;
71 if not g_Scripts_ProcInstall('conprint', SP_Lua_ConPrint) then Exit;
73 Result := True;
74 end;
76 function g_Scripts_Init(): Boolean;
77 var
78 i: Integer;
79 begin
80 Result := False;
81 if gScriptInit then Exit;
83 gScriptCtx := luaL_newstate();
84 if gScriptCtx = nil then Exit;
86 // don't open all the libs
87 for i := 0 to High(LUA_LIBS) do
88 begin
89 //lua_pushcfunction(gScriptCtx, LUA_LIBS[i].func);
90 lua_pushstring(gScriptCtx, LUA_LIBS[i].name);
91 //lua_call(gScriptCtx, 1, 0);
92 LUA_LIBS[i].func(gScriptCtx);
93 end;
95 // create a table for game-related functions
96 lua_newtable(gScriptCtx);
97 lua_setglobal(gScriptCtx, 'game');
99 // create game-related tables
100 g_Scripts_Reset(RESET_ALL);
102 gScriptInit := True;
103 // try to install game-related shit
104 if not LuaInstallGameFuncs() then
105 begin
106 g_Console_Add('SCRIPT: Could not init game callbacks');
107 lua_close(gScriptCtx);
108 gScriptCtx := nil;
109 gScriptInit := False;
110 Exit;
111 end;
113 Result := True;
114 end;
116 // TODO: maybe actually put some fields into these?
117 procedure g_Scripts_Reset(What: Integer);
118 begin
119 if not gScriptInit then Exit;
120 if What in [RESET_ALL, RESET_SRV] then
121 begin
122 lua_newtable(gScriptCtx);
123 lua_setglobal(gScriptCtx, 'srv');
124 end;
125 if What in [RESET_ALL, RESET_WAD] then
126 begin
127 lua_newtable(gScriptCtx);
128 lua_setglobal(gScriptCtx, 'wad');
129 end;
130 if What in [RESET_ALL, RESET_MAP] then
131 begin
132 lua_newtable(gScriptCtx);
133 lua_setglobal(gScriptCtx, 'map');
134 end;
135 end;
137 function g_Scripts_ProcInstall(PName: string; PPtr: PScriptProc): Boolean;
138 begin
139 Result := False;
140 if not gScriptInit then Exit;
142 if g_Scripts_ProcExists(PName) then
143 begin
144 g_Console_Add('SCRIPT: ProcInstall(' + PName + '): function already exists');
145 Exit;
146 end;
148 lua_getglobal(gScriptCtx, 'game');
149 lua_pushstring(gScriptCtx, PName);
150 lua_pushcfunction(gScriptCtx, PPtr);
151 lua_settable(gScriptCtx, -3);
152 lua_setglobal(gScriptCtx, 'game');
154 Result := True;
155 end;
157 function g_Scripts_ProcExists(PName: string): Boolean;
158 begin
159 Result := False;
160 if not gScriptInit then Exit;
162 lua_getglobal(gScriptCtx, 'game');
163 lua_pushstring(gScriptCtx, PName);
164 lua_gettable(gScriptCtx, -2);
166 if lua_isfunction(gScriptCtx, -1) then
167 Result := True;
168 end;
170 function g_Scripts_ProcExec(PName: string; const Args: array of const): Integer;
171 var
172 i: Integer;
173 begin
174 Result := -255;
175 if not gScriptInit then Exit;
177 lua_getglobal(gScriptCtx, 'game');
178 lua_pushstring(gScriptCtx, PName);
179 lua_gettable(gScriptCtx, -2);
180 if not lua_isfunction(gScriptCtx, -1) then
181 begin
182 g_Console_Add('SCRIPT: ProcExec(' + PName + ') error: no such function');
183 Exit;
184 end;
186 for i := 0 to High(Args) do
187 with Args[i] do
188 begin
189 case VType of
190 vtInteger: lua_pushinteger(gScriptCtx, vInteger);
191 vtBoolean: lua_pushboolean(gScriptCtx, vBoolean);
192 vtString: lua_pushstring(gScriptCtx, vString^);
193 vtAnsiString: lua_pushstring(gScriptCtx, PAnsiString(vAnsiString)^);
194 vtExtended: lua_pushnumber(gScriptCtx, vExtended^);
195 end;
196 end;
198 if lua_pcall(gScriptCtx, Length(Args), 1, 0) <> 0 then
199 begin
200 g_Console_Add('SCRIPT: ProcExec(' + PName + ') error: ' + lua_tostring(gScriptCtx, -1));
201 Exit;
202 end;
204 if not lua_isnumber(gScriptCtx, -1) then
205 begin
206 g_Console_Add('SCRIPT: ProcExec(' + PName + ') error: return value is not a number');
207 Exit;
208 end;
210 Result := lua_tointeger(gScriptCtx, -1);
211 lua_pop(gScriptCtx, 1);
212 end;
214 function g_Scripts_Load(Text: string): Boolean;
215 begin
216 Result := False;
217 if not gScriptInit then Exit;
219 if lua_dostring(gScriptCtx, PChar(Text)) <> 0 then
220 begin
221 g_Console_Add('SCRIPT: Load() error: ' + lua_tostring(gScriptCtx, -1));
222 Exit;
223 end;
225 Result := True;
226 end;
228 procedure g_Scripts_Free();
229 begin
230 if not gScriptInit then Exit;
231 lua_close(gScriptCtx);
232 gScriptInit := False;
233 gScriptCtx := nil;
234 end;
236 end.