Modding: Difference between revisions
More actions
Bonsaibauer (talk | contribs) Create en-GB source page for translation |
Bonsaibauer (talk | contribs) Marked this version for translation |
||
| Line 15: | Line 15: | ||
<translate> | <translate> | ||
<!--T:1--> | |||
Read the main-menu state and selected local character name through the Lua runtime. Both queries use the same native data as the Modloader and require no world access. | Read the main-menu state and selected local character name through the Lua runtime. Both queries use the same native data as the Modloader and require no world access. | ||
== Prerequisites == | == Prerequisites == <!--T:2--> | ||
<!--T:3--> | |||
Enable the mod and declare the <code>runtime</code> capability in <code>mod.json</code>: | Enable the mod and declare the <code>runtime</code> capability in <code>mod.json</code>: | ||
<!--T:4--> | |||
<pre> | <pre> | ||
{ | { | ||
| Line 27: | Line 30: | ||
</pre> | </pre> | ||
<!--T:5--> | |||
For these client queries, set <code>targets</code> to <code>["client"]</code> in <code>extended.mod.json</code>. Call the functions from active runtime callbacks such as <code>on_load</code> and <code>on_update</code>. <code>runtime.phase == "ingame"</code> describes the started mod runtime and does not confirm entry into a world. Neither query needs an execution profile. Other world operations retain their own requirements. | For these client queries, set <code>targets</code> to <code>["client"]</code> in <code>extended.mod.json</code>. Call the functions from active runtime callbacks such as <code>on_load</code> and <code>on_update</code>. <code>runtime.phase == "ingame"</code> describes the started mod runtime and does not confirm entry into a world. Neither query needs an execution profile. Other world operations retain their own requirements. | ||
== Detect the main menu == | == Detect the main menu == <!--T:6--> | ||
<!--T:7--> | |||
<pre> | <pre> | ||
local in_menu, reason = runtime.is_main_menu() | local in_menu, reason = runtime.is_main_menu() | ||
</pre> | </pre> | ||
<!--T:8--> | |||
{| class="wikitable" | {| class="wikitable" | ||
! Return value !! Meaning | ! Return value !! Meaning | ||
| Line 45: | Line 51: | ||
|} | |} | ||
<!--T:9--> | |||
Check <code>in_menu == true</code> or <code>in_menu == false</code> explicitly. <code>nil</code> is not a confirmed state. <code>false</code> alone does not confirm a readable world either. Check the operation you need separately, such as <code>runtime.has("runtime.ecs.read")</code>. | Check <code>in_menu == true</code> or <code>in_menu == false</code> explicitly. <code>nil</code> is not a confirmed state. <code>false</code> alone does not confirm a readable world either. Check the operation you need separately, such as <code>runtime.has("runtime.ecs.read")</code>. | ||
== Read the character name == | == Read the character name == <!--T:10--> | ||
<!--T:11--> | |||
<pre> | <pre> | ||
local name, reason = runtime.player.name() | local name, reason = runtime.player.name() | ||
| Line 54: | Line 62: | ||
</pre> | </pre> | ||
<!--T:12--> | |||
<code>name, nil</code> returns the character name selected in the local main menu as a UTF-8 string. Unicode characters, as in <code>Ikiju 育樹</code>, are preserved. <code>nil, reason</code> means that no name is available yet, or access is unavailable or not allowed. | <code>name, nil</code> returns the character name selected in the local main menu as a UTF-8 string. Unicode characters, as in <code>Ikiju 育樹</code>, are preserved. <code>nil, reason</code> means that no name is available yet, or access is unavailable or not allowed. | ||
<!--T:13--> | |||
The mod chooses its own fallback name. The API inserts no default and does not use the Modloader's manual name selection. The value identifies no remote player and is neither a SteamID nor a Steam display name. A Dedicated Server has no local client character name. | The mod chooses its own fallback name. The API inserts no default and does not use the Modloader's manual name selection. The value identifies no remote player and is neither a SteamID nor a Steam display name. A Dedicated Server has no local client character name. | ||
== Shared cache == | == Shared cache == <!--T:14--> | ||
<!--T:15--> | |||
Lua and the Modloader read the same native cache. The existing runtime tick refreshes the menu state. The existing menu integration captures the name on the first available selection and again when selection or name metadata changes. Lua queries start no separate discovery and read no logs. | Lua and the Modloader read the same native cache. The existing runtime tick refreshes the menu state. The existing menu integration captures the name on the first available selection and again when selection or name metadata changes. Lua queries start no separate discovery and read no logs. | ||
<!--T:16--> | |||
The last successfully captured name remains cached after joining a world. A cached name therefore does not confirm that the menu is open. <code>runtime.has("runtime.is_main_menu")</code> and <code>runtime.has("runtime.player.name")</code> report each query's availability. <code>runtime.status(...)</code> also supplies a reason. | The last successfully captured name remains cached after joining a world. A cached name therefore does not confirm that the menu is open. <code>runtime.has("runtime.is_main_menu")</code> and <code>runtime.has("runtime.player.name")</code> report each query's availability. <code>runtime.status(...)</code> also supplies a reason. | ||
== Example for <code>src/mod.lua</code> == | == Example for <code>src/mod.lua</code> == <!--T:17--> | ||
<!--T:18--> | |||
This example reads the cache on load and every 500 ms afterwards. It chooses a fallback name and logs only changes: | This example reads the cache on load and every 500 ms afterwards. It chooses a fallback name and logs only changes: | ||
<!--T:19--> | |||
<pre> | <pre> | ||
runtime.require("runtime.lifecycle") | runtime.require("runtime.lifecycle") | ||
<!--T:20--> | |||
local previous_message = nil | local previous_message = nil | ||
<!--T:21--> | |||
local function refresh() | local function refresh() | ||
local in_menu = runtime.is_main_menu() | local in_menu = runtime.is_main_menu() | ||
| Line 83: | Line 99: | ||
end | end | ||
local message = state .. ": " .. (name or "Flameborn") | <!--T:22--> | ||
local message = state .. ": " .. (name or "Flameborn") | |||
if message ~= previous_message then | if message ~= previous_message then | ||
previous_message = message | previous_message = message | ||
| Line 90: | Line 107: | ||
end | end | ||
<!--T:23--> | |||
return { | return { | ||
on_load = refresh, | on_load = refresh, | ||
Latest revision as of 21:38, 6 November 2026
Read the main-menu state and selected local character name through the Lua runtime. Both queries use the same native data as the Modloader and require no world access.
Prerequisites
Enable the mod and declare the runtime capability in mod.json:
{
"capabilities": ["runtime"]
}
For these client queries, set targets to ["client"] in extended.mod.json. Call the functions from active runtime callbacks such as on_load and on_update. runtime.phase == "ingame" describes the started mod runtime and does not confirm entry into a world. Neither query needs an execution profile. Other world operations retain their own requirements.
Detect the main menu
local in_menu, reason = runtime.is_main_menu()
| Return value | Meaning |
|---|---|
true, nil |
The main menu, including character, world and server selection, has been confirmed. |
false, nil |
A different original game state has been validated. |
nil, reason |
The state is unknown, changing, or the query is unavailable. |
Check in_menu == true or in_menu == false explicitly. nil is not a confirmed state. false alone does not confirm a readable world either. Check the operation you need separately, such as runtime.has("runtime.ecs.read").
Read the character name
local name, reason = runtime.player.name() local display_name = name or "Flameborn"
name, nil returns the character name selected in the local main menu as a UTF-8 string. Unicode characters, as in Ikiju 育樹, are preserved. nil, reason means that no name is available yet, or access is unavailable or not allowed.
The mod chooses its own fallback name. The API inserts no default and does not use the Modloader's manual name selection. The value identifies no remote player and is neither a SteamID nor a Steam display name. A Dedicated Server has no local client character name.
Shared cache
Lua and the Modloader read the same native cache. The existing runtime tick refreshes the menu state. The existing menu integration captures the name on the first available selection and again when selection or name metadata changes. Lua queries start no separate discovery and read no logs.
The last successfully captured name remains cached after joining a world. A cached name therefore does not confirm that the menu is open. runtime.has("runtime.is_main_menu") and runtime.has("runtime.player.name") report each query's availability. runtime.status(...) also supplies a reason.
Example for src/mod.lua
This example reads the cache on load and every 500 ms afterwards. It chooses a fallback name and logs only changes:
runtime.require("runtime.lifecycle")
local previous_message = nil
local function refresh()
local in_menu = runtime.is_main_menu()
local name = runtime.player.name()
local state = "unknown"
if in_menu == true then
state = "menu"
elseif in_menu == false then
state = "other"
end
local message = state .. ": " .. (name or "Flameborn")
if message ~= previous_message then
previous_message = message
shroudforge.log.info(message)
end
end
return {
on_load = refresh,
on_update = function()
refresh()
end,
update_interval_ms = 500,
}