Developer diary

Dev Diary #8: Mod support in a strategy game engine

Mod support in a strategy game engine: content files, script rules and WebAssembly systems; sandboxed code, mod sets and a summary of what can be reached today.

Contents

In short: In MKA Engine the game itself is a mod; the game and mods connect to the engine through the same door. A mod author can work on three levels: write content with text files, write rules with scripts, and write new systems with WebAssembly. In this diary we describe what can be reached today, what is still in progress, and why mods must be identical in multiplayer.

For people who play strategy games, a mod usually means a new event, a new country, a new unit, or a setting that changes a rule of the game. For a game engine, mod support is a question: which part of the engine can someone from outside the game touch, and through which route? In this diary we give today's answer to that question in broad strokes. The details, meaning how each access works, are the subject of later diaries.

The game is a mod too

One of the most basic design decisions of MKA Engine is this: the game itself is a mod. The engine knows nothing specific to a game; the game brings the tables, the systems and the rules. The route the game uses to connect to the engine is the same route a mod uses. This has two benefits. First, the power in the modder's hands does not fall behind the power of the person who wrote the game. Second, the mod route is tested with our own test game; so it is not a route that exists only on paper.

Three levels

Think of a workshop. A scribe arranges the cards and decrees on the map; a craftsman fits a new gear into the mechanism under the map. Mods also do two different kinds of work, and there is a rule-writing job in between:

LevelWhat is writtenWhat it touches
ContentText files (.bsm)Events, decisions, modifiers, goods, technologies and the other content types of the game
RulesCondition, effect and formula scriptsRules like "is this country rich?", "collect tax", "how much is this region's income?"
CodeA WebAssembly moduleNew tables and fields, new systems, commands, hooks, timers
The three levels of a mod

Content. The easiest level. A mod puts files into the content folders of the game. A later mod can change the record of an earlier one: it can rewrite it fully, change a single field, or delete it. Mods are processed in load order, and that order is the same on every computer. If two mods change the same record, the engine reports the conflict; the mod that comes later wins. Errors are reported with file name, line and column; a broken file does not crash the engine.

Rules. A condition tests whether something is true, an effect changes the state of the game, a formula produces a number. We described this language in Diary #5. A mod author can write new rules in the same language as the rules of the game itself.

Code. The most powerful level. A mod that carries code comes as a WebAssembly module (a portable compiled code format that is also used in browsers). This module can register new tables and fields with the engine, add systems that run every day, define command types and hooks, and set timers. It can read and write large columns in a single call. It takes random numbers from the engine's own source too; so the result is the same on every machine.

Why do mods with code run safely?

Allowing a mod to run its own code can also mean allowing it to freeze the game with a badly written loop. That is why a WebAssembly module runs inside a glass case: a sandbox. The rules of the case are these:

  • Every call has an instruction limit. The default limit is 10,000,000 instructions per call; a mod that exceeds it is shut down. Because instructions are counted, the limit is the same on every machine.
  • Memory is limited too.
  • A wrong id, a wrong value or a write to a field it may not write stops the run. The engine reports the error with the name of the mod and its system; the game does not crash.
  • The code has no clock, no file and no network; it gets time and randomness only from the engine.

Why must mods be the same?

In a multiplayer strategy game every computer runs the same simulation on its own; only commands travel over the network. So if two players have different mod sets, two different worlds appear after a while (Diary #2). The engine recognizes a mod set by a numeric digest computed from the content files and the compiled modules; since the digest is computed with integer math, it is the same on every platform. The save file also records which mod set the game was played with. So when loading a save, the answer to "which mods was this game played with?" is ready.

What can be reached today?

Roughly like this:

  • Content and rule language: events, decisions, modifiers, actions and the content types the game defines.
  • On the code side: mechanisms such as the map, fronts and war, the transport network, sea control and the AI. Also modifiers, events, timers, script variables and notifications (we described these in Diary #6).
  • New data: mods can add their own tables and fields; these also enter the engine's own storage layout (Diary #3).

Some things are still in progress. The market, production, population, family and hierarchy mechanisms that already work in the engine are not yet opened to mods that carry code; sight, fog of war and exploration are next in line. These openings are part of the work we have planned, and we will share them in new diaries as they progress.

Limits of this diary

  • This is a summary of access, not a full modding guide. We will explain each mechanism and how it is used in later diaries.
  • What is described is the state of the engine today. When the things in progress are finished, the picture will change.
  • There are no measurements; this diary only describes the structure and the limits.

Frequently asked questions

How does mod support work in a game engine?

A mod connects to the engine through the same door as the game. In MKA Engine a mod can bring content with text files, rules with scripts and new systems with a WebAssembly module.

Can WebAssembly mods crash the game?

No. A mod with code runs in an isolated space with instruction and memory limits. A mod that exceeds a limit or misbehaves is stopped, and the engine reports the error with the name of the mod.

What happens in multiplayer if the mod sets differ?

Because every computer runs the same simulation, the mod set must be the same. The engine recognizes the mod set with a digest number and writes it into the save file.

What happens if two mods change the same thing?

Mods load in a deterministic order. The engine reports the conflict, and the mod that loads later wins.

Sources

More on this will come

We plan much more work on mod support and game state. We will share it in new diaries.

For questions or ideas, write to us from the contact page. For an overview of the engine see the MKA Engine page, and for all diaries the Developer Diaries list.

Sources and related docs

You may also like

  • How is a strategy game's world map made?

    For MKA Engine we built a 27,357-location world map of 1337 from real data: how terrain, rivers, straits, population and location borders were made.

  • The road to a game engine

    How we started MKA Engine: reading four games, treating determinism as law, moving phase by phase with measurements, and where we are now.