It is a clean, minimal, purple-themed graphic social media banner, serving as the official header for the "Metruvia Knowledge Base" (Metruvia and Metruvia Knowledge Base) Transport Fever mod brand on Mod.io. The banner is set against a solid, deep-violet-purple background with a rich saturation. In the upper-center, a white, simplified, and symmetrical game controller icon is positioned. Directly below this icon, in prominent, white, bold, sans-serif text, is the text "Metruvia Knowledge Base". Below that, in smaller, regular white text, is the tagline "Built by Players. Powered by Knowledge." Symmetrically framing the central text and icon, on the far left and far right sides, are two large, detailed, white game controllers, depicted from a top-down aerial perspective with colorful button inputs (yellow, blue, pink, and green) and analog sticks. Scattered across the remaining purple space are small, white line-art icons that reinforce the gaming and puzzle themes: several puzzle piece outlines, small pixel-art heart outlines, simple bullseye targets, and a single solid white circle (a "knowledge" point). The layout is balanced, professional, and easily recognizable as part of a gaming community and documentation resource. The art style is flat vector graphic. A small, stylized white compass needle icon, derived from the Metruvia brand mark, is visible over the left analog stick of the controller on the right, providing a cohesive brand identity. The text is sharp and legible.

Metruvia Content Creator Series: Scripting Border

Welcome to the Metruvia Content Creator Scripting Border Guide for Transport Fever 2. You have successfully navigated file hygiene, mastered the Mod.io cloud API, optimized your polygons for unified memory architectures, and scrubbed your textures of copyright liabilities. Now, you face the most invisible and unforgiving hurdle of cross-platform modding: Code Security.

In the localized, PC-only ecosystem of the Steam Workshop, the Transport Fever 2 engine allows for remarkable flexibility. PC modders have historically used Lua to completely overhaul UI systems, inject custom shaders, and even read external files from a user’s hard drive.

On PlayStation 5 and Xbox Series X|S, this level of access is a critical security vulnerability.

When you check the “Console Compatible” box on Mod.io, your code is subjected to a strict “Sandbox.” Sony and Microsoft do not permit arbitrary code execution on their closed hardware. If your script attempts to call a restricted OS-level function, or if it introduces a custom UI element that a gamepad controller cannot navigate, your mod will be instantly rejected.

This masterclass will tear down the Transport Fever 2 Lua Sandbox. We will define the exact blacklist of prohibited functions, explore the strict limitations of the UI API, and provide you with the architectural knowledge needed to write safe, console-compliant logic that enhances the game without violating hardware security protocols.

1. The Architecture of the Lua Sandbox

To understand why your code might be rejected, you must understand how Transport Fever 2 handles scripts. The game utilizes Lua 5.3 as its embedded scripting language. However, the environment your mod executes within is not standard Lua.

When a console player loads your mod, the game engine wraps your code in a Sandbox—a heavily restricted virtual environment that sits between your script and the console’s operating system.

1.1 The Principle of Least Privilege

The sandbox operates on the “Principle of Least Privilege.” Your mod is only granted access to the specific internal game APIs necessary to function (game.config, api.engine, api.res). It is entirely blinded to the outside world. It cannot know what operating system it is running on, it cannot see the player’s network connection, and it cannot access the local file system beyond its own designated Virtual File System (VFS) boundaries.

1.2 The Time Complexity Trap

Consoles have strict watchdog timers to prevent hard lockups. If your Lua script contains an inefficient, nested loop that takes too long to execute, the console OS will assume the game has frozen and forcefully terminate the application.

When parsing massive arrays (like checking every single vehicle on a map), you must be aware of your algorithmic time complexity, aiming for $O(n)$ or better. A script running an $O(n^2)$ operation during the runFn initialization will cause a noticeable hang on a console CPU, flagging your mod for manual performance rejection.

2. The Blacklist: Triggers for Immediate Security Rejection

The Urban Games API proactively strips access to standard Lua libraries that pose security threats. Attempting to call any of the following functions will result in a fatal nil value error, an engine crash, and a permanent rejection from the Mod.io console pool.

2.1 The os.* Library Ban

The os library interacts directly with the operating system. On a PC, this might be harmlessly used to get the current system time. On a console, it is a vector for system-level exploitation.

Restricted: os.execute, os.remove, os.rename, os.exit, os.getenv.

The Consequence: Attempting to use os.execute to run a batch script or external command is categorized as a malicious payload attempt.

2.2 The io.* Library Restriction

While you are allowed to read configuration files packaged within your mod’s folder structure using the Transport Fever 2 specific file handlers, the standard Lua Input/Output library is heavily restricted.

Restricted: io.open, io.popen, io.tmpfile.

The Consequence: You cannot write dynamic log files to a console’s hard drive, nor can you read external configuration data outside of your specific mod directory.

2.3 package.loadlib and External Binaries

PC modders sometimes use .dll (Dynamic Link Library) files on Windows to extend Lua’s capabilities.

Restricted: package.loadlib and require (when targeting external C/C++ libraries).

The Consequence: Consoles do not run Windows .dll files. Any attempt to load external binary code is an immediate violation of Sony and Microsoft developer agreements.

2.4 The debug.* Library

The debug library allows scripts to inspect the memory stack and alter the behavior of other running scripts.

Restricted: debug.sethook, debug.getupvalue, debug.setmetatable.

The Consequence: Utilizing the debug library breaks the sandboxing between different mods, allowing one mod to hijack or crash another.

3. The UI API: The Gamepad Problem

The most common non-malicious reason scripts are rejected for console distribution is the mishandling of the UI API.

Transport Fever 2 features a robust UI modification system (gui.*) that allows PC modders to create custom windows, buttons, and readouts. However, PC players use a mouse, which has free-roaming pixel accuracy. Console players use a controller, which relies on predefined UI navigation meshes (UI Nav-Meshes).

3.1 The “Unreachable Button”

If you use Lua to inject a custom “Auto-Schedule” button into the vehicle management window, a PC player simply clicks it. A console player presses the D-Pad to move their selection highlight around the screen.

Because your custom button is injected dynamically via a mod, the console’s UI Nav-Mesh does not know it exists. The controller highlight will skip right over it. You have effectively placed a feature on the screen that the console player physically cannot interact with.

3.2 The Strict UI Prohibition

Because Urban Games cannot dynamically generate controller support for arbitrary UI elements created by third-party code, all custom UI alterations are prohibited for Console Compatible mods.

Do not inject new windows.

Do not add custom buttons to vanilla menus.

Do not intercept mouse-click events.

If your mod relies on a custom UI panel to function (e.g., a complex timetable manager), it is inherently PC-only. You must strip the custom UI and rely purely on the vanilla game logic, or accept that the mod cannot be published to the console Mod.io network.

4. Code Hygiene: The mod.lua Lifecycle

Safe scripting requires understanding exactly when your code is executed by the engine. The mod.lua file uses specific callback functions to manage the lifecycle of your logic. Placing code in the wrong callback will cause memory leaks or save-game corruption.

4.1 The Global Scope (Initialization)

Code written outside of any function in your mod.lua is executed the moment the game builds the mod list in the main menu.

Rule: Never place heavy mathematical operations or table generations in the global scope. It bloats the game’s startup memory before the player has even loaded a save file.

4.2 runFn(settings, modParams)

This is the primary execution block. It runs exactly once when a save game is loaded or a new map is generated.

Best Use: Use this block to modify global game configuration tables (e.g., altering vanilla bridge costs, registering new cargo types via api.res).

Warning: Changes made here are baked into the save file.

4.3 postRunFn(settings, modParams)

This block executes after all other mods have completed their runFn.

Best Use: This is critical for compatibility. If you are writing a script that modifies all vehicles in the game (e.g., doubling the top speed of every train), you must place it in postRunFn. If you place it in runFn, your script will only affect vanilla trains and will miss any trains added by mods loaded after yours in the load order.

5. Advanced Mechanics: Safe State Alteration

If you cannot use external libraries and you cannot alter the UI, what can you do? The key to console-compliant scripting is utilizing the api.engine to manipulate the game state invisibly.

5.1 Modifier Scripts

You can safely iterate through the game’s resource repository to apply bulk changes without risking stability.

— Console-Safe Example: Modifying all vehicle lifespans
function data()
return {
info = {
minorVersion = 1,
severityAdd = “NONE”,
severityRemove = “WARNING”,
name = “Extended Vehicle Lifespan”,
},
runFn = function (settings, modParams)
local addModifier = function(fileName, data)
if data.metadata and data.metadata.maintenance then
data.metadata.maintenance.lifespan = data.metadata.maintenance.lifespan * 2
end
return data
end
— Safely hooking into the engine API
api.res.modelRep.addModifier(“addModifier”, addModifier)
end
}
end

This script passes console certification perfectly. It uses only internal APIs, does not touch the OS, does not require custom UI, and executes predictably.

5.2 The severityRemove = "CRITICAL" Requirement

As discussed in previous articles, the severityRemove parameter is the most important metadata flag in your mod.lua.

If your script introduces new commodities, new town generation logic, or fundamentally alters the mathematical structure of the economy, you are altering the deep architecture of the save file.

If a console player deletes your mod, the engine will attempt to find the custom cargo type your script created. When it returns a nil value, the console will instantly hard-crash to the dashboard.

If your script alters the economy or adds custom industries, you must set severityRemove = "CRITICAL". This locks the mod to the player’s save file, preventing them from accidentally destroying a 100-hour playthrough. Failure to use this flag for heavy scripting mods is a guaranteed QA rejection.

6. Summary: The Pre-Publish Code Audit

Before you submit a script-heavy mod to the Mod.io API, run your codebase through this final sandbox audit:

The Library Check: Search your entire repository for os., io., debug., and require. If any exist, your mod will fail.

The UI Check: Does your mod alter the vanilla UI or require the player to click a custom button? If yes, it is PC-only. Strip it for the console release.

The Loop Check: Are you running deep, nested loops over large datasets during initialization? Refactor for efficiency to prevent console watchdog timeouts.

The Execution Order: Are your global game modifications placed securely inside postRunFn to ensure compatibility with other mods?

The Save Integrity Check: Does your script alter the economy, add cargo, or change town generation? Set severityRemove = "CRITICAL".

By respecting the Sandbox, you ensure that your modifications run seamlessly, securely, and stably across the unified Mod.io ecosystem, bridging the gap between PC complexity and console reliability.