ModAPI Diagnostic Tool#

Zero-overhead development tool for TNI game engine modding (0.10.11+).

Version4.5.9
AuthorCJFWeatherhead
Status🟒 Active Development
Game Versionstable
Last Updated2026-05-31

Download#

Installation Instructions
  1. Download the Mod Manager
  2. Find ModAPI Diagnostic Tool in the Available mods list
  3. Click Download to install automatically
  4. Configure parameters in the GUI

Manual Installation#

  1. Download the zip file above
  2. Extract the modapi-diagnostic/ folder to your mods directory:
    • Windows: %APPDATA%\Godot\app_userdata\Tower Networking Inc\mods\
    • Linux: ~/.local/share/godot/app_userdata/Tower Networking Inc/mods/
  3. Ensure luajit.elf is in the mods directory

About This Mod#

Zero-overhead development tool for TNI game engine modding (0.10.11+).

v4.5 β€” Panel removal#

  • Removed standalone CanvasLayer panel and on_tick polling (Callable bridge crash)
  • All functionality now via console commands only (press ~ to open)

v4.0 β€” Zero-overhead rewrite#

Architecture#

  • REMOVED on_player_input β€” eliminates per-frame pcall/GC memory pressure
  • All functionality via console commands and automatic lifecycle hooks
  • Lifecycle callback tracker shows exact init order and timing

All Lifecycle Callbacks#

  • on_mod_load, on_mods_loaded, on_engine_load
  • on_game_state_ready (auto-diagnostic on game init)
  • on_game_host_eod, on_mod_reload
  • on_device_spawned, on_user_spawned, on_location_spawned
  • on_day_start, on_day_end
  • on_world_ready, on_world_created, on_game_start, on_scenario_start

JSON Game State Export#

  • All 0.10.11 fields: PlayOptions, LogicControllerUser, FloorBuilders
  • New sections: player_messages, link_controller, acquired_techs
  • File write via ModFileSystem + log fallback
  • Auto-export on day end (configurable)

API Test Suite#

  • Tests get_locations(), get_merchants(), get_game_version()
  • Tests all control modules: networkctl, routectl, firewallctl, vlanctl, dhcpctl, filesysctl, packetctl
  • Tests GameWorld methods, Programs API, Merchants API
  • NETWORK_STORAGE (class 20) device support

Console Commands#

  • dump_world_overview() β€” quick world summary
  • inspect_locations() β€” list all floors
  • dump_all_world_devices() β€” list all devices
  • reinspect_all_users() β€” re-inspect tracked users
  • export_to_json() β€” export full game state
  • run_api_test_suite() β€” test all API endpoints
  • export_test_results_json() β€” export test results
  • show_lifecycle_log() β€” show callback order and timing

Use Cases#

  • Debug mod development issues
  • Export game state for external automation tools
  • Test and document API endpoint availability
  • Diagnose callback init order and timing
  • Build Terraform/OpenTofu providers

Full Documentation

ModAPI Diagnostic Tool v4.4#

Development tool for TNI game engine modding (0.10.11+).

FOR MOD DEVELOPERS AND EXTERNAL TOOL INTEGRATION

What’s New in v4.4#

  • Debug console activation β€” the game ships with DebugLayer.enabled = false. This mod sets it to true on startup, making the ~ key open the debug console
  • All commands in debug console β€” type command names directly (no parentheses)
  • Netsh terminal documented β€” 23 built-in terminal routines mapped (see Netsh Terminal Reference)

What was new in v4.3#

  • Debug console integration β€” all commands registered with DebugLayer.register_cmd()
  • Removed sandbox probes β€” findings documented below in Sandbox API Reference

What was new in v4.0#

  • Removed on_player_input entirely β€” eliminates the per-frame pcall/GC memory pressure that caused the memory leak in v3.x
  • Added on_game_state_ready β€” the correct entrypoint for post-init diagnostics (world guaranteed valid)
  • Added all missing callbacks: on_mod_load, on_mods_loaded, on_game_host_eod, on_location_spawned
  • Lifecycle tracker β€” records exact callback order and timing for debugging init issues
  • Expanded API coverage for game version 0.10.11: new PlayOptions fields, LogicControllerUser fields, all control modules, NETWORK_STORAGE device class, GameWorld methods
  • New API getters tested: get_locations(), get_merchants(), get_game_version(), has_mods_reloaded()
  • File write support β€” JSON export tries ModFileSystem before falling back to log output

Usage#

  1. Place in mods/modapi-diagnostic/
  2. Load the game β€” on_game_state_ready runs automatic diagnostics
  3. Use console commands for interactive features
  4. Check [DIAG] prefixed messages in the game console

Console Commands#

Open the debug console with ~ and type the command name (no parentheses needed):

dump_world_overview       -- Quick world summary (day, cash, counts)
inspect_locations         -- List all floors with user counts
dump_all_world_devices    -- List all devices with class/condition
reinspect_all_users       -- Re-inspect tracked users' network configs
export_to_json            -- Export full game state to JSON
run_api_test_suite        -- Test all API endpoints
export_test_results_json  -- Export test results as JSON
show_lifecycle_log        -- Show callback order and timing

Commands are also available as globals() for direct Lua calls.

Auto-triggers#

TriggerConfig KeyDefault
Diagnostics on game readyauto_diag_on_readytrue
JSON export on day endauto_export_on_day_endfalse

Lifecycle Callbacks#

All 16 known callbacks are registered. Use show_lifecycle_log() to see the exact order they fired:

[DIAG]    1. [0.0012s] on_mod_load -- mod binary/script loaded
[DIAG]    2. [0.0015s] on_mods_loaded -- all mods finished loading
[DIAG]    3. [0.0340s] on_engine_load
[DIAG]    4. [0.1200s] on_game_state_ready -- game fully initialized
[DIAG]    5. [0.1500s] on_location_spawned -- Floor 1: Lobby
[DIAG]    6. [0.1800s] on_device_spawned -- Switch-8 (NETWORK_SWITCH)
...

Complete Callback List#

CallbackWhenv3.x?
on_mod_load()Mod script loadedNEW
on_mods_loaded()All mods loadedNEW
on_engine_load()Engine startupYes
on_game_state_ready()World fully initializedNEW
on_game_host_eod()End-of-day host processingNEW
on_mod_reload()F11 mod reloadYes
on_device_spawned(device)Device placedYes
on_user_spawned(user)Customer appearsYes
on_location_spawned(location)Floor spawnedNEW
on_day_start()Day beginsYes
on_day_end()Day endsYes
on_tick(delta)Every frame (empty)Yes
on_world_ready(world)World readyYes
on_world_created(world)World createdYes
on_game_start(world)Game session startsYes
on_scenario_start(world)Scenario beginsYes

JSON Export#

export_to_json() outputs a comprehensive game state snapshot. Tries writing to diagnostic-export.json via ModFileSystem, falls back to log output between === JSON GAME STATE START === / === JSON GAME STATE END === markers.

Data Sections#

SectionConfig KeyContent
WorldalwaysDay, cash, scenario, difficulty
Play Optionsjson_include_play_optionsAll PlayOptions fields (expanded in 0.10.11)
Devicesjson_include_devicesFull device tree with logic/power controllers
Usersjson_include_usersLogicControllerUser fields, visitor stats
Locationsjson_include_locationsFloors with user counts
Financesjson_include_financesTransactions, payment breakdown
Networkjson_include_networkDNS lookup, network address tables
Statisticsjson_include_statisticsGame statistics
Loansjson_include_loansPlayer loans
Hostingsjson_include_hostingsPlayer hosting contracts
Merchantsjson_include_merchantsMerchants with full listing data
Messagesjson_include_messagesPlayer messages
Floor Buildersjson_include_floor_buildersFloor build config
Link Controllerjson_include_link_controllerNetwork links
Acquired Techsjson_include_acquired_techsUnlocked technologies

API Test Suite#

run_api_test_suite() tests all documented API endpoints:

  • ModApiV1: sanity, get_game_world, get_devices, get_users, get_locations, get_merchants, get_game_version, has_mods_reloaded
  • Mod Global: mod_dir, mod_type, manifest, filesystem, config
  • GameWorld: 17 properties + 8 methods (send_player_message, put_dns_entry, lookup_domain, etc.)
  • DeviceUnit: 10 properties + methods
  • User/LogicControllerUser: Base + extended fields (payment_calculation_method, csr, vsr, etc.)
  • Locations: display_name, floor_num, is_datacenter, surge/outage immunity, etc.
  • Network/Control Modules: networkctl, routectl, firewallctl, vlanctl, dhcpctl, filesysctl, packetctl
  • Merchants: Properties + restock/submit_order methods
  • Programs: release_name, cpu_load, install_size, etc.
  • FileSystem: get_files_at, get_directories_at, open/read, mod_path_to_real
  • GameWorld Methods: lookup_domain, get_loc_index (safe read-only calls)

Why No Keyboard Shortcuts?#

v3.x used on_player_input for Shift+R/D/J/Q shortcuts. This callback fires on every input event including mouse movement, and the C++ bridge crashes (bad_cast: Variant is not an Object for Variant of type 0 (Nil)) when pushing InputEvent userdata to the Lua stack. This happens before any Lua code executes, making it unfixable from Lua. Even without the crash, the per-frame pcall/GC overhead caused OOM in the ~1800-byte Lua arena.

v4.4 enables the game’s built-in debug console (DebugLayer) and registers commands with register_cmd(). Commands only run when explicitly invoked β€” zero per-frame overhead.

Sandbox API Reference#

Tested on game version 0.10.15. These findings document what the RISC-V mod sandbox permits.

BLOCKED β€” Will Not Work#

APIResultNotes
Engine.get_singleton(name)BANNED“Banned property accessed: get_singleton” β€” applies to ALL singletons
on_player_input(event)CRASHC++ bad_cast in push_gd_object_metatable before Lua runs
Direct Input accessImpossibleRequires Engine.get_singleton("Input") which is banned
Direct InputMap accessImpossibleSame reason
Key polling in on_tickImpossibleNo way to obtain Input singleton

WORKS β€” Safe to Use#

APIHow to AccessNotes
DebugLayerworld.get_node("/root/DebugLayer")Game’s debug console overlay
DebugLayer.enabled = trueProperty setRequired β€” disabled by default, enables ~ key
DebugLayer.visible = trueProperty setRequired β€” hidden by default
DebugLayer.register_cmd(name, func)On the node aboveRegisters commands in ~ console
DebugLayer.print_console(msg)On the node aboveWrites to debug console display
Engine.has_singleton(name)Direct callReturns true/false, not banned
create_node("InputEventKey")Direct callCan create and configure input events
InputEventKey properties.keycode, .pressed, .shift_pressedAll settable
MobileOSLayerworld.mobile_os_cvlGame state layer (16 children)
MobileOSLayer.at_netshell_screenOn aboveBoolean β€” is netsh terminal open?
MobileOSLayer.safe_to_use_keyboardOn aboveBoolean β€” can type?
MobileOSLayer.find_child("*Shell*")Recursive searchFinds NetShell (VBoxContainer)
NetShell.terminal_routinesArray property23 built-in routines (read-only)
NetShell.has_terminal_routine(name)Method callCheck if routine exists
NetShell.exec_command(cmdstr, stdout)Method callExecute existing terminal commands
world.get_node(path)Scene tree traversalArbitrary scene tree access works
ModApiV1.get_game_world()Direct callGame world reference
ModApiV1.get_base_ui()Direct callUI reference for notifications

Command Registration Pattern#

The recommended pattern for exposing mod commands:

-- 1. Define as global (fallback for direct Lua calls)
function my_command()
    print("Hello from my mod!")
end

-- 2. Enable debug console and register in on_game_state_ready
function on_game_state_ready()
    local world = ModApiV1.get_game_world()
    if not world then return end

    local ok, dbg = pcall(function()
        return world.get_node("/root/DebugLayer")
    end)
    if not ok or not dbg then
        print("[my-mod] DebugLayer not found")
        return
    end

    -- Enable the debug console (disabled by default)
    pcall(function() dbg.enabled = true end)
    pcall(function() dbg.visible = true end)

    pcall(function() dbg.register_cmd("my_command", my_command) end)
end

Players can then open the debug console with ~ and type my_command.

Netsh Terminal Reference#

The in-game “netsh” terminal (the pseudo gameplay terminal on the player’s monitor) is separate from the debug console. It is a NetShell (VBoxContainer) found via world.mobile_os_cvl.find_child("*Shell*").

Built-in Terminal Routines (23)#

#NameDescription
0manManual / help
1aliasCommand aliases
2quitExit terminal
3clearClear screen
4lstdbgList debuggers
5godGod mode
6scanNetwork scan
7tracePacket trace
8watchWatch mode
9programProgram management
10alwaysAlways-on rules
11pingPing host
12routeRouting table
13pcapPacket capture
14netNetwork config
15dnsDNS lookup
16firewallFirewall rules
17dhcpDHCP config
18echoEcho text
19dstatDevice status
20vlanVLAN config
21stpSpanning tree
22middleboxMiddlebox config

Netsh Injection β€” Not Currently Possible#

Custom commands cannot be injected into the netsh terminal because:

  • TerminalRoutine subclasses are not registered in create_node() β€” they cannot be instantiated from Lua
  • The terminal_routines array can be read but appending requires a valid TerminalRoutine instance
  • AliasRoutine.alias_expand() only does stringβ†’string substitution between existing commands
  • The netsh reports unknown routine for any unregistered command name

Use the debug console (~) for mod commands instead.

Device Hardware Classes (0.10.11)#

IDName
0DEFAULT
1NETWORK_SWITCH
2NETWORK_ROUTER
3NETWORK_TAP
4NETWORK_FIREWALL
5MEDIA_LINE_SIMPLEX
6MEDIA_LINE_DUPLEX
7COMPUTE_SERVER
8DISPLAY_MONITOR
9DEBUGGER
10LOAD_TESTER
11POWER_EXPANSION
12DECENTRO_RIGS
13SURGE_PROTECTOR
14UPS
15INERT
16CCTV
17PHONE
18PRINTER
19NETWORK_LOAD_BALANCER
20NETWORK_STORAGE

Additional Notes

This is a developer tool for mod creators and external tool integrations. No gameplay impact. Ideal for:

  • Mod developers learning the API
  • Building REST API bridges
  • Terraform/OpenTofu provider development
  • Game state analysis and automation

Technical Details
FieldValue
Mod IDmodapi-diagnostic
Creation Date2026-01-20
Last Updated2026-05-31
Game Versionstable
DependenciesNone
Websitehttps://github.com/CJFWeatherhead/TNI-Mods/tree/main/mods/modapi-diagnostic

Release URLs:


Back to All Mods