GMLive.gml cheat sheet (2024)

This is a "cheat sheet" for GMLive.gml extension by YellowAfterlife.
The extension can be acquired fromGM:Marketplaceor itch.io.
For questions/support, use forums,or send me an email.
An up-to-date version of this document can always be found online.
Click on sections to expand/collapse them.
Quick display controls:Categories· Sections· Everything· Toggle night mode
Using GMLive.gml in GMS1
Initial setup

Setting up is as following:

  • Make sure that you are running an up-to-date version of GameMaker: Studio.
    You can find links to all versions at official website.
  • Import the GMLive extension to the project.
    With GMEZ file, either right-click on "Extensions" category in project tree and pick "import extension", or just drag-and-drop the file onto IDE from Explorer.
  • Import the assets (included files and obj_gmlive) from the package.
    To do so, right-click on the extension, pick "Properties", and use the "Import" tab.
    Depending on factors, it can take GMS1 a bit of time to show the dialog.
    If it's stuck for good, use 7-zip (or equivalent) to unpack the GMEZ file, and import the assets(contents of "datafiles" directory and obj_gmlive.object.gmx) via dragging and dropping them onto IDE.
  • Place obj_gmlive in the first room of the project.
  • Open menu "Resources - Define Macros" (Ctrl+Shift+N) and add a macro called live_enabled with value 1.

Now, as you might know, GMS1 does not let you save project while the game is running on most targets. This can be solved in multiple ways:

A. Use netlog and GMLiveHelper extensions (when on Windows):

  • Right-click on netlog.gmez in Included Files and pick "Open in Explorer".
  • Import netlog.gmez and GMLiveHelper.gmez to the project (much like above).
  • When starting up gmlive-server, also run netlog.exe in Included Files.
  • Use netlog script for debug logging instead of show_debug_message.
    (which will display text in netlog's window when connected or IDE when not)

B. Compile and run the game instead of running it from IDE directly.

C. Use an external editor for changing the "live" files mid-game:

  • There's a free and open-source GM code editor I madethat works well for this (among other things).
    There's also a decent number of plugins for GML supportin existing editors (Notepad++, Sublime Text, Visual Studio Code, etc.).
  • This can be faster than other options because an external editorwill only re-save the file in question while saving the project in GMS1always also re-saves the .project.gmx(and makes a backup if you didn't disable "backup on save" in File - Preferences).
  • The file(s) in question should not be open in GM:S while you are editing them externally,or GMS1 might overwrite them with additional version next time you save the project.If accidents happen, copy the updated code from external editor back to GM:S.Enabling built-in version control for the project reduces the chances of this happening.

Once you are done setting things up, you can remove netlog.gmez and GMLiveHelper.gmez from Included Files.

If you have Neko VM installed, you can also remove all DLL and NDLL files.

If you are not using option A, you can also remove netlog.exe and remove the live_restart_if_necessary line from obj_gmlive's Create event.

(you can always re-import the included files later on)

Starting up
  • Double-click gmlive-server.exe in Included Files to run it.
    You can leave it running when recompiling the game -it will re-scan the project directory whenever a new game instance connects to it.
  • If you've installed GMLiveHelper, also double-click netlog.exe.
    Similarly, can be left running between game sessions.
  • Add live function calls to scripts and events of interest.
    Note that for events the live-call must be in the first block of the event(since GMS simply combines them during compilation),and there may not be non-"Execute code" DnD blocks in the event.
  • Run the game.
  • Change the "live" scripts/events as you see fit and see the changes in-game(if everything was done correctly). gmlive-server's window will report status updates.
Exporting

Usually you do not want non-development buildsof the game to periodically ping a local or non-local address- while not exactly resource-intensive,this may raise warnings on some firewalls and anti-virus software.

For that reason it is suggested that you disable GMLive prior to exporting.

To do so, open menu "Resources - Define Macros" (Ctrl+Shift+N), and change the value of previously defined live_enabled macro to 0.

This will disable the logic inside all of GMLive's scriptsand return default values, having it that nothing will happenwhen calling them, and that they will not influence compile times/output size much as such.

After exporting you can set live_enabled back to 1.

Using GMLive.gml in GMS2/2022+
Initial setup
  • Import the GMLive asset the project:

    • If you bought the asset on GM Marketplace, you can import it using menu:Marketplace➜My Library.
    • If you bought the asset on itch.io, you can import it using menu:Tools➜Import Local Asset Package,or by dragging and dropping the .yymps file onto the workspace area (where the resource editor windows show up) of the GameMaker window.
      Note: .yymp is for GMS2.2.5, .yymps is for the current versions.
  • Import the assets (extension, object, and included files) from the package.
    Note: On Mac/Linux, omit importing Windows-specific exe and ndll files.
  • On Mac/Linux, install Neko VM if you haven't already.
    Neko VM is a tiny (1.5 .. 3.2MB) runtime for cross-platform applications that I usefor GMLive's server application.
  • Place obj_gmlive in the first room of the project.
Starting up (Windows)
  • Open your project directory using menu:Help ➜ Open project in Explorer
    (or navigate to it manually)
  • Navigate to datafilesGMLive
  • Open gmlive-server.exe
    (you may also run it from Command Prompt/PowerShell/etc. if you prefer)
  • Once the server window says "Project load took Xms", the server is ready to go.
    You can leave it running when recompiling the game -it will re-scan the project directory whenever a new game instance connects to it.
  • Add live function calls to scripts and events of interest.
    Note that the event must be GML-type (not a DND space with a GML block)
  • Run the game.
  • Change the "live" scripts/events as you see fit, save the file/project(this is important) and see the changes in-game(if everything was done correctly).
    gmlive-server's window will report status updates.
Starting up (Mac/Linux)
  • Open your project directory using menu:Help ➜ Show Project In Finder/File Manager
    (or navigate to it manually)
  • Navigate to datafilesGMLive
  • Open a Terminal window in the folder.
    On Mac, this is done using menu:Finder ➜ Services ➜ New Terminal at Folder.
    On Linux, this depends on your file manager and/or desktop environment.
    I trust you to know how to open Terminal if you have chosen Linux as your OS.
  • Type neko gmlive-server.n and press Enter.
    If all is well, you'll see "Starting up... (protocol version: ...".
  • Once the server window says "Project load took Xms", the server is ready to go.
    You can leave it running when recompiling the game -it will re-scan the project directory whenever a new game instance connects to it.
  • Add live function calls to scripts and events of interest.
    Note that the event must be GML-type (not a DND space with a GML block)
  • Run the game.
  • Change the "live" scripts/events as you see fit, save the file/project(this is important) and see the changes in-game(if everything was done correctly).
    gmlive-server's window will report status updates.
Exporting

Usually you do not want non-development buildsof the game to periodically ping a local or non-local address- while not exactly resource-intensive,this may raise warnings on some firewalls and anti-virus software.

For that reason it is suggested that you disable GMLive prior to exporting.

To do so, change the value of live_enabled macro in obj_gmlive's Create event to 0.

This will disable the logic inside all of GMLive's scriptsand return default values, having it that nothing will happenwhen calling them, and that they will not influence compile times/output size much as such.

After exporting you can set live_enabled back to 1.

General functions
live_init(update_rate, url, password)

update_rate is how often files should be checked for updates, in seconds.1 is a common value. Lower values can load changed files faster,but will also cause file system to be polled more frequently.

url is the URL that gmlive-server is running on.Most often you would have this as "http://127.0.0.1:5100" to connect to the server on the same machine.

password is the password set via gmlive-server's --password option, as a basic form of security if running the server in an unprotected network. If you did not specify one, this should be left as a blank string.

live_log_script:script(debug_text, log_level)

Can be assigned to a script that GMLive will call to display debug information (such as notifications about scripts being reloaded), e.g.

live_log_script = scr_my_log;

If not assigned, plain show_debug_message calls are used.

log_level can be 0 (info), 1 (warning), or 2 (error).

For example,

live_log_script = function(text, level) { show_debug_message(text); if (level == 2) { // make a beep }}
live_execute_string(gml_code, ...arguments)​➜ok?

Attempts to compile and run a snippet of GML code.

Returns whether execution succeeded. If it did, live_result contains the returned value (if any). If it didn't, live_result contains the error text.

if (live_execute_string(@'show_message("Hello!"); return 1')) { show_debug_message("Result: " + string(live_result));} else show_debug_message("Error: " + string(live_result));

Please keep in mind that much like the similarly-named GM<=8.1 function, this compiles code on every call, thus is not fast and should only be used for debugging (e.g. if you want to be able to type snippets of GML in-game for quick tests)- use live_snippet_create if you need to repeatedly execute dynamic code.

live_snippet_create(gml_code, name = "snippet")​➜snippet

Creates a new "snippet" from a string of code.

Since this pre-compiles code, doing so is faster than live_execute_string for cases where you would want to repeatedly execute the same dynamic code snippet (in parallel with object_event_add in legacy GameMaker).

If there is a compilation error, the function returns undefined and stores the error text in live_result.

var snip = live_snippet_create(@'show_debug_message(argument0 * 2);');if (snip != undefined) { live_snippet_call(snip, 3); // -> 6 live_snippet_call(snip, 5); // -> 10 live_snippet_destroy(snip);} else show_debug_message("Error: " + string(live_result));

Don't forget to destroy your snippets to free up memory when you're done using them!

live_snippet_call(snippet, ...arguments)​➜ok

Executes a previously compiled snippet, returns whether successful.

// ...if (live_snippet_call(snip, 1)) { show_debug_message("Result: " + string(live_result));} else show_debug_message("Error: " + string(live_result));
live_snippet_destroy(snippet)

Destroys a previously created snippet.

Using a snippet after it had been destroyed will generally error.

Live functions
live_call(...arguments)

Calls the "live" version of the current script/event with specified arguments (if any).

Returns whether the "live" version is already loaded and was called.

If execution succeeds, live_result contains the returned value.

If execution fails, live_result contains 0 (also see live_defcall).

For example, if your script takes no arguments, you could do:

/// scr_testif (live_call()) return live_result;return "Hello!";

If your script takes two arguments, you could do:

/// scr_add(a, b)if (live_call(argument0, argument1)) return live_result;return argument0 + argument1;

If your script takes a varying number of arguments, see live_call_ext.

live_call_ext(argument_array)

Same as live_call, but takes arguments in an array instead of a list. You would usually use it like the following:

var argument_arr = array_create(argument_count);for (var i = 0; i < argument_count; i++) { argument_arr[i] = argument[i];}if (live_call_ext(argument_arr)) return live_result;

(unfortunately, GM macros do not currently allow to use argument[] / argument_count inside of them, but you can add the code as a "snippet" in GM)

live_auto_call

In 2.3 version of GMLive, this macro is equivalent to packing up argumentsand calling live_call_ext (as shown above).So, instead of one or other if (live_call... snippet, you can just do

live_auto_call;

and that's it.

live_defcall(...arguments, default_value)

Same as live_call but returns default_value instead of 0 if execution fails.

This is handy if livecoding a script that may only return values of specific type (thus specifying a default value would allow to avoid errors outside of "live" code).

For example,

/// scr_transform_string(string)if (live_defcall(argument0, "")) return live_result;// (some risky manipulations with string)

would return "" if execution of the "live" code fails.

live_defcall_ext(argument_array, default_value)

A mix of live_call_ext and live_defcall - you can both pass arguments as an array and a default return value.

live_result

Stores the returned value from the last live_call (or other "live" group functions) if execution succeeded. If the code did not return anything, holds 0 (GM default for exit).

live_name

In GMS2.3+, it can be hard for GMLive to tell apart inline functions due to theirautomatic naming. To mitigate this, a live_name variable is available and can be setto any unique string prior to live_call for GMLive to know what function it is.

For example,

Greety = function(_name) constructor { name = _name; static greet = function() { live_name = "Greety:greet"; if (live_call()) return live_result; trace("A greet from", name) }}
Resource functions

Apart of the primary feature of live-reloading code, GMLive can also live-reload other resource types.

As an opening note, set_live functions from this category can be called wheneverand have no overhead for repeated calls,so you can set up the callbacks and make yourself a debug console/menu for picking resourcesto live-reload, or even just add-remove a line of code in a "live" script/event.

Sprite functions
sprite_set_live(sprite, enable)

Enables/disables live reloading for a specific sprite.

Does not work for Spine/SWF sprites (as they cannot be reloaded at runtime)and cannot do variable frame timings (since there are no functions for changing this)

For example,

sprite_set_live(spr_test, true);

While it might be tempting to call this for all the sprites, usually you should not,as the server has to watch "live" sprites and their subimage files for changes,and this can add up in disk access time on larger projects.

Limitations:

  • Can't reload SWF sprites because there are no functions for doing so.
  • Can't reload Spine sprites because I don't know much about these.
    (but you might be able to do so yourself using file_set_live).
  • Can't do variable frame timings and broadcast messages.because there are no functions for setting them up.
live_sprite_updated:function(sprite)

You can assign a function/script to this global variable and it will be calledwhenever a sprite gets updated, like so:

live_sprite_updated = function(spr) { show_debug_message("Reloaded " + sprite_get_name(spr)); // any extra logic}
Path functions
path_set_live(path_ind, enable)

Enables/disables live reloading for a specific path (the resource type).

For example,

path_set_live(pt_test, true);

Note that GameMaker stores path positions as a number in 0..1 range so making a pathshorter/longer will cause instances following it to jump around as they readjust.

live_path_updated:function(path)

Like live_sprite_updated, but for paths.

Animation curve functions
animcurve_set_live(animcurve_ind, enable, ?precision)

Enables/disables live reloading for a specific animation curve.

Optional precision determines bezier curve iterations.

For example,

animcurve_set_live(ac_test, true);
live_animcurve_updated:function(animcurve)

Like live_sprite_updated, but for animation curves.

file_set_live(path, ?callback, ?kind)

Enables/disables live reloading for a specific included file.

This can be used for live-updating game data, localization, or anything else.

path is a relative path to the file (e.g. some.txt, or GMLive/gmlive.html).
You may go out of the included file directory using ../ to read other filesinside the project directory (e.g. ../notes/mynote/mynote.txt), but not files outsideof the project directory.

callback is a function/script that will be called whenever the file changes.
The function's first argument will be the new contents (more on this later)and the second argument will be the relative path (as provided here).
Omit this argument or set it to undefined to disable live reloading.

kind is a string determining how to load the file. It can be one of the following:

  • "text": provides file contents as a string.
  • "buffer": provides file contents as a buffer.
    Note that the buffer will be automatically deleted later so you should copy the datafrom it somewhere as necessary.
  • "csv": provides file contents as a CSV grid (using load_csv).
    Similarly, the grid will be automatically deleted afterwards.
  • "json": provides file contents as a JSON value, provided that it's valid JSON.
  • "base64": provides file contents as a base64 string.
    This is the format data is originally received in and is convenient if you intendto decode it yourself as you please.

If kind is not specified or is set to "auto", it will be auto-detected based on file extension:

  • .txt"text"
  • .json"json"
  • .bin"buffer"
  • .csv"csv"
  • .b64, .base64"base64"

If the file extension is not recognized, an error is thrown.

Example (assuming that you have a test.txt in your Included Files):

file_set_live("test.txt", function(_text, _path) { show_debug_message(_path + " has been updated: " + _text);});

With a file type override:

file_set_live("test.txt", function(_buf, _path) { show_debug_message(_path + " is now " + buffer_get_size(_buf) + " bytes long");}, "buffer");

Disabling live-reloading:

file_set_live("test.txt", undefined);
Room functions
Setting up
  • Create an empty object and name it, for example, obj_blank;
  • Create an empty room and name it, for example, rm_blank;If using GMS2, remove the default instance and background layers;Add the following to its Room Creation Code:

    live_room_start();
  • Assign the two to live_blank_object and live_blank_room in obj_gmlive's Create event:

    live_blank_object = obj_blank;live_blank_room = rm_blank;
room_set_live(room, enable)

Enables/disables live reload for a specific room. Don't forget to setup helper resources first.

For example,

room_set_live(rm_test, true);

Can be called at runtime, including from "live" code.

room_goto_live(room)

Transits to the specified room much like regular room_goto.

If a "live" version of the room is loaded, transits to live_blank_roominstead and loads the new version of the room there.

live_room_updated

If set, this script will be called whenever a new version of a room is received.

By default this does an equivalent of

live_room_updated = function(_rm) { room_goto_live(_rm);};

but you can also add your own logic this way.

Limitations
Referencing "live" instances by name from non-"live" code

Since instance names are transformed into hardcoded instance IDs during compilation, this will not work.
Consider assigning instances of interest into global variables in room creation codeif you need to - that way you'll assign IDs that were given out to "live" versions asthe "live" code would know the "new" ones.

(anything else?)

This feature is relatively new and the topic of room loading is relatively complex soit is possible that you'll encounter some issues that I've not even thought of testing for.Make sure to report things that break!

Shader functions

These are currently experimental.

Setting up

First, you will need an extension to perform shader replacement.

There are a few options,

  • shader_replace_simple
    A minimalistic extension by me.
    Admittedly barebones (single function, some limitations) but works in GMS1+GMS2.
    If imported, GMLive will auto-assign live_shader_updated so that you don't have to.
  • Live Shader Editor
    A little more feature-rich, GMS2 only (?).
    Not out yet as of me writing this on Jan 28, 2020.
    2021 edit: it would appear like development of the extension has been abandoned.

As of writing this, there is not a Mac OS compatible extension,and it is as of yet unclear whether it is possible to implement one.

live_shader_updated:script(shader, hlsl_vertex_code, hlsl_pixel_code)

A script should be assigned to this variable and will be executed whenever a shader should be reloaded.

For example,

live_shader_updated = scr_shader_reloaded;

and then in scr_shader_reloaded:

/// scr_shader_reloaded(shader, hlsl_vertex_code, hlsl_pixel_code)// ... call your respective function to replace the shader

or, for 2.3,

live_shader_updated = function(shader, hlsl_vertex_code, hlsl_pixel_code) { // ... call your respective function to replace the shader}

GMLive will automatically assign shader_replace_simple's function if available.

shader_set_live(shader, enable)

Enables/disables live reloading for a specific shader.

For example,

shader_set_live(sh_test, true);

Can be called at runtime, including from "live" code.

API functions

The following functions are designed to add/override how GMLive will compile codeand are designed for rare cases where something doesn't work rightor to get around limitations with calling extension functions.

Note that changing the API only affects newly compiled live code / snippets- you should perform such operations on game start.

live_function_add(signature, impl)

Registers a function for use in GMLive code / snippets.

signature is function signature, including the name, such as:

  • clamp(a, b, c) (normal),
  • instance_destroy(?id, ?execEvent) (prepend optional arguments with ?)
  • max(...values) (include ... for trailing arguments).

impl (a script in 2.2, a function in 2.3)will then be called with provided arguments as normal.

For example,

live_function_add("video_open(path)", scr_video_open);

and then in scr_video_open

video_open(argument0);

in 2.3, this can be written as

live_function_add("video_open(path)", function(path) { video_open(path);});

You may call live_throw_error to hand an error back to the executing "live" code(such as noting that arguments are mis-typed if this would result in a catastrophic error otherwise).

live_variable_add(signature, impl)

Registers a global built-in variable for use in GMLive.

signature is the variable signature in fnames format:

  • room_speed (a read/write variable)
  • fps* (a read-only variable)
  • view_xport[] (an array)

impl (a script in 2.2, a function in 2.3)will be called with the following arguments:

  • argument0: whether writing (true) or reading (false) the variable.
  • argument1: if writing the variable, this contains the new value.
  • argument2: if the variable is an array, this contains the index.
    Please note that, honoring how GameMaker (still!) works,a = view_xport; is equivalent to a = view_xport[0];.

You may call live_throw_error to hand an error back to the executing "live" code(such as preventing out-of-bounds array access for fixed-size arraysor performing value validation on write).

For example,

live_variable_add("my_room_speed", scr_my_room_speed);// and then in scr_my_room_speedif (argument0) { room_speed = argument1;} else return room_speed;

or, in 2.3,

live_variable_add("my_room_speed", function(set, val) { if (set) { room_speed = val; } else return room_speed;});
live_constant_add(name, value)

Registers a constant for use in GMLive.

There isn't much to this one - name and value.

live_constant_add("MATCHMAKING_SESSION", MATCHMAKING_SESSION);
live_throw_error(text)

When ran from a function that is being ran by live code / snippet,this passes an error message to GMLive, which will abort code execution.

In GMS2.3 you may instead use show_error or throw.

I cannot think of why you would want to unregister API entries, but, just in case:

live_function_remove(name)

Removes a previously registered function.

live_variable_remove(name)

Removes a previously registered global built-in variable.

live_constant_remove(name)

Removes a previously registered constant.

GMS2.3+ functions
live_method(self, func)​➜method

Like the built-in method function,but supports re-binding functions produced by GMLive code.

live_method_get_self(func)​➜

Like the built-in method_get_self function,but returns correct values for functions produced by GMLive code.

Technical topics
gmlive-server

Is a helper application for GMLive.gml. It does a few things:

  • Fetches resources from the project.
  • Watches "live" files for changes.
  • Sends updated files to the game.

Starting up without arguments (such as by double-clicking the executable) has it automaticallylook for a GMS1/GMS2 project in the parent directory.

Passing an argument (such as by dragging a file/directory onto the executable) has it load up the specified project.

Starting up from command-line/PowerShell/terminal allows to specify additional arguments:

  • --port <port number>: Sets a custom port to run the server on.You shouldn't need to touch this unless the default port (5100) is being used by some other application or you desire to run multiple gmlive-server instances on multiple project directories at once.
  • --password <string>: Sets a custom password (to be passed in live_init).
  • --timeout <seconds>: Adjusts connection timeout for clients.In other words, how long it is without a response before a connection is dropped and related data structures are cleaned up. Default is 60 seconds and you wouldn't usually need to touch this unless you have issues with the game disconnecting during a step-by-step debug session.
  • --runtimePath <path>: If your GMS2 runtimes somehow don't reside in the usual location and gmlive-server fails to detect them as result, you can use this to force a path (which would end on \runtime-a.b.c.d)

On the technical side, gmlive-server is a Neko VM application. For Windows, the few DLLs it uses and an executable version are packaged together with it. On Mac, you'll need to install Neko VM binaries (~1.5MB) to be able to run it from terminal via

neko gmlive-server.n
Error handling

Things that GMLive takes care of:

  • Syntax errors in "live" code
    (code will not be updated if the new version doesn't compile)
  • Value errors (e.g. trying to add a string to a number, dividing by 0)
  • Missing variables/instances
  • Wrong argument types passed to common built-in functions

When a "runtime" error occurs, it is logged and the "live" script/event halts execution.This does not prevent subsequent attempts to execute the code.

Things that GMLive cannot take care of:

  • Runtime errors in non-"live" scripts
  • Fatal errors thrown by built-in functions (e.g. memory allocation errors)

If you are using GMS1 or older versions of GMS2 (2.2.5 or earlier),you can also use catch_errorand a "GMLiveForGMSX_and_catch_error" version of the extension to prevent a number of crashes.

Using GMLive on Windows and Mac/Linux at once

If you have the same project directory shared between a Windows and non-Windows machine(via cloud sync, network folder, SyncThing, version control, etc.)and want to be able to use GMLive without adding/removing files,you can do any of the following:

  • Make a copy of GMLive folder so that you have one for Windows (with EXE and NDLLs)and one for Mac/Linux (without NDLLs).
  • If using Git, delete the NDLL files, commit the deletion,add them back on Windows machine, and alsoadd them to .gitignore so that they do not make it to Mac/Linux machines.
  • Install Neko VM on Windows so that you don't need the NDLLs nor the EXE(and subsequently run neko gmlive-server.n from Command Prompt/PowerShell)
  • Copy the GMLive folder elsewhere and run it from Command Prompt/PowerShell/terminalwith a path to your YYP (see above).
Limitations
Performance

On average, any time you add another layer on interpreted code, performance degrades 5x..10x- YYC code is on average 5 times slower than equivalent handwritten C++ code,non-YYC GML is about 3..5 times slower than that, and GMLive,having runtime compiled to GML,has roughly GM8.1 level of performance on non-YYC and roughly regular GMS level of performance on YYC.

This has a few implications:

  • Enabling livecoding for too many performance-critical scripts at once isn't a good idea.
    GMLive versions from 1.0.48 onward will not compile-interpret code until a script/eventis changed after game start, but still there is minor overhead in checking whether thescript/event has a "live" version loaded or not.
  • Using GMLive for ad-hoc modding support isn't a super good idea
  • both for performance reasons and because the interpreted scripts would havecomplete access to GameMaker API and game's resources.
    You can look into tiny expression runtime

That said, both GMLive and GameMaker are being worked on, thus things will likely improve as time goes on.

Use of GMLive for modding

Although it may be tempting to use GMLive'slive_execute_string and Snippet APIfor ad-hoc modding support,the consequences of that aren't unlike use of execute_string -you would be executing code without any security measures in place,meaning that scripts could crash the game, corrupt save data or unrelated variables, and so on.

Better options would be:

  • tiny expression runtime
    An open-source example project and accompanying tutorial on writing purpose-specificscripting languages. Can be highly customized in terms of access and sandboxing.
  • Apollo
    A native wrapper for industry-standard Lua.
    Similarly has sandboxing and full control over what executed code can access.
  • For projects with higher requirements,I may be available for contract work and had builtall kinds of compilers and interpretersfor clients over years.
Calling functions in native extensions

GMLive by default has entirety of standard GameMaker API and all game-specific resourcesexposed to it, but native extension's functions currently cannot be dynamically referenced,therefore you would not be able to call them from "live" code by default.

As a workaround, you can make a script that calls the function, and then call that script(this is also what GMLive does for built-in GM functions).

Copy-on-write behaviour in arrays

NOTE: As of GM2022, copy-on-write has been deprecated and is turned off by defaultin new projects.

GML itself has a particular feature(see "Advanced Array Functionality") that has it so that passing an array as an argumentto a script, and then changing it via arr[index] = value(rather than arr[@index] = value) would duplicate the array prior.

The internal data for this is not exposed, however,so GMLive is unable to do it in the same way,and only does "create-on-write" (replacing a value with a new array if it isn't yet).

If this doesn't make immediate sense, it is unlikely that you rely on this feature anywhere.

API compatibility

Since GMLive reasonably needs to reference every function and constantyet there is no way to go over constants nor get information about function argumentsat runtime, so the extension has this massive script with function definitions andseries of live_function_add/live_variable_add/live_constant_add calls.

Here are the specific cases and instructions for getting around them:

Function signature changes

As of GMS2022, GMLive will gracefully new functions appearing (albeit with no argument count checks)or functions going missing, but it cannot handle argument changes for existing functions -like the infamous reduction of buffer_set_surface from 5 to 3 arguments,or introduction of an optional argument to instance_create_depth.

When this happens, GMLive will refuse to compile code with seemingly-incorrect argument counts,but you can fix this yourself:

live_function_add("instance_create_depth(x, y, depth, object, ?vars)", instance_create_depth);
Constants

If a GameMaker update adds new constants, "live" code will not be able to reference themuntil a GMLive update releases, but you can also handle this yourself, like so:

live_constant_add("some_constant", some_constant);

But if a constant is removed, you'll get a startup error in GMLiveAPI.
You can comment out the offending lines in the script, but it can be easier to addan empty macro for each such constant, like so:

#macro some_constant undefined
Variables

On occasion, a GameMaker update might introduce a new global variable that"live" code wouldn't be aware of. You can fix this like so:

live_variable_add("some_variable", function(set, val) { if (set) { some_variable = val; } else return some_variable;});
Troubleshooting
Code does not update
  • Make sure that you are saving the file (Ctrl+S).
  • Make sure that gmlive-server is running.
  • Check the output log for any compile/runtime errors with new code.
  • Check gmlive-server window for any project load errors.
  • Check if the time next to the client in gmlive-server window is ticking.
    If it's not ticking, you likely accidentally deactivated/destroyed obj_gmlive.
"Argument index is out of range"

This usually happens for one of two reasons:

  • You are calling the script with fewer arguments than you have the code expect
    (in which case GM would throw you an error as well).
  • You forgot to add script arguments to live_call/live_call_ext.
"Couldn't find live function"

There are generally two possible causes for this error:

  1. You are trying to live-code a function-in-function(e.g. a static function inside a constructor)or function-in-event(e.g. a function assigned inside a Create event).
    Depending on GameMaker version,debug_get_callstack() output can be unreliable for such cases,so use of live_name is necessary for GMLive to know which functionit should be taking the new code from.
  2. You are using a macro that has not been auto-detected as containing a live-call.
    Try using one of the default live_call functions instead.
"Can't call instance-specific function - instance does not exist."

You can occasionally get this error in output log when calling scripts for instancesafter deactivating/destroying them - currently the only way self/otherinstances can be set up for a call is via with blocks,and these do not work with deactivated/destroyed instance IDs.

GMLive uses a few workarounds to get around this in common situations(applying to original self/other instances of the event), but if you have something like

with (some_instance_id) { instance_destroy(); scr_some_instance_script();}

that may show that error.

As a workaround, you can either change your code not to attempt to call scripts on freshlydeactivated/destroyed instances, or move the D/D+call branch into a separate script.

Problems with tilemaps in "live" rooms

If you are using layer_tilemap_get_id, you should be aware (as per manual) that it does not workwith "dynamically" created tilemaps, including those made by GMLive.

The workaround is to make a little function, which would look as following in GMS2.3:

function layer_tilemap_get_id_fixed(_layer) { var els = layer_get_all_elements(_layer); var n = array_length_1d(els); for (var i = 0; i < n; i++) { var el = els[i]; if (layer_get_element_type(el) == layerelementtype_tilemap) { return el; } } return -1;}

and as so in GMS2.2.5 and older versions:

var els = layer_get_all_elements(_layer);var n = array_length_1d(els);for (var i = 0; i < n; i++) { var el = els[i]; if (layer_get_element_type(el) == layerelementtype_tilemap) { return el; }}return -1;
What is "GMLive - copy.gml"?

Occasionally I make a copy of one or other GMLive script to run a diff on thembefore publishing an update and forget to remove them later. Such files are safe to remove.

"Failed to load library : no suitable image found. "

You can get this on Mac if you did not remove the original ndll files- NDLLs that Windows uses are different from those for OSX.

"Cleartext HTTP traffic not permitted" on Android

You'll need to add

<android:usesCleartextTraffic="true">

to "Game Options ➜ Android ➜ Permissions - Inject to Application Tag".

Running game in debug mode skips over create events

GameMaker versions prior to 2.3 have a curious bug that has it thatif your game has "enough" code in it and your computer matches the unknown requirements,the debugger may choke for a bit, causing the game to skip events for the first few frames.

Since GMLive adds about 900KB worth of GML code to your game, it tends to tip off the issue for affected users.

The solution is to add a blank room in front of the rest, and add a blank object to it which has a step event with something like the following:

if (!debug_mode || ++x > xstart + 3) { instance_destroy(); room_goto_next(); // or room_goto(real_init_room)}

In worse cases, 3 may be increased until the issue is no longer present.

The issue appears to occur to fewer users in GMS2.3+

GMLive.gml cheat sheet (2024)
Top Articles
Latest Posts
Article information

Author: Nathanael Baumbach

Last Updated:

Views: 6351

Rating: 4.4 / 5 (75 voted)

Reviews: 90% of readers found this page helpful

Author information

Name: Nathanael Baumbach

Birthday: 1998-12-02

Address: Apt. 829 751 Glover View, West Orlando, IN 22436

Phone: +901025288581

Job: Internal IT Coordinator

Hobby: Gunsmithing, Motor sports, Flying, Skiing, Hooping, Lego building, Ice skating

Introduction: My name is Nathanael Baumbach, I am a fantastic, nice, victorious, brave, healthy, cute, glorious person who loves writing and wants to share my knowledge and understanding with you.