GameMaker GMS "Headless", Start-up commands, and Logging via Powershell

Bingdom

Googledom
GM Version: GMS1.4 and Up
Target Platform: Windows
Download: N/A
Links:
https://www.yoyogames.com/blog/37/command-line-parameters-for-gamemaker-studio
https://docs.microsoft.com/en-us/powershell/

Summary
We will begin first by creating .exe parameters. After that, we will start a GMS program as a "background process", and learn how to interpret parameters through GML. We then will monitor the console log through Windows PowerShell and demonstrate a powerful script.

I have described this as "Headless" because I don't have a better name to describe it.

This tutorial does not cover receiving instructions over a connection, or any server related material. This is more of an introduction on how you could make your application potentially headless.

Tutorial
Let's say you're making a game, and you've designed your game network's structural design to use a dedicated server.

Now, you could write it in a different language, and have the benefits of multithreading. But let's say the network task must be completed in a month, and you don't have weeks to invest in a new language.

You don't want to split your project into 2 parts, as managing 2 projects would be a monotonous task.

You also don't want the host to deal with 2 applications. You'd want to give them the option to hide the window, right?

Handling parameters
Game maker has neat functions to deal with .exe parameters. They are parameter_count and parameter_string.
To deal with such parameters, we will store them into an array. We will use a different version of the manual's example.
Code:
var p_num;
p_num = parameter_count();
for (var i = 0; i < p_num; i += 1) {
   p_string[i] = parameter_string(i);
}
Ok, we have the code, now how do we pass these "parameters".

The answer is; it's easy. If you already know what to do, feel free to skip to Starting GM game as a background process.

First, you'll need to export your game.
Then, create a shortcut
upload_2018-12-8_10-56-46.png

Right click on that shortcut -> Go to properties.

In the "Target" field, feel free to add all sorts of commands after the end of the directory.
upload_2018-12-8_11-5-26.png

Now if you draw your array, you should be able to see them.
upload_2018-12-8_11-9-10.png

These parameters function in any way you like. Try to make "noshaders" change the background colour, and make "gmc" change the font colour. If you do not know how, we will cover an approach with dealing with parameters in Making parameters functional.

If you were making a multiplayer game, you can have ip address, port, hostname, host description, and other configuration data as parameters.

Starting GMS applications as a background process
This part is going to be short.

All we need to do is have draw_enable_drawevent(false) in the create event. The GM window will not appear. So you'll need to kill it in task manager. Alternatively, you could set a timer to set the draw event to true, which will create the window.

If we do this, the player would not be able to play your game (of course!). We would want this as a parameter like what we did before, right?

Making parameters functional
We want to give players an option to start the game with no window for their dedicated server, right? You can call your own parameter in any name you like, but in this case, we will name this parameter "-nowindow".

We will grab the code that we used before, and use a switch statement to process the parameters.
Code:
var p_num;
p_num = parameter_count();
for (var i = 0; i < p_num; i += 1) {
   p_string[i] = parameter_string(i);
   switch(p_string[i]) {
      case "-nowindow":
         draw_enable_drawevent(false);
      break;
   }
}
Cool, we learnt how to pass in parameters and how to deal with them. But did you know that GMS has their own parameters? You can find a list of them here (applies to gms2 too).

Tracking console output
As mentioned earlier, GMS has their own parameters (which you can see here). If you've gone through the list, you may have noticed "-output".

To quote what the website describes it as
  • output <filename> : sends console output to the filename
By using the function show_debug_message(), you will output text into this text file. Handy, isn't it?

We will be using Windows Powershell to watch that file, but first, let's feed the shortcut an important parameter. We will not hide the window for now. Give it "-output log.txt". "log.txt" could be anything, but we will use this for this tutorial.

log.txt should appear next to the .exe when you start the shortcut.
upload_2018-12-8_11-46-8.png

Now, each time we run the shortcut, GMS will keep stacking log data in the text file without removing it. We cannot delete the file in GMS, because GMS is already using it to output log data. This can be fixed if we create a PowerShell file (.ps1) that we'd use instead of a shortcut.

Now, SHIFT + RIGHT CLICK into the whitespace, and click on "open PowerShell window here".


Run the command "Get-Content log.txt -wait".
I will not get into the details of Powershell commands. Please refer to their documentation.
Now if you had show_debug_message calls, PowerShell will update live. Try to experiment with it.
To stop PowerShell from logging, simply press Ctrl + C.

You could have your PowerShell filter out specific commands.
"Get-Content log.txt -wait | where { $_ -match "PLAYER_UPDATE>" }"
Then in GMS, you'd use something like this
Code:
show_debug_message("PLAYER_UPDATE> " + string(newX) +" : " + string(newY))
show_debug_message("WORLD_UPDATE> " + string(newWX) +" : " + string(newWY))
It would filter out the commands by showing only the ones that contain "PLAYER_UPDATE>"

To demonstrate the potential out of this, I have created a PowerShell script that;
  • Clears the log before starting the server
  • Reads a settings text file and adds it to the parameters of the server
  • Kills the server when shutdown-server or exit is called.
  • An easy "watch" function so non-programmers can start the logging process.
  • Monitors console log
To stop PowerShell from logging, simply press Ctrl + C.
Code:
param($Work)

#Restart PowerShell with -noexit, the same script, and 1
if (!$Work) {
    powershell -noexit -file $MyInvocation.MyCommand.Path 1
    return
}

#Empty log data
Clear-Content log.txt

#Get server settings called "Server Settings.txt"
$serverSettings = Get-Content "Server Settings.txt"

#Start game as a dedicated server
$dedicatedServer = Start-Process MyGame.exe "-nowindow -output log.txt $serverSettings" -PassThru

#Kill server when exit or shutdown-server is called
Register-EngineEvent PowerShell.Exiting -SupportEvent –Action {
    $dedicatedServer | Stop-Process
}

#Aleternative of exit. This makes no difference
function shutdown-server {
    exit
}

#Shortcut of monitoring the console log
function watch {
    Get-Content log.txt -wait
}

#Monitor console logs
Get-Content log.txt -wait

Thank you for reading. If you have any suggestions or problems, feel free to comment.
 
Last edited:
If I'm understanding the use for this correctly: it is allowing a program to be activated in the background, and use it when running some functions? Your example is for networking.

One thing I have been curious about is whether two versions of gamemaker can be run on the same computer, and have them communicate information. I don't have the know how to figure if this tutorial could be used for that, so maybe you don't mind answering a noob question. Would some variation on the above make such a thing possible? or is that either the wrong application for it, or just not doable at all?
 

Bingdom

Googledom
If I'm understanding the use for this correctly: it is allowing a program to be activated in the background, and use it when running some functions? Your example is for networking.
There's no allowance for activation in the background. You can call draw_enable_drawevent(false) in the create event and it would still start windowless.
In this tutorial, we're launching GM with parameters, and providing behaviours/ assigning attributes to those parameters. Once the app has started, we can no longer send instructions.

One thing I have been curious about is whether two versions of game maker can be run on the same computer, and have them communicate information. I don't have the know how to figure if this tutorial could be used for that, so maybe you don't mind answering a noob question. Would some variation on the above make such a thing possible? or is that either the wrong application for it, or just not doable at all?
It is possible to have another instance of GM to send instructions to your headless application (via networking). You could even send your log to it.

Alternatively, you could write a CLI app (in C# for example) to communicate with your headless GM app.
 
@Bingdom
Thanks for the reply.

As I said - I'm not the most technically minded person, or a talented programmer. Whenever I've run into performance issues there's the question of my capability versus the limits of Gamemaker Studio. One of the latter is whether it uses a single core of the CPU, or if it can use more than one.

If it only uses one, and so is under utilizing the available power, then the idea of having two instances of the game running would be my noobs thought on how to get past that. One handles x amount of computing (a slave instance), while the other handles the rest as the master. The two communicate, and that data gets combined in the master.

If such a thing were possible, and beneficial to performance, then I'd imagined some networking would be required between the two. So it's interesting to find out if this tutorial offers any path into that. Hopefully it's not a stupid thought, and I appreciate you taking the time to answer :) (and if it is silly, then fair enough...)
 

FrostyCat

Redemption Seeker
@Bingdom
Thanks for the reply.

As I said - I'm not the most technically minded person, or a talented programmer. Whenever I've run into performance issues there's the question of my capability versus the limits of Gamemaker Studio. One of the latter is whether it uses a single core of the CPU, or if it can use more than one.

If it only uses one, and so is under utilizing the available power, then the idea of having two instances of the game running would be my noobs thought on how to get past that. One handles x amount of computing (a slave instance), while the other handles the rest as the master. The two communicate, and that data gets combined in the master.

If such a thing were possible, and beneficial to performance, then I'd imagined some networking would be required between the two. So it's interesting to find out if this tutorial offers any path into that. Hopefully it's not a stupid thought, and I appreciate you taking the time to answer :) (and if it is silly, then fair enough...)
Every version of GM thus far uses a single core. You can see this by running a project with a single infinite loop, where the most CPU it ever takes up is always 100 divided by the number of CPU cores on your system.

It is 100% possible to do a MapReduce-like architecture through named pipes or even networking over localhost. The performance gains relative to a single process depends on the computation and the overheads of redistributing the work, but if you can get it to run in parallel it's usually worth it.
 
@FrostyCat
Thanks for the input Having gone through several variations of my AI, and struggling to get good performance, maybe it is time to look at other methods beyond optimization. Since there could well be a ceiling that limits it, that won't change no matter how good I get it. The idea that other available power of the CPU is not being utilized hopefully offers some leeway.

This has been something at the back of my mind for a while, and whilst I may not have the understanding to do it (yet, at least) it is nice to know it can be done!
 
Top