Skip to content

Instantly share code, notes, and snippets.

@TrueBrain
Last active February 23, 2023 22:31
Show Gist options
  • Save TrueBrain/ebeb53986081b506a46e51d1484bfc3a to your computer and use it in GitHub Desktop.
Save TrueBrain/ebeb53986081b506a46e51d1484bfc3a to your computer and use it in GitHub Desktop.
Command batch in scripts

The GSBatchMode starts a mode, much like GSTestMode and GSExecMode. All commands executed in the scope of a batch are queued to be executed as soon as the batch closes.

If wanted, one can request a promise from the last command queued, so at a later moment the actual value can be retrieved. This is mostly useful for things like building of new stuff, but in many other cases users don't care about the result.

When the batch closes, OpenTTD sends all the commands to the command-queue, in order of creation. It is important to note that our current queue-system is limited, so possibly we need to allow those queues to either be a bit bigger, or to receive batches. The latter can be useful, as that means all multiplayer clients get a single packet with everything in there for the batch.

You can nest GSTestMode and GSExecMode inside a batch, which does exactly what you expect. Useful to note, that switching to GSExecMode means the old system kicks back in. This is needed to make sure calls to library that use GSTestMode/GSExecMode still function as expected, as they will use the return values immediately.

This approach keeps it very much in line with current script capabilities, while allowing for GSes to do mass-mutations in a much faster rate.

As example case, one could walk all the towns and modify their rating in a batch, and execute it, in one or two ticks (depending how much opcodes you need to do that). In the current implementation, you need as many ticks as there are towns to do the same.

Example script

Update rating of a company in all towns

{
  local batch = GSBatchMode();
  foreach (town, _ in GSTownList()) {
    GSTown::ChangeRating(town, GSCompany::COMPANY_FIRST, 10);
  }
}

Create a sign per town in a single go

local promises = [];
{
  local batch = GSBatchMode();
  foreach (town, _ in GSTownList()) {
    GSSign::BuildSign(0, "Look at me!"); // Returns the same value as if we were in GSTestMode
    promises.append(batch.GetLastPromise());
  }
}
foreach (promise in promises) {
  GSLog::info(promise.GetResult()); // Prints the ID of the sign created.
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment