Skip to content

Lua API

Qais Patankar edited this page Aug 22, 2020 · 6 revisions

The Hitchiker's Guide to MTA's Lua API

Table of Contents

  1. How to add a new Lua definition
  2. How to migrate to the "new" argument parser
  3. How to rename functions
  4. How to delete functions

How to add a new Lua definition

When adding new Lua definitions, there are a few things you need to be aware of:

  1. You should always add your function to the client/server function init list (scroll down for the server list).
  2. 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.
  3. 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.

The new way: ArgumentParser

  • TODO: provide instructions and examples for ArgumentParser

The old way: CScriptArgReader

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!

How to migrate to the "new" argument parser

TODO: this section needs to be written. basically, make sure you use ArgumentParserWarn.

How to rename functions

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).

  1. 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.

  2. Make sure you add the new function to the init lists, as mentioned above.

  3. Add to the server/client deprecated list.

    • If the deprecation is a simple rename, set the bRemoved field to false. 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 to true. 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.

  1. We added entries to clientFunctionInitList and serverFunctionInitList.
  2. We added entries to clientDeprecatedList and serverDeprecatedList. Because this is just a simple alias, the first field (bRemoved) is set to false.

How to delete functions

It most cases you should not delete functions. Here are some examples of when it's okay to actually delete functions:

  1. 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.

  2. 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: also 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.

Clone this wiki locally