• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

Demo Inter-process Communication (No Networking!) with Environment Variables in GMS2

S

Sam (Deleted User)

Guest
When you click each window it displays in a message box the value of an environment variable it reads from the other window's process. Basically, the child process sets an environment variable which is called "CURRENT" and the value of it is "CHILD". The parent process sets an environment variable called "CURRENT" and the value is "PARENT". You can use whatever environment variable names and values you want.

They both read that "CURRENT" environment variable value from each other to communicate. Doesn't work in MacOS in my testing, but does on Windows, and should on Linux as well. Please note on Windows it launches a command line app to get the environment variables of the external process. This makes it very slow and it is recommended to read environment variables from other processes sparingly to save on performance.
 
Last edited by a moderator:
S

Sam (Deleted User)

Guest
Something worth mentioning that I forgot to say in my initial post...

Be careful when using this project's approach - it is easy with this setup to accidentally create a fork bomb which is a type of virus.

I'll show you guys how to avoid that.
@YellowAfterlife explains what a fork bomb is at the link above - he made a similar example project.

Look in your project for this code in the create event:
GML:
globalvar game, proc, pid, ppid, opid,
oenv, senv, newlinesplit, equalssplit;
widget_get_owner(window_handle());
if (os_type == os_windows) {
  if (file_exists(working_directory + "data.win")) {
    game = working_directory + "data.win";
  } else {
    game = working_directory +
      string_replace_all(game_project_name, "_", " ") + ".win";
  }
} else if (os_type == os_macosx) {
  game = working_directory + "game.ios";
} else if (os_type == os_linux) {
  game = working_directory + "game.unx";
}
pid = pid_from_self(); ppid = ppid_from_self();
proc = 0; global.string_split_list = ds_list_create();
if (string_copy(cmd_from_pid(ppid), 0, 8) == "/bin/sh ") {
  ppid = ppid_from_pid(ppid);
}
if (path_from_pid(pid) != path_from_pid(ppid)) {
  window_set_position(window_get_x() - (window_get_width() / 2), window_get_y());
  environment_set_variable("CURRENT", "PARENT");
  process_execute_async(proc, "\"" + path_from_pid(pid) +
  "\" -game \"" + game + "\"");
} else {
  window_set_position(window_get_x() + (window_get_width() / 2), window_get_y());
  environment_set_variable("CURRENT", "CHILD");
}
More specifically, the last if/else check at the bottom:
GML:
if (path_from_pid(pid) != path_from_pid(ppid)) {
  window_set_position(window_get_x() - (window_get_width() / 2), window_get_y());
  environment_set_variable("CURRENT", "PARENT");
  process_execute_async(proc, "\"" + path_from_pid(pid) +
  "\" -game \"" + game + "\"");
} else {
  window_set_position(window_get_x() + (window_get_width() / 2), window_get_y());
  environment_set_variable("CURRENT", "CHILD");
}
That if/else check prevents the fork bomb, so never remove that.

Basically it checks if the parent process was not started by the same exact copy of the executable that started the current process.

If it wasn't started by the same exact executable file, then create another instance of the game, otherwise don't to prevent the fork bomb.

In other words, it prevents the game from making infinite instances of itself over and over until you have to hard reboot.

By design, if you run this project from the IDE, you cannot have underscores in your project name, use spaces instead.
 
Last edited by a moderator:
Top