-
-
Notifications
You must be signed in to change notification settings - Fork 438
Lua API
The Hitchiker's Guide to MTA's Lua API
- How to add a new Lua definition
- How to migrate to the "new" argument parser
- How to rename functions
- How to delete functions
When adding new Lua definitions, there are a few things you need to be aware of:
- You should always add your function to the client/server function init list (scroll down for the server list).
- Since 5 April 2020, in #973, we introduced a new Lua argument parser. We recommend that all new code uses this "new" style of parsing Lua arguments.
- Most existing code uses
CScriptArgReader
, which is an old-but-still-supported method of parsing arguments. The "new" argument parser does not work perfectly for every use case, and in those scenarios we accept the use ofCScriptArgReader
.
The new parser is quite straight forward to use, it's much cleaner than the old one.
Note: There are 4 false-positive errors which you can ignore.
Full error text
template parameter "Ret" is not used in or cannot be deduced from the template argument list of class template "CLuaOverloadParser<Func, Func2>"
template parameter "Args" is not used in or cannot be deduced from the template argument list of class template "CLuaOverloadParser<Func, Func2>"
template parameter "Ret" is not used in or cannot be deduced from the template argument list of class template "pad_func_with_func<Func, FuncB>"
template parameter "Args" is not used in or cannot be deduced from the template argument list of class template "pad_func_with_func<Func, FuncB>"
To add a new function:
- Add a new function on the C++ side:
- Go to the appropriate header, for example if you want to add a new function for elements go to
CLuaElementDefs.h
- Add the function definition. For example, if you want the function to take in an Element, a string and a bool and returns a bool:
static bool YourFunction(CElement* element, std::string string, bool bl)
. It is very important not to forget thestatic
keyword. - Now, go the the source file (Right click -> Toggle header / Code file or Ctrl K, Ctrl O)
- Here you will need to define the function:
Note how theres nobool CLuaElementDefs::YourFunction(CElement* element, std::string string, bool bl) { /* do something here */ return true; /* return some value */ }
static
, only in the header. See CLuaCryptDefs.cpp for some good examples. - Go to the appropriate header, for example if you want to add a new function for elements go to
- Go to the
::LoadFunctions()
function in the givenLuaDefs
class- Add a new entry into the
functions
array like so:{"yourFunctionsLuaName", ArgumentParser<YourFunction>}
- where:-
yourFunctionsLuaName
is the name of the function in Lua -
YourFunction
is the function to-be-called on the C++ side
-
- Add a new entry into the
-
error C2065: 'CLuaFunctionParser': undeclared identifier
: Go to the top of the file, and add#include <lua/CLuaFunctionParser.h>
- Something weird like the function (in this case
YourFunction
) is inaccessible: Make sure you've added thestatic
keydowrd in the header -
Undefined function
: Make sure you didn't forget to add the class prefix to the function in the source file. Eg, you wrote:bool YourFunction
instead ofbool CLuaElementDefs::YourFunction
. - Anything else? Ask us over at the development Discord.
Most existing code uses CScriptArgReader
, which is an old-but-still-supported method of parsing arguments. The "new" argument parser does not work perfectly for every use case, and in those scenarios we accept the use of CScriptArgReader
.
Copy and paste warning: we error for bad types, now
You may see some m_pScriptDebugging->LogCustom(luaVM, argStream.GetFullErrorMessage());
. Use luaL_error(luaVM, argStream.GetFullErrorMessage());
instead.
TODO: improve explanation - we use hard errors now, see #821
Copy and paste warning: very old code performs compulsive checking
Note that some very old code that uses CScriptArgReader
might compulsively check the validity of pLuaMain
, pResource
, or other arguments. There is no need to do this.
For example, CLuaFunctionDefs::ExecuteCommandHandler grabs pLuaMain
and doesn't use it anywhere — this is unnecessary!
Here you will need to use ArgumentParserWarn
instead of ArgumentParser
.
(The only difference is that the new parser will hard error on usage mistakes, while the other (ArgumentParserWarn
) won't.).
You need to specify an additional parameter, the return value in case the function threw an error. This value is usually false
, but somne function's might return nil
(with lua_pushnil
), in which case you will need to specify nullptr
(We use nullptr
to represent nil
).
Okay, so, let the function you want to refactor be called YourFunction
, this is how the ArgumentParser
part should look like: ArgumentParserWarn<<ReturnValueOnErrorHere> YourFunction>
where ReturnValueOnErrorHere
is the value to-be-returned if the function fails.
Function renames are primarily a change in documentation—we don't delete old functions when performing renames. If the syntax is changing, you often want to keep the original definition around (example 1). If just the name is changing, you can rename everything, but add an additional alias for the old function name (example 2).
-
If the new function requires a different syntax, don't rename any Lua definitions.
If the new function is just a rename, rename the Lua function definitions and add an alias with the old function name.
-
Make sure you add the new function to the init lists, as mentioned above.
-
Add to the server/client deprecated list.
-
If the deprecation is a simple rename, set the
bRemoved
field tofalse
. This allows MTA to automatically upgrade the script to use the new function. -
If the function was removed and cannot be automatically upgraded (due to a change in syntax), set
bRemoved
totrue
. This tells MTA to not automatically upgrade the script. You can also include an extra note explaining how to migrate to the new function, as shown here. -
If the old functions still work as expected, cannot be automatically upgraded, and you'd like to move people to the new functions... hold off on adding a deprecation entry. In this example (read #289 too) we commented out this deprecation entry because it was too annoying.
This means that servers do not have to immediately adopt new function names, thus allowing nightly servers to serve stable clients.
-
Example 1:
Jetpack renamed from givePedJetpack
and removePedJetpack
to setPedWearingJetpack
. We did not delete the original functions and we did not add a deprecation entry. (We did actually add the deprecation entry, but we later reverted it.)
TODO: make this section look better
Example 2
We used to have a function setVehicleTurnVelocity(vehicle, velX, velY, velZ)
. Later, we extended this to support more than just vehicles, so we renamed this to setElementAngularVelocity
.
- We added entries to
clientFunctionInitList
andserverFunctionInitList
. - We added entries to
clientDeprecatedList
andserverDeprecatedList
. Because this is just a simple alias, the first field (bRemoved
) is set tofalse
.
It most cases you should not delete functions. Here are some examples of when it's okay to actually delete functions:
-
The function was only introduced in a nightly, and did not make it into a Point Release.
For example, if 1.5.7 released in January, and you added a new function in February, it's OK to delete that function any time before August, when 1.5.8 releases.
-
The original functionality is completely unusable.
For example,
engineLoadIFP
was introduced in 2010 and then quickly removed due to instability. Then this function was re-introduced with a new API eight years later.(This is perhaps a bad example, because this function never actually made it into a Point Release.)
I really want to delete a function
TOOD: add instructions on where to look for things to delete
Also, if the function did not make it into a Point Release, follow the instructions above on adding to the deprecation lists.
Project Management
Git cheat sheet
Release Checklist
Code Review
Documentation
Contributors Guide
Style Guide
Lua API
Dev Tips
BitStream
CAccountPassword
Debug Settings
General
Testing Lua
Dependencies
MTADiag
Future Planning
CEF Versions
Windows XP Support
Things for 1.6