◈ 青元仙途 · 攻略维基EN
🔌QYXT API v1跨模组调用接口 · 共 13 个命令
QYXT API v1 是什么:《青元仙途》对外开放的跨模组调用接口。 别的模组可以通过 tModLoader 的 Mod.Call 读取玩家境界、灵根、功法、灵气, 查询境界/灵根/功法规则表与世界进度,也能在服务端发放灵气奖励 —— 用来做联动、任务、奖励结算, 而不必反编译本模组。
适合谁看:会写 C# 模组的作者。只想玩游戏的话,这份文档用不上。

概览

项目值
协议标识(第一个参数)"QYXT"(全大写,区分大小写)
API 主版本号(第二个参数)1(Int32)
API 版本字段ApiMajor = 1,ApiMinor = 0
接口(命令)总数13 个

握手方式与版本协商(单独一节)

调用形式
object result = qyxtMod.Call("QYXT", 1, "命令名", 参数1, 参数2, ...);

三个固定前缀参数:

位置名称类型说明
args[0]协议标识string必须是 "QYXT",否则报 InvalidRequest
args[1]API 主版本int必须是 1,否则报 UnsupportedVersion
args[2]命令名string见下方接口列表,未知命令报 UnknownCommand
args[3..]命令参数视命令而定数量必须精确匹配,多传少传都报 InvalidArgument
如何判断本模组是否可用

推荐做法:反射拿 Mod 实例 + 探测 Api.GetInfo(因为 Api.GetInfo 不需要世界加载,且在菜单界面即可调用)。

Mod qyxt = null;
if (ModLoader.TryGetMod("QingzhuFengyun", out qyxt))
{
    object raw = qyxt.Call("QYXT", 1, "Api.GetInfo");
    if (raw is Dictionary<string, object> info
        && info.TryGetValue("Ok", out var ok) && ok is true
        && info.TryGetValue("ApiMajor", out var major) && major is int m && m >= 1)
    {
        // API 可用
    }
}

注意:模组内部名(ModLoader.TryGetMod 的第一个参数)源码中未直接以字符串常量出现,Api.GetInfo 返回的 ModName 字段取自 mod.Name,运行时会返回实际内部名。建议 wiki 中注明「以运行时 Api.GetInfo 返回的 ModName 为准」。

统一返回信封

所有接口永远返回一个 Dictionary<string, object>,从不抛异常到调用方(ApiRouter.Dispatch 内部 try/catch 全部兜住,见 ApiRouter.cs:95-106)。

键类型说明
Okbool成功为 true,失败为 false
ApiVersionint恒为 1
Dataobject成功时的载荷(bool / long / int / Dictionary / Dictionary[]);失败时为 null
ErrorCodestring成功时为空字符串 "",失败时为错误码
Messagestring成功时为空字符串 "",失败时为英文错误说明
错误码总表(源码原文)
ErrorCode触发条件Message 原文
InvalidRequestargs 为 null、长度 < 3、args[0] 不是字符串或不等于 "QYXT"Use Mod.Call("QYXT", 1, command, ...arguments).
InvalidArgumentargs[1] 不是 intAPI version must be Int32.
UnsupportedVersionargs[1] != 1Supported API major version: 1.
InvalidArgumentargs[2] 不是 stringCommand must be String.
UnknownCommand命令名未注册Query Api.GetCommands for supported commands.
InvalidArgument参数个数不等于 Arguments.Length + 3{命令名} expects {N} arguments.
WorldNotReady命令标记 RequiresWorld 但当前在菜单/加载界面This call requires a loaded world, not a menu/loading screen.
NotAuthority命令标记 ServerOnly 但不是服务端/单人Call only on the server or in singleplayer; no packet is sent automatically.
InvalidArgument参数类型不符(ApiArgs.Get<T>)Argument {index} must be {类型名}.
InvalidArgument数值参数既不是 int 也不是 longArgument {index} must be Int32 or Int64.
OutOfRange数值参数 <= 0 或 > 上限Amount must be between 1 and {maximum}.
OutOfRange境界 ID 不在 0–8Realm ID must be between 0 and 8; True Immortal is a separate state.
OutOfRange玩家索引不在 0–254Player index is outside Main.player.
OutOfRangeNPC 索引不在 0–Main.maxNPCs-1NPC index is outside Main.npc.
PlayerInactive目标玩家不存在或未激活The requested player is not active.
NpcInactive目标 NPC 不存在或未激活The requested NPC is not active.
PlayerDead目标玩家已死亡(仅 Player.GrantAura)Cannot reward a dead player through this API.
NoBasicTechnique玩家未学习基础功法(仅 Player.GrantAura)The player must learn a basic technique first.
UnknownKey未知秘术键 / 未知内容分类Unknown secret technique key; query Rules.GetTechniques. / Supported kinds: Item, NPC, Projectile, Buff, Tile, Wall.
NotFoundContent.Find 未命中Content name was not found; query Content.List.
InternalError处理器抛出未预期异常See the QingzhuFengyun log. Do not automatically retry mutations.
InternalError 有去重机制:同一命令名的内部错误只写一次日志(ApiRouter.cs:101-104)。
世界状态与执行端要求(重要)

分类一:元数据 / 自省类(2 个)

无需世界,任何时刻可调用。这一组是握手和自文档化的核心。

1. Api.GetInfo
字段类型含义
ModNamestring本模组内部名(运行时取自 mod.Name)
ModVersionstring模组版本字符串(mod.Version.ToString())
ApiMajorint恒为 1
ApiMinorint恒为 0
Commandsstring[]所有已注册命令名,按 Ordinal 升序排列
if (ModLoader.TryGetMod("QingzhuFengyun", out Mod qyxt))
{
    if (qyxt.Call("QYXT", 1, "Api.GetInfo") is Dictionary<string, object> info
        && info["Ok"] is true)
    {
        string ver = (string)info["ModVersion"];      // 例如 "2.1.6.10"
        int major  = (int)info["ApiMajor"];            // 1
        int minor  = (int)info["ApiMinor"];            // 0
        string[] cmds = (string[])info["Commands"];    // 全部 13 个命令名
    }
}
2. Api.GetCommands
字段类型含义
Namestring命令名
Argumentsstring[]参数签名清单,如 ["playerIndex:int", "realmId:int"]
Returnsstring返回类型描述,如 "bool"、"Dictionary<string,object>"
Summarystring中文摘要(源码原文,见各接口条目)
RequiresWorldbool是否要求已加载世界
ServerOnlybool是否仅限服务端/单人
var list = (Dictionary<string, object>[])qyxt.Call("QYXT", 1, "Api.GetCommands")["Data"];
foreach (var ep in list)
{
    string name = (string)ep["Name"];
    string[] sig = (string[])ep["Arguments"];
    string ret   = (string)ep["Returns"];
    bool needWorld = (bool)ep["RequiresWorld"];
    bool srvOnly   = (bool)ep["ServerOnly"];
    Mod.Logger.Info($"{name}({string.Join(", ", sig)}) -> {ret}");
}

分类二:规则数据查询类(3 个)

全部不需要世界,属于「静态规则表」,可在主菜单调用。返回内容全部来自枚举与规则表,不含玩家/世界状态。

3. Rules.GetRealms
字段类型含义
Idint境界 ID(0–8)
Keystring枚举稳定键名,如 "QiRefining"
Namestring中文显示名(CultivationRules.GetName)
BaseAuraThresholdlong基础突破门槛(未计个人修正,见下方数值表)
ApertureLimitint该境界累计秘窍上限
IdKeyName 语言键
0MortalMods.QingzhuFengyun.Cultivation.Realms.Mortal
1QiRefining...Realms.QiRefining
2Foundation...Realms.Foundation
3CoreFormation...Realms.CoreFormation
4NascentSoul...Realms.NascentSoul
5DeityTransformation...Realms.DeityTransformation
6SpatialTempering...Realms.SpatialTempering
7BodyIntegration...Realms.BodyIntegration
8GrandAscension...Realms.GrandAscension
Name 字段的实现是 Language.GetTextValue($"Mods.QingzhuFengyun.Cultivation.Realms.{realm}")(CultivationRules.cs:33-36),因此运行时返回的是当前语言下的本地化文案,不是硬编码中文。wiki 写作时不要写死中文名。
注意:真仙是独立状态,不在 0–8 之内(错误消息原文:Realm ID must be between 0 and 8; True Immortal is a separate state.)
境界BaseAuraThreshold
Mortal (0)0
QiRefining (1)100
Foundation (2)1,000
CoreFormation (3)10,000
NascentSoul (4)100,000
DeityTransformation (5)1,000,000
SpatialTempering (6)2,000,000
BodyIntegration (7)3,000,000
GrandAscension (8)4,000,000
另有境界配色表(CultivationRules.GetColor,CultivationRules.cs:64-75)可供 wiki 排版参考,但该接口不返回配色,如需配色需自行从源码取值:炼气 (245,245,235)、筑基 (90,225,115)、结丹 (85,165,255)、元婴 (190,105,255)、化神 (255,205,65)、炼虚 (20,20,26)、合体 (245,70,70)、大乘 (255,160,195)、默认 (175,185,180)。
境界ApertureLimit
Mortal0
QiRefining100
Foundation150
CoreFormation300
NascentSoul500
DeityTransformation800
SpatialTempering1000
BodyIntegration1300
var realms = (Dictionary<string, object>[])qyxt.Call("QYXT", 1, "Rules.GetRealms")["Data"];
foreach (var r in realms)
{
    int id = (int)r["Id"];
    string key = (string)r["Key"];
    string name = (string)r["Name"];        // 中文名
    int aperture = (int)r["ApertureLimit"];
}
4. Rules.GetSpiritRoots
字段类型含义
Maskint位标记值(1 / 2 / 4 / 8 / 16)
Keystring"Metal" / "Wood" / "Water" / "Fire" / "Earth"
Namestring元素名,中文 金/木/水/火/土,英文 Metal/Wood/Water/Fire/Earth(QingzhuText.Lang,跟随语言)
Rgbint[3]与结丹演出一致的配色,[R, G, B]
KeyMask说明
None0无(此接口不返回)
Metal1金
Wood2木
Water4水
Fire8火
Earth16土
All31五行齐全(= 1\2\4\8\16)
灵根数量 = popcount(Mask & 31),源码用 SpiritRootRules.Count(...)。 灵根品质枚举 SpiritRootQuality(SpiritRootQuality.cs):Untested, Heavenly, Superior, Ordinary, Pseudo, FiveElements —— 会在 Player.GetSnapshot 的 SpiritRootQuality 字段以字符串形式返回。
var roots = (Dictionary<string, object>[])qyxt.Call("QYXT", 1, "Rules.GetSpiritRoots")["Data"];
foreach (var r in roots)
{
    int mask = (int)r["Mask"];
    string key = (string)r["Key"];
    int[] rgb = (int[])r["Rgb"];   // 与结丹演出同色
}
// 判断玩家是否同时有金、木灵根:
bool metalWood = (mask & 1) != 0 && (mask & 2) != 0;
5. Rules.GetTechniques
键内容
Basic基础功法(不含 None)
Advanced高阶功法(不含 None)
Secret秘术(不含 None)
类别KeyName 来源
BasicThreeTurnEssenceItems.ThreeTurnEssenceArt.DisplayName
BasicProfoundYinArtItems.ProfoundYinArt.DisplayName
BasicEvergreenArtItems.EvergreenArt.DisplayName
BasicGreatDevelopmentArtItems.GreatDevelopmentArt.DisplayName
AdvancedAzureEssenceSwordArtItems.AzureEssenceSwordArt.DisplayName
AdvancedBrahmaSacredTrueDevilArtItems.BrahmaSacredTrueDevilArt.DisplayName
AdvancedMysteriousYinInfantArtItems.MysteriousYinInfantArt.DisplayName
AdvancedSpiritRefinementArtItems.SpiritRefinementArt.DisplayName
SecretSuNuReincarnationArtItems.SuNuReincarnationArt.DisplayName
SecretBloodDemonScriptureItems.BloodDemonScripture.DisplayName
SecretShaDemonArtItems.ShaDemonArt.DisplayName
SecretExorcisingThunderArtItems.ExorcisingThunderArt.DisplayName
SecretIncompleteDemonScriptureItems.IncompleteDemonScripture.DisplayName
SecretXuanSoulDemonManualItems.XuanSoulDemonManual.DisplayName
SecretInsectRepellingArtItems.InsectRepellingSecretArt.DisplayName(注意物品名与键名不同)
SecretGreatGengSwordArray硬编码中文 大庚剑阵秘术
SecretSwordControlArt硬编码中文 御剑术
SecretSixExtremeTrueDemonArt硬编码中文 六极真魔功
SecretMagneticDivineLight硬编码中文 元磁神光
SecretGoldDevouringCultivation硬编码中文 噬金虫培养秘籍
SecretBloodRefiningDivineLightItems.BloodRefiningDivineLight.DisplayName
SecretShuraHolyFireArtItems.ShuraHolyFireSecretArt.DisplayName(注意物品名与键名不同)
var dict = (Dictionary<string, object>)qyxt.Call("QYXT", 1, "Rules.GetTechniques")["Data"];
var secrets = (Dictionary<string, object>[])dict["Secret"];
foreach (var s in secrets)
    Mod.Logger.Info($"{s["Key"]} = {s["Name"]}");
// 输出形如: SuNuReincarnationArt = 素女轮回功

分类三:玩家状态读取类(4 个)

全部 RequiresWorld: true、ServerOnly: false。playerIndex 取值 0 ≤ index < 255,越界返回 OutOfRange;指向的玩家不存在或未激活返回 PlayerInactive。

索引来源即 Main.player[index],一般用 player.whoAmI。
6. Player.GetSnapshot
字段类型含义
PlayerIndexintplayer.whoAmI
IsAuthoritativeboolMain.netMode != 1(是否权威数据)
NaturalRealmint自然境界(不受场景压制)
EffectiveRealmint有效境界(受场景压制影响)
RealmLevelint当前境界内的等级
IsTrueImmortalbool是否为真仙
RealmSuppressedbool是否被宫殿场景压制(PalaceRealmSuppressed)
Auralong当前灵气值
AuraStorageCaplong灵气存储上限(GetAuraStorageCap())
ImmortalSpiritQilong真仙仙气值
SpiritRootMaskint灵根位标记(已 & All)
SpiritRootCountint灵根数量
SpiritRootQualitystring灵根品质枚举名字符串
RefinedFiveElements(源码未显式转型,为 int/byte 计数)已炼化五行数量
AbsorbedSpiritQiMaskint已吸收灵气位标记(已 & All)
BasicTechniquestring基础功法键名,未学为 "None"
AdvancedTechniquestring高阶功法键名,未学为 "None"
SelectedSecretstring当前选装秘术键名,未选为 "None"
UnlockedSecretsstring[]已解锁秘术键名数组(不含 None)
DharmicPower(数值)法力值
DharmicPowerMaximum(数值)法力上限
DivineSense(数值)神识值
DivineSenseMaximum(数值)神识上限
ApertureCoresUsed(数值)已用秘窍数
ApertureLimit(数值)秘窍上限
ApertureRemaining(数值)剩余秘窍(Math.Max(0, 上限 - 已用))
var res = (Dictionary<string, object>)qyxt.Call("QYXT", 1, "Player.GetSnapshot", player.whoAmI);
if ((bool)res["Ok"])
{
    var d = (Dictionary<string, object>)res["Data"];
    Mod.Logger.Info($"境界={d["EffectiveRealm"]} 灵气={d["Aura"]}/{d["AuraStorageCap"]}");
    string[] unlocked = (string[])d["UnlockedSecrets"];
}
else Mod.Logger.Warn($"查询失败 {res["ErrorCode"]}: {res["Message"]}");
7. Player.MeetsRealm
// 该玩家是否至少元婴(Id=4),按有效境界判定
bool ok = (bool)qyxt.Call("QYXT", 1, "Player.MeetsRealm", player.whoAmI, 4, false)["Data"];

// 按自然境界判定(忽略宫殿压制)
bool natural = (bool)qyxt.Call("QYXT", 1, "Player.MeetsRealm", player.whoAmI, 4, true)["Data"];
8. Player.GetThreshold
long need = (long)qyxt.Call("QYXT", 1, "Player.GetThreshold", player.whoAmI, 5)["Data"];
long aura = (long)((Dictionary<string,object>)qyxt.Call("QYXT",1,"Player.GetSnapshot",player.whoAmI)["Data"])["Aura"];
Mod.Logger.Info($"化神所需 {need},当前 {aura}");
9. Player.HasSecret
bool has = (bool)qyxt.Call("QYXT", 1, "Player.HasSecret", player.whoAmI, "SwordControlArt")["Data"];

分类四:玩家状态写入类(1 个)

10. Player.GrantAura
字段类型含义
Requestedlong请求发放的量(原样回显)
Appliedlong实际生效的量(受上限/加成/转化影响,可能为 0)
Resourcestring"Aura"(普通灵气)或 "ImmortalSpiritQi"(真仙仙气)
// 仅服务端执行
if (Main.netMode != NetmodeID.MultiplayerClient)
{
    var res = (Dictionary<string, object>)qyxt.Call("QYXT", 1, "Player.GrantAura", player.whoAmI, 5000L);
    if ((bool)res["Ok"])
    {
        var d = (Dictionary<string, object>)res["Data"];
        long applied = (long)d["Applied"];      // 实际到账(可能被上限截断为 0)
        string res2  = (string)d["Resource"];   // "Aura" 或 "ImmortalSpiritQi"
    }
    else Mod.Logger.Warn($"发放失败 {res["ErrorCode"]}: {res["Message"]}");
}

分类五:世界与 NPC 查询类(2 个)

11. NPC.GetSnapshot
字段类型含义
NpcIndexint传入的索引
TypeintNPC 类型 ID
Realmint该 NPC 的境界 ID(CultivationRules.ClassifyNPC 分类结果)
IsBossbool`npc.boss \\Sets.ShouldBeCountedAsBoss[type]`
ModNamestring所属模组名(null 时回落为 "Terraria")
IsAuthoritativeboolMain.netMode != 1
var res = (Dictionary<string, object>)qyxt.Call("QYXT", 1, "NPC.GetSnapshot", npc.whoAmI);
if ((bool)res["Ok"])
{
    var d = (Dictionary<string, object>)res["Data"];
    int realm = (int)d["Realm"];
    bool boss = (bool)d["IsBoss"];
    string from = (string)d["ModName"];
}
12. World.GetProgress
字段类型含义
IsAuthoritativeboolMain.netMode != 1
RealmCeilingint当前世界允许达到的境界上限(CultivationProgressionSystem.GetCurrentRealmCeiling())
BossesDictionary<string, object>各 Boss 是否已通关(永久记录,已同步)
键数据来源
InkFloodDragonInkFloodDragonWorldSystem.DownedInkFloodDragon
BloodJadeSpiderBloodJadeSpiderWorldSystem.DownedBloodJadeSpider
KingXuKingXuWorldSystem.DownedKingXu
WhiteHairedHealerWhiteHairedHealerWorldSystem.DownedWhiteHairedHealer
PoisonFloodDragon`PoisonFloodDragonWorld.Downed \\StarSeaBossChecklist.Done(1)`
HiddenShaMasterStarSeaBossChecklist.Done(64)
RuinXuanGuStarSeaBossChecklist.Done(2)
VoidFireAntQueenStarSeaBossChecklist.Done(4)
VoidHeavenPalaceStarSeaBossChecklist.Done(8)
WenTianrenStarSeaBossChecklist.Done(16)
NestBlackPythonEscapeStarSeaBossChecklist.Done(32)
YuanchaYuanchaWorldSystem.DownedYuancha
MaLiangYuanchaWorldSystem.DownedMaLiang
var w = (Dictionary<string,object>)qyxt.Call("QYXT", 1, "World.GetProgress")["Data"];
int ceiling = (int)w["RealmCeiling"];
var bosses = (Dictionary<string,object>)w["Bosses"];
bool killedKingXu = (bool)bosses["KingXu"];

分类六:内容 ID 查询类(2 个)

均不需要世界,可在主菜单调用。用于把本模组的内部名解析成运行时 ID。

13. Content.Find
int itemType = (int)qyxt.Call("QYXT", 1, "Content.Find", "Item", "HeavenBottle")["Data"];
int npcType  = (int)qyxt.Call("QYXT", 1, "Content.Find", "NPC",  "MaLiang")["Data"];
// 生成一个物品:
Item.NewItem(null, (int)player.position.X, (int)player.position.Y, 0, 0, itemType);
14. Content.List
⚠️ 编号说明:此处序号 14 仅为文档条目编号,接口实际总数为 13(本条目与第 13 条同属内容查询类,文档按节顺序编排)。
字段类型含义
Namestring内部名
FullNamestring模组名 + "/" + Name,即完整内容名
Idint运行时 ID(ModItem.Type / ModNPC.Type 等;Tile/Wall 取 ModBlockType.Type)
var items = (Dictionary<string, object>[])qyxt.Call("QYXT", 1, "Content.List", "Item")["Data"];
foreach (var it in items)
{
    string name = (string)it["Name"];
    string full = (string)it["FullName"];   // "QingzhuFengyun/HeavenBottle"
    int id      = (int)it["Id"];
}

完整接口速查表

#命令名参数返回需世界仅服务端一句话用途
1Api.GetInfo—Dict✗✗握手:拿模组版本、API 版本与命令清单
2Api.GetCommands—Dict[]✗✗自省:运行时枚举全部接口及其签名/要求
3Rules.GetRealms—Dict[]✗✗境界 ID、基础门槛、秘窍上限全表
4Rules.GetSpiritRoots—Dict[]✗✗五行灵根位标记与官方 RGB 配色
5Rules.GetTechniques—Dict✗✗基础/高阶功法与秘术的键名→中文名目录
6Player.GetSnapshotplayerIndexDict✓✗玩家修仙状态全量只读快照
7Player.MeetsRealmplayerIndex, realmId, useNaturalRealmbool✓✗判断玩家是否达到某境界
8Player.GetThresholdplayerIndex, realmIdlong✓✗查该玩家突破到某境界所需灵气
9Player.HasSecretplayerIndex, secretKeybool✓✗判断某秘术是否已解锁
10Player.GrantAuraplayerIndex, baseAmountDict✓✓服务端发放灵气奖励
11NPC.GetSnapshotnpcIndexDict✓✗查 NPC 的境界/是否 Boss/所属模组
12World.GetProgress—Dict✓✗世界境界上限与 13 项 Boss 通关记录
13Content.Findkind, internalNameint✗✗内部名 → 运行时内容 ID
14Content.ListkindDict[]✗✗枚举某分类全部内容名与 ID