<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-GB">
	<id>https://wiki.shroudforge.net/index.php?action=history&amp;feed=atom&amp;title=Modding%2Fzh</id>
	<title>Modding/zh - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.shroudforge.net/index.php?action=history&amp;feed=atom&amp;title=Modding%2Fzh"/>
	<link rel="alternate" type="text/html" href="https://wiki.shroudforge.net/index.php?title=Modding/zh&amp;action=history"/>
	<updated>2026-11-07T23:13:43Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.46.2</generator>
	<entry>
		<id>https://wiki.shroudforge.net/index.php?title=Modding/zh&amp;diff=2633&amp;oldid=prev</id>
		<title>Bonsaibauer: Importing a new version from external source</title>
		<link rel="alternate" type="text/html" href="https://wiki.shroudforge.net/index.php?title=Modding/zh&amp;diff=2633&amp;oldid=prev"/>
		<updated>2026-11-07T01:35:29Z</updated>

		<summary type="html">&lt;p&gt;Importing a new version from external source&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;&amp;lt;languages /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- ShroudForge Modloader Wiki Post&lt;br /&gt;
title: Modding&lt;br /&gt;
description: 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.&lt;br /&gt;
language: en-GB&lt;br /&gt;
picture:ShroudForge-Wiki-modding.svg&lt;br /&gt;
creator: Bonsaibauer&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:ShroudForge-Wiki-modding.svg|thumb|left|600px|Modding]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br style=&amp;quot;clear:both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
通过 Lua 运行时读取主菜单状态和当前选中的本地角色名称。这两个查询使用与 Modloader 相同的原生数据，无需访问世界。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;Prerequisites&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== 前置条件 ==&lt;br /&gt;
&lt;br /&gt;
启用模组，并在 &amp;lt;code&amp;gt;mod.json&amp;lt;/code&amp;gt; 中声明 &amp;lt;code&amp;gt;runtime&amp;lt;/code&amp;gt; 能力：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;capabilities&amp;quot;: [&amp;quot;runtime&amp;quot;]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
对于这些客户端查询，请在 &amp;lt;code&amp;gt;extended.mod.json&amp;lt;/code&amp;gt; 中将 &amp;lt;code&amp;gt;targets&amp;lt;/code&amp;gt; 设为 &amp;lt;code&amp;gt;&amp;amp;#91;&amp;quot;client&amp;quot;&amp;amp;#93;&amp;lt;/code&amp;gt;。从活动的运行时回调（例如 &amp;lt;code&amp;gt;on_load&amp;lt;/code&amp;gt; 和 &amp;lt;code&amp;gt;on_update&amp;lt;/code&amp;gt;）调用这些函数。&amp;lt;code&amp;gt;runtime.phase == &amp;quot;ingame&amp;quot;&amp;lt;/code&amp;gt; 表示模组运行时已启动，但不能确认已进入世界。这两个查询都不需要执行配置文件。其他世界操作仍有各自的要求。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;Detect_the_main_menu&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== 检测主菜单 ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
local in_menu, reason = runtime.is_main_menu()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! 返回值 !! 含义&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;true, nil&amp;lt;/code&amp;gt; || 已确认处于主菜单，包括角色、世界和服务器选择界面。&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;false, nil&amp;lt;/code&amp;gt; || 已验证为游戏的其他原始状态。&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;nil, reason&amp;lt;/code&amp;gt; || 状态未知、正在变化，或查询不可用。&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
请明确检查 &amp;lt;code&amp;gt;in_menu == true&amp;lt;/code&amp;gt; 或 &amp;lt;code&amp;gt;in_menu == false&amp;lt;/code&amp;gt;。&amp;lt;code&amp;gt;nil&amp;lt;/code&amp;gt; 不代表已确认的状态。单独的 &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; 也不能确认世界可读取。请另外检查所需操作，例如 &amp;lt;code&amp;gt;runtime.has(&amp;quot;runtime.ecs.read&amp;quot;)&amp;lt;/code&amp;gt;。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;Read_the_character_name&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== 读取角色名称 ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
local name, reason = runtime.player.name()&lt;br /&gt;
local display_name = name or &amp;quot;Flameborn&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;name, nil&amp;lt;/code&amp;gt; 会以 UTF-8 字符串形式返回在本地客户端主菜单中选中的角色名称。&amp;lt;code&amp;gt;Ikiju 育樹&amp;lt;/code&amp;gt; 这样的 Unicode 字符会保留。&amp;lt;code&amp;gt;nil, reason&amp;lt;/code&amp;gt; 表示名称尚不可用，或当前无法访问或不允许访问。&lt;br /&gt;
&lt;br /&gt;
模组自行选择备用名称。API 不会插入默认名称，也不会使用 Modloader 的手动名称选择。此值不代表远程玩家，也不是 SteamID 或 Steam 显示名称。专用服务器没有本地客户端角色名称。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;Shared_cache&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== 共享缓存 ==&lt;br /&gt;
&lt;br /&gt;
Lua 和 Modloader 读取同一个原生缓存。现有运行时 tick 会刷新菜单状态。现有菜单集成会在首次选择可用时获取名称，并在选择或名称元数据变化时再次获取。Lua 查询不会启动单独的发现过程，也不会读取日志。&lt;br /&gt;
&lt;br /&gt;
进入世界后，最近一次成功获取的名称仍会保留在缓存中。因此，缓存中存在名称并不能确认菜单仍处于打开状态。&amp;lt;code&amp;gt;runtime.has(&amp;quot;runtime.is_main_menu&amp;quot;)&amp;lt;/code&amp;gt; 和 &amp;lt;code&amp;gt;runtime.has(&amp;quot;runtime.player.name&amp;quot;)&amp;lt;/code&amp;gt; 会报告各自查询是否可用。&amp;lt;code&amp;gt;runtime.status(...)&amp;lt;/code&amp;gt; 也会提供原因。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;Example_for_src/mod.lua&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== &amp;lt;code&amp;gt;src/mod.lua&amp;lt;/code&amp;gt; 示例 ==&lt;br /&gt;
&lt;br /&gt;
此示例会在加载时读取缓存，之后每 500 毫秒读取一次。它会选择备用名称，并且只记录变化：&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
runtime.require(&amp;quot;runtime.lifecycle&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
local previous_message = nil&lt;br /&gt;
&lt;br /&gt;
local function refresh()&lt;br /&gt;
    local in_menu = runtime.is_main_menu()&lt;br /&gt;
    local name = runtime.player.name()&lt;br /&gt;
    local state = &amp;quot;unknown&amp;quot;&lt;br /&gt;
    if in_menu == true then&lt;br /&gt;
        state = &amp;quot;menu&amp;quot;&lt;br /&gt;
    elseif in_menu == false then&lt;br /&gt;
        state = &amp;quot;other&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local message = state .. &amp;quot;: &amp;quot; .. (name or &amp;quot;Flameborn&amp;quot;)&lt;br /&gt;
    if message ~= previous_message then&lt;br /&gt;
        previous_message = message&lt;br /&gt;
        shroudforge.log.info(message)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return {&lt;br /&gt;
    on_load = refresh,&lt;br /&gt;
    on_update = function()&lt;br /&gt;
        refresh()&lt;br /&gt;
    end,&lt;br /&gt;
    update_interval_ms = 500,&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:guide:Shroudforge]]&lt;/div&gt;</summary>
		<author><name>Bonsaibauer</name></author>
	</entry>
</feed>