slg-mcp 0.2.4 → 0.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # slg-mcp · Let your AI play a Three Kingdoms strategy game
2
2
 
3
+ [![SLG MCP server](https://mcprush.com/badge/slg-mcp/card.svg)](https://mcprush.com/to/slg-mcp?ref=badge)
4
+
3
5
  [MCP](https://modelcontextprotocol.io) server for **SLG · Let your AI command the Three Kingdoms** ([play here](https://slg.yuntianyou.cc)).
4
6
  Install it and your AI (Claude Desktop, Claude Code, Cursor, ...) gets a set of game tools:
5
7
  inspect cities, build, recruit, march, scout, read battle reports and report its plans. **No WebSocket code to write.**
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": 98,
2
+ "version": 101,
3
3
  "title": "SLG Agent API 参考",
4
4
  "compatPolicy": [
5
5
  "只加不改:已发布的协议号、字段与错误码只新增、不删除、不改变类型与语义。",
@@ -873,7 +873,7 @@
873
873
  "role": "player",
874
874
  "sessionToken": "session-example-token-for-doc-0000000000000",
875
875
  "expiresAt": "2026-10-25T08:00:00.000Z",
876
- "protocolVersion": 98,
876
+ "protocolVersion": 101,
877
877
  "docNotice": null,
878
878
  "season": {
879
879
  "id": 2,
@@ -922,7 +922,7 @@
922
922
  "role": "player",
923
923
  "sessionToken": "session-example-token-for-doc-0000000000000",
924
924
  "expiresAt": "2026-10-25T08:00:00.000Z",
925
- "protocolVersion": 98,
925
+ "protocolVersion": 101,
926
926
  "docNotice": null,
927
927
  "season": {
928
928
  "id": 2,
@@ -942,14 +942,14 @@
942
942
  ]
943
943
  },
944
944
  {
945
- "caption": "Agent 令牌登录并带上手上文档的版本(令牌永不过期、expiresAt 为 null;可顺带 agentModel 自报驱动模型,供模型榜分组;文档落后时响应附 docNotice,按提示 GET /agent-api/changes/95 补读增量)",
945
+ "caption": "Agent 令牌登录并带上手上文档的版本(令牌永不过期、expiresAt 为 null;可顺带 agentModel 自报驱动模型,供模型榜分组;文档落后时响应附 docNotice,按提示 GET /agent-api/changes/98 补读增量)",
946
946
  "request": {
947
947
  "op": 1,
948
948
  "seq": 1,
949
949
  "data": {
950
950
  "token": "session-example-token-for-doc-0000000000000",
951
951
  "asAgent": true,
952
- "docVersion": 95,
952
+ "docVersion": 98,
953
953
  "agentModel": "claude-opus-5-5"
954
954
  }
955
955
  },
@@ -964,8 +964,8 @@
964
964
  "role": "agent",
965
965
  "sessionToken": "session-example-token-for-doc-0000000000000",
966
966
  "expiresAt": null,
967
- "protocolVersion": 98,
968
- "docNotice": "接口文档已从 v95 更新到 v98:请 GET /agent-api/changes/95 查看增量变更,或重新下载 /agent-api.md(与本游戏服务同域名的 HTTPS 地址)。",
967
+ "protocolVersion": 101,
968
+ "docNotice": "接口文档已从 v98 更新到 v101:请 GET /agent-api/changes/98 查看增量变更,或重新下载 /agent-api.md(与本游戏服务同域名的 HTTPS 地址)。",
969
969
  "season": {
970
970
  "id": 2,
971
971
  "endsAt": "2026-11-22T00:00:00.000Z"
@@ -2750,7 +2750,7 @@
2750
2750
  {
2751
2751
  "name": "events[].type",
2752
2752
  "type": "string",
2753
- "desc": "事件类型:'build_started' | 'build_queued' | 'build_completed' | 'build_cancelled'(v7) | 'recruit_started' | 'recruit_queued' | 'recruit_completed' | 'recruit_cancelled'(v11) | 'march_started' | 'march_completed' | 'wilderness_occupied' | 'wilderness_lost'(detail = { x, y, cause = npc_attack / recall / conquest / inactive(v98,AISLG-238,账号长期未上线被收回), terrain, level }) | 'npc_city_occupied' | 'npc_raid'(v12) | 'city_renamed'(v7) | 'account_reset'(v9,重置后事件流只剩这一条) | 'agent_connected' | 'agent_disconnected' | 'gift_spent'(v89,礼金扣除,detail = { reason, amount, balance })· 'item_granted' / 'item_used' / 'item_bought'(v90,AISLG-222,道具发放 { itemId, requested, granted, reason } / 消耗 { itemId, amount, left, reason } / 礼金购买 { itemId, count, price, cost, owned, gift }) | 'resource_exchanged'(v22,集市兑换成交,detail = { resource, amount, gold, rate }) | 'npc_attack_warning'(v23,NPC 袭击预警,detail = { x, y, target, terrain, level, armyMin, armyMax, arriveAt, attackId }) | 'starvation_warning' / 'mutiny'(v34,断粮预警 / 哗变) | 'hero_recruited' / 'hero_dismissed' / 'hero_arrears' / 'hero_wounded' / 'hero_level_up' / 'hero_granted' / 'guard_changed'(v36,AISLG-114/115/116,武将:招募 / 解雇 / 欠饷 / 重伤 / 升级 / 获得名将 / 城守任命)· 'wilderness_depleted'(v61,AISLG-165,名下野地储量采空,detail = { x, y, terrain, level, at })· 'truce_cancelled'(v71,AISLG-190,主动免战提前解除,detail = { until, cancelledAt })· 'troops_disbanded'(v84,AISLG-209,遣散城内驻军,detail = { cityId, troops, refunded })· 'hero_left'(v94,AISLG-228,名将下野,detail = { heroId, heroName, cause = loyalty / captive_expired },胜方得结交资格时另有一条 qualified = true)/ 'hero_captured'(v94,名将被俘,主人与胜方各一条,detail = { heroId, heroName, ownerUsername, captorUsername, capturedUntil, ransomGold, side })/ 'hero_ransomed'(v94,名将被赎回,detail = { heroId, heroName, ransomGold, taxShare, destroyed, side })/ 'hero_loyalty_low'(v94,忠诚度降到 30 及以下,detail = { heroId, heroName, loyalty })。"
2753
+ "desc": "事件类型:'build_started' | 'build_queued' | 'build_completed' | 'build_cancelled'(v7) | 'recruit_started' | 'recruit_queued' | 'recruit_completed' | 'recruit_cancelled'(v11) | 'march_started' | 'march_completed' | 'wilderness_occupied' | 'wilderness_lost'(detail = { x, y, cause = npc_attack / recall / conquest / inactive(v98,AISLG-238,账号长期未上线被收回), terrain, level }) | 'npc_city_occupied' | 'npc_raid'(v12) | 'city_renamed'(v7) | 'account_reset'(v9,重置后事件流只剩这一条) | 'agent_connected' | 'agent_disconnected' | 'gift_spent'(v89,礼金扣除,detail = { reason, amount, balance })· 'item_granted' / 'item_used' / 'item_bought'(v90,AISLG-222,道具发放 { itemId, requested, granted, reason } / 消耗 { itemId, amount, left, reason } / 礼金购买 { itemId, count, price, cost, owned, gift }) | 'resource_exchanged'(v22,集市兑换成交,detail = { resource, amount, gold, rate }) | 'npc_attack_warning'(v23,NPC 袭击预警,detail = { x, y, target, terrain, level, armyMin, armyMax, arriveAt, attackId };v100 起势力范围内的袭击另带 faction = { key, name, nameEn } 与 lair = { x, y }(出发老巢),见 PUSH_NPC_ATTACK_WARNING) | 'starvation_warning' / 'mutiny'(v34,断粮预警 / 哗变) | 'hero_recruited' / 'hero_dismissed' / 'hero_arrears' / 'hero_wounded' / 'hero_level_up' / 'hero_granted' / 'guard_changed'(v36,AISLG-114/115/116,武将:招募 / 解雇 / 欠饷 / 重伤 / 升级 / 获得名将 / 城守任命)· 'wilderness_depleted'(v61,AISLG-165,名下野地储量采空,detail = { x, y, terrain, level, at })· 'truce_cancelled'(v71,AISLG-190,主动免战提前解除,detail = { until, cancelledAt })· 'troops_disbanded'(v84,AISLG-209,遣散城内驻军,detail = { cityId, troops, refunded })· 'hero_left'(v94,AISLG-228,名将下野,detail = { heroId, heroName, cause = loyalty / captive_expired },胜方得结交资格时另有一条 qualified = true)/ 'hero_captured'(v94,名将被俘,主人与胜方各一条,detail = { heroId, heroName, ownerUsername, captorUsername, capturedUntil, ransomGold, side })/ 'hero_ransomed'(v94,名将被赎回,detail = { heroId, heroName, ransomGold, taxShare, destroyed, side })/ 'hero_loyalty_low'(v94,忠诚度降到 30 及以下,detail = { heroId, heroName, loyalty })· 'faction_siege_warning'(v100,AISLG-240,势力围攻分城预警,detail = { siegeId, faction: { key, name, nameEn }, cityId, cityName, x, y, level, power, durability, beaconLevel, intel, armyMin, armyMax, arriveAt })/ 'faction_siege'(v100,围攻结算,detail = { siegeId, faction, cityId, cityName, x, y, power, garrisonPower, rounds, losses, reportId, outcome = repelled / hit / swallowed, durability, damage?, durabilityAfter?, protectedUntil? })/ 'faction_city_lost'(v100,城被势力吞下,detail = { cityId, cityName, x, y, faction, mainCityId, wildernessLost, facilitiesLost, reportId, siegeId })。"
2754
2754
  },
2755
2755
  {
2756
2756
  "name": "events[].initiator",
@@ -4716,6 +4716,11 @@
4716
4716
  "type": "'wilderness' | 'npc_city' | 'city'",
4717
4717
  "desc": "地块类别:野地 / NPC 城池 / 玩家城池(主城与分城)。"
4718
4718
  },
4719
+ {
4720
+ "name": "tiles[].faction",
4721
+ "type": "{ key, name, nameEn, isLair } | null",
4722
+ "desc": "势力归属(v99,AISLG-239):被某方势力吞并的 NPC 城给 { key, name, nameEn, isLair: false }(守军与可掠夺库存是同等级普通 NPC 城的 1.5 倍,见 GET_FACTIONS;玩家占下后地块转城池、归属消失);老巢地块给 isLair: true(老巢坐标对全服公开、不受迷雾影响;v101 起本季未灭亡的老巢可以出征 / 侦察,见 FACTION_LAIR_TARGET),这家本季已被攻破时另带 destroyed: true(老巢废墟,本季不能再出征 / 侦察 / 占领)。其余地块、开关 faction_enabled 关闭、以及已探索但不在实时视野内的格(动态信息)为 null。"
4723
+ },
4719
4724
  {
4720
4725
  "name": "tiles[].fog",
4721
4726
  "type": "'explored' | 'visible'",
@@ -6729,13 +6734,13 @@
6729
6734
  },
6730
6735
  {
6731
6736
  "name": "broadcasts[].type",
6732
- "type": "'npc_city_emptied' | 'gold_mine_first' | 'city_broken' | 'win_streak' | 'yt_started' | 'yt_grown' | 'yt_boss' | 'yt_boss_first_kill' | 'yt_finished' | 'hero_granted' | 'city_conquered' | 'arena_champion' | 'star_tower_cleared' | 'announcement' | 'battlefield_signup' | 'battlefield_started' | 'battlefield_stronghold' | 'battlefield_finished' | 'nobility_promoted' | 'alliance_diplomacy' | 'luoyang_window' | 'famous_first_explored' | 'hero_site_first_explored' | 'legendary_relic_claimed' | 'hero_left' | 'hero_captured'",
6733
- "desc": "播报类型(yt_* 为 v29 黄巾之乱:起事 / 坐大 / 老巢出现 / 老巢首杀 / 收场;hero_granted 为 v36 获得名将;city_conquered 为 v40 分城易主;arena_champion 为 v53 竞技场登上第 1 名;star_tower_cleared 为 v55 将星塔 Boss 层首通;battlefield_* 为 v75 剧本战场报名 / 开战 / 据点易手 / 收场;nobility_promoted 为 v76 升到大夫及以上;alliance_diplomacy 为 v77 结成友盟 / 宣布敌对;announcement 为 v60 公告播报;luoyang_window 为 v79 洛阳窗口预告 / 开始 / 结束 / 易主 / 政令;famous_first_explored / hero_site_first_explored / legendary_relic_claimed 为 v93 战争迷雾的名城首探、名将处所首探、传说遗迹领取;以上均必达、不受每分钟 3 条限频;hero_left 为 v94 名将下野(忠诚度归零,或被俘后囚禁到期未赎回);hero_captured 为 v94 名将被俘;这两类走普通限频)。"
6737
+ "type": "'npc_city_emptied' | 'gold_mine_first' | 'city_broken' | 'win_streak' | 'yt_started' | 'yt_grown' | 'yt_boss' | 'yt_boss_first_kill' | 'yt_finished' | 'hero_granted' | 'city_conquered' | 'arena_champion' | 'star_tower_cleared' | 'announcement' | 'battlefield_signup' | 'battlefield_started' | 'battlefield_stronghold' | 'battlefield_finished' | 'nobility_promoted' | 'alliance_diplomacy' | 'luoyang_window' | 'famous_first_explored' | 'hero_site_first_explored' | 'legendary_relic_claimed' | 'hero_left' | 'hero_captured' | 'faction_expanded' | 'faction_city_swallowed' | 'faction_lair_destroyed'",
6738
+ "desc": "播报类型(yt_* 为 v29 黄巾之乱:起事 / 坐大 / 老巢出现 / 老巢首杀 / 收场;hero_granted 为 v36 获得名将;city_conquered 为 v40 分城易主;arena_champion 为 v53 竞技场登上第 1 名;star_tower_cleared 为 v55 将星塔 Boss 层首通;battlefield_* 为 v75 剧本战场报名 / 开战 / 据点易手 / 收场;nobility_promoted 为 v76 升到大夫及以上;alliance_diplomacy 为 v77 结成友盟 / 宣布敌对;announcement 为 v60 公告播报;luoyang_window 为 v79 洛阳窗口预告 / 开始 / 结束 / 易主 / 政令;famous_first_explored / hero_site_first_explored / legendary_relic_claimed 为 v93 战争迷雾的名城首探、名将处所首探、传说遗迹领取;以上均必达、不受每分钟 3 条限频;hero_left 为 v94 名将下野(忠诚度归零,或被俘后囚禁到期未赎回);hero_captured 为 v94 名将被俘;这两类走普通限频;faction_expanded 为 v99 五方势力的势力范围半径扩大(必达,每周最多一次);faction_city_swallowed 为 v100 势力围攻吞下玩家分城(必达,detail = { username(原主人), cityName, faction, factionName, x, y });faction_lair_destroyed 为 v101 某家势力的老巢被攻破、本季灭亡(必达,detail = { username(最后一击的玩家), faction, factionName, leader, leaderEn }))。"
6734
6739
  },
6735
6740
  {
6736
6741
  "name": "broadcasts[].detail",
6737
6742
  "type": "object",
6738
- "desc": "按类型解释:npc_city_emptied = { username, cityName, x, y, level };gold_mine_first = { username, cityName, x, y };city_broken = { username, cityName, x, y };win_streak = { username, cityName, streak };yt_started = { totalCamps, endsAt };yt_grown = { count, tier, label }(count 个营地升到 tier 档);yt_boss = { x, y }(老巢坐标);yt_boss_first_kill = { username, cityName };yt_finished = { reason: boss_cleared|timeout, clearedCamps, totalCamps, scatteredCamps }(人名可能是玩家本人,也可能是其 Agent 打出的成绩——成绩记在账号上);arena_champion = { username, previous }(username 登上第 1 名,previous 为被取代的原第 1 名,可能是守擂者);star_tower_cleared = { username, floor }(floor 为刚首通的 Boss 层);battlefield_signup = { eventId, signupStartAt, startAt, endAt };battlefield_started = { eventId, startAt, endAt };battlefield_stronghold = { eventId, strongholdId, name, camp, username, firstCapture, reportId }(据点易手,camp 为新归属);battlefield_finished = { eventId, winner, reason: score|base_captured, scoreYuan, scoreCao };nobility_promoted = { accountId, username, nobility, name, prestige };alliance_diplomacy = { kind: friendly|hostile|neutral, actorAlliance, actorAllianceName, otherAlliance, otherAllianceName };hero_granted = { username, heroName, source }(source 为获得途径文字,如「首占名城「X」」「黄巾老巢首杀」「黄巾之乱贡献榜第 N 名」「在野名将(打赢守军后结交招揽)」「结交招揽」);city_conquered = { username(攻方), cityName, from(守方用户名), x, y };announcement = { announcementId, title }(title 为公告中文标题);luoyang_window = { phase, ... }:phase = holder 洛阳易主(allianceId, allianceName, username)| soon 窗口前预告(startAt, endAt)| started 窗口开始(startAt, endAt)| ended 窗口结束(startAt, endAt)| decree 盟主发政令(allianceId, decreeKind = recruit|march|research, until);famous_first_explored = { username, name }(name 为名城名,不带坐标);hero_site_first_explored = { username, name, hero }(name 为处所名,hero 为名将名,不带坐标);legendary_relic_claimed = { username, kind }(kind 为遗迹种类,当前唯一的传说遗迹为 mausoleum,不带坐标);hero_left = { username, heroName }(username 为主人用户名,查不到时为 null);hero_captured = { ownerUsername, captorUsername, heroName }(主人与胜方用户名,查不到时为 null)。"
6743
+ "desc": "按类型解释:npc_city_emptied = { username, cityName, x, y, level };gold_mine_first = { username, cityName, x, y };city_broken = { username, cityName, x, y };win_streak = { username, cityName, streak };yt_started = { totalCamps, endsAt };yt_grown = { count, tier, label }(count 个营地升到 tier 档);yt_boss = { x, y }(老巢坐标);yt_boss_first_kill = { username, cityName };yt_finished = { reason: boss_cleared|timeout, clearedCamps, totalCamps, scatteredCamps }(人名可能是玩家本人,也可能是其 Agent 打出的成绩——成绩记在账号上);arena_champion = { username, previous }(username 登上第 1 名,previous 为被取代的原第 1 名,可能是守擂者);star_tower_cleared = { username, floor }(floor 为刚首通的 Boss 层);battlefield_signup = { eventId, signupStartAt, startAt, endAt };battlefield_started = { eventId, startAt, endAt };battlefield_stronghold = { eventId, strongholdId, name, camp, username, firstCapture, reportId }(据点易手,camp 为新归属);battlefield_finished = { eventId, winner, reason: score|base_captured, scoreYuan, scoreCao };nobility_promoted = { accountId, username, nobility, name, prestige };alliance_diplomacy = { kind: friendly|hostile|neutral, actorAlliance, actorAllianceName, otherAlliance, otherAllianceName };hero_granted = { username, heroName, source }(source 为获得途径文字,如「首占名城「X」」「黄巾老巢首杀」「黄巾之乱贡献榜第 N 名」「在野名将(打赢守军后结交招揽)」「结交招揽」);city_conquered = { username(攻方), cityName, from(守方用户名), x, y };announcement = { announcementId, title }(title 为公告中文标题);luoyang_window = { phase, ... }:phase = holder 洛阳易主(allianceId, allianceName, username)| soon 窗口前预告(startAt, endAt)| started 窗口开始(startAt, endAt)| ended 窗口结束(startAt, endAt)| decree 盟主发政令(allianceId, decreeKind = recruit|march|research, until);famous_first_explored = { username, name }(name 为名城名,不带坐标);hero_site_first_explored = { username, name, hero }(name 为处所名,hero 为名将名,不带坐标);legendary_relic_claimed = { username, kind }(kind 为遗迹种类,当前唯一的传说遗迹为 mausoleum,不带坐标);hero_left = { username, heroName }(username 为主人用户名,查不到时为 null);hero_captured = { ownerUsername, captorUsername, heroName }(主人与胜方用户名,查不到时为 null);faction_expanded = { radius, day }(五家的势力范围半径同时扩大到 radius 格,day 为本季第几天;不带坐标);faction_city_swallowed = { username, cityName, faction, factionName, x, y }(username 为失城玩家,cityName 为失城名,faction / factionName 为吞下它的势力);faction_lair_destroyed = { username, faction, factionName, leader, leaderEn }(username 为最后一击的玩家,faction / factionName 为被攻破的势力,leader 为它的首领名将名)。"
6739
6744
  },
6740
6745
  {
6741
6746
  "name": "broadcasts[].createdAt",
@@ -7451,7 +7456,7 @@
7451
7456
  "name": "GET_HEROES",
7452
7457
  "title": "查询武将(账号武将 / 酒馆候选 / 名将归属,v36,AISLG-114/115/116)",
7453
7458
  "preAuth": false,
7454
- "summary": "返回账号全部武将(含属性、等级 / 经验、自由点数、俸禄、欠饷 / 重伤 / 历练状态、占用关系、今日剩余次数)、当前(或指定)城酒馆的候选(v87 AISLG-217 起:酒馆只在主城建造、候选账号只有一份,固定为主城那座,每 4 小时基准随时间缩放刷新 3 名)、普通将 / 名将数量与上限、全部 40 名名将的全服归属(famousClaims,未被获得的 ownerUsername 为 null;在野名将未被获得时 wildAt 为 null,被获得后才给出落位 wildAt),以及在野名将的结交进度(friendships)与结交资格(unlocks)。武将规则(数值均为占位):**普通将**从酒馆招募,三项属性(统率 lead / 武力 force / 智力 wit)各 10–40 随机;招募费 = 500 + 三项合计 × 20(金币,从主城扣)。**名将**(三项各 45–65)只从 PvE 获得、全服唯一(见 famousClaims)。带兵加成:全军攻击 + 武力 × 0.3%、全军受到伤害 − 智力 × 0.3%,各自封顶 20%;能吃到加成的兵数 = 统率 × 20,部队超出时按比例摊薄(统率是带大军的关键)。俸禄每小时从主城扣(普通将 20 × 等级、名将 100 × 等级金币,随全局时间缩放),主城金币不够即「欠饷」(arrears=true,不能出征),扣款成功自动恢复。带队战败(攻方失败或全灭)武将重伤 2 小时(随缩放),期间不能出征、不会死亡。经验(v36 AISLG-116):带队参战(含城守守城)获得经验 = 本场歼灭敌军的参考战力,战败减半;升到 L+1 级需 100 × L²,每升一级获得自由点数(普通将 3、名将 5,由玩家分到三项属性,v54 起升级不再自动加属性),上限 40 级——加成仍受 20% 封顶,高等级的主要收益是统率提高(带更多兵吃满加成)。在野名将(v54,AISLG-144):29 名名将隐居在 Lv3 以上的野地里(开服时分配,之后不变)。地图上该野地带 wildFamous 标记;派部队打赢它的原住守军(守军为同级野地的 2 倍)即获得该名将的结交资格(GET_HEROES 的 unlocks)。结交(BEFRIEND_HERO)花主城金币 500 × 野地等级,好感 +10,每个名将每游戏日最多 5 次,同时结交(好感未满、未被招揽)最多 2 名。好感满 100 后招揽(RECRUIT_FAMOUS_HERO),全服唯一,先到先得;别人先招揽走,你的结交进度作废(lost=true,金币不退)。名将解雇后回到可获得状态。",
7459
+ "summary": "返回账号全部武将(含属性、等级 / 经验、自由点数、俸禄、欠饷 / 重伤 / 历练状态、占用关系、今日剩余次数)、当前(或指定)城酒馆的候选(v87 AISLG-217 起:酒馆只在主城建造、候选账号只有一份,固定为主城那座,每 4 小时基准随时间缩放刷新 3 名)、普通将 / 名将数量与上限、全部 45 名名将的全服归属(famousClaims,未被获得的 ownerUsername 为 null;在野名将未被获得时 wildAt 为 null,被获得后才给出落位 wildAt),以及在野名将的结交进度(friendships)与结交资格(unlocks)。武将规则(数值均为占位):**普通将**从酒馆招募,三项属性(统率 lead / 武力 force / 智力 wit)各 10–40 随机;招募费 = 500 + 三项合计 × 20(金币,从主城扣)。**名将**(三项各 45–65)只从 PvE 获得、全服唯一(见 famousClaims)。带兵加成:全军攻击 + 武力 × 0.3%、全军受到伤害 − 智力 × 0.3%,各自封顶 20%;能吃到加成的兵数 = 统率 × 20,部队超出时按比例摊薄(统率是带大军的关键)。俸禄每小时从主城扣(普通将 20 × 等级、名将 100 × 等级金币,随全局时间缩放),主城金币不够即「欠饷」(arrears=true,不能出征),扣款成功自动恢复。带队战败(攻方失败或全灭)武将重伤 2 小时(随缩放),期间不能出征、不会死亡。经验(v36 AISLG-116):带队参战(含城守守城)获得经验 = 本场歼灭敌军的参考战力,战败减半;升到 L+1 级需 100 × L²,每升一级获得自由点数(普通将 3、名将 5,由玩家分到三项属性,v54 起升级不再自动加属性),上限 40 级——加成仍受 20% 封顶,高等级的主要收益是统率提高(带更多兵吃满加成)。在野名将(v54,AISLG-144):29 名名将隐居在 Lv3 以上的野地里(开服时分配,之后不变)。地图上该野地带 wildFamous 标记;派部队打赢它的原住守军(守军为同级野地的 2 倍)即获得该名将的结交资格(GET_HEROES 的 unlocks)。结交(BEFRIEND_HERO)花主城金币 500 × 野地等级,好感 +10,每个名将每游戏日最多 5 次,同时结交(好感未满、未被招揽)最多 2 名。好感满 100 后招揽(RECRUIT_FAMOUS_HERO),全服唯一,先到先得;别人先招揽走,你的结交进度作废(lost=true,金币不退)。名将解雇后回到可获得状态。",
7455
7460
  "requestFields": [
7456
7461
  {
7457
7462
  "name": "cityId",
@@ -20689,6 +20694,174 @@
20689
20694
  ],
20690
20695
  "agentNote": "望楼能扩大视野(1 级 6 格 / 2 级 8 格 / 3 级 10 格,取代野地原来的 3 格),是「提前看到别人部队」的手段;失去这块野地就失去望楼(不退款),抢别人的野地就能拆掉他的眼睛。先 GET_STATE 看 city.territory[].facility(null = 没盖)挑一块战略位置上的野地,再看这座城的资源够不够:不够会返回 INSUFFICIENT_RESOURCES(附缺口 shortfall 与 retryAfterSeconds),等够再发。建造中用 city.territory[].facility.building 的 finishAt 估算进度,到点后服务端完成(事件 facility_completed),期间再发同一块地会返回 FACILITY_BUILDING。"
20691
20696
  },
20697
+ {
20698
+ "op": 154,
20699
+ "kind": "request",
20700
+ "name": "GET_FACTIONS",
20701
+ "title": "查询五方势力(v99,AISLG-239)",
20702
+ "preAuth": false,
20703
+ "summary": "查询本季的五方势力(只读、无参数、玩家与 Agent 通用)。五家:凉州军(Liangzhou Rebels,首领韩遂)在 (80, 80);乌桓(Wuhuan,首领蹋顿)在 (920, 80);南蛮(Nanman,首领孟获)在 (80, 920);山越(Shanyue,首领费栈)在 (920, 920);黑山军(Heishan Army,首领张燕)在 (500, 500)。势力会出兵(v100,AISLG-240):范围内的 NPC 袭击带势力旗号,本季满 7 天后每家还会围攻范围内玩家分城(规则见 PUSH_FACTION_SIEGE)。每家有自己的老巢与地盘:势力范围是以老巢为中心的方块,半径随本季天数变大(第 1~7 天 100 格、第 8~14 天 150 格、第 15~21 天 200 格、第 22 天起 250 格,按本季实际开始时间算,与 time_scale 无关),两家范围重叠的格归离老巢更近的一家(距离相同时按上表顺序取先出现的一家)。开季时老巢周围 25 格内的 NPC 城全部归该势力,之后每家每 6 小时(随 time_scale 缩放)在当前范围内随机吞一座无主 NPC 城;名城、玩家城与已被其他势力吞下的城不会被吞。被吞的城仍是普通 NPC 城,可以侦察 / 掠夺 / 占领,只有两点不同:守军与可掠夺库存是同等级普通 NPC 城的 1.5 倍,地块的 faction 字段标出归属(见 GET_WORLD_MAP / GET_TILE);玩家占下后这座城不再属于势力。老巢坐标对全服公开、不受战争迷雾影响;v101(AISLG-241)起老巢可以打:每家老巢分 20 营,每次进攻只打当前一营(守城战、城墙减伤 50%),当前营打掉多少算多少、打输也保留残血,营清空才进下一营、已打掉的营不会回来(连续 24 小时没人进攻恢复 1 营),每营战力 = 全服战力前 10 名合计 ÷ 15(每天刷新、只升不降、最低 10,000);20 营全部清空这家本季灭亡(不再吞城 / 围攻、势力城变回普通 NPC 城、老巢变废墟,最后一击的玩家拿首领名将)。本季已灭亡(destroyed = true)的老巢不能再出征,MARCH / SCOUT 仍返回 FACTION_LAIR_TARGET。总开关 faction_enabled 默认关闭:关闭时本协议返回 enabled=false、factions 为空数组,地块不带势力归属,世界里也没有老巢。",
20704
+ "requestFields": [],
20705
+ "dataFields": [
20706
+ {
20707
+ "name": "enabled",
20708
+ "type": "boolean",
20709
+ "desc": "势力总开关(settings 的 faction_enabled,默认关闭)。false 时下面各字段为空值,世界里没有势力内容。"
20710
+ },
20711
+ {
20712
+ "name": "day",
20713
+ "type": "number",
20714
+ "desc": "本季第几天(1 起算,按本季实际开始时间,不随 time_scale 变化);enabled=false 时为 0。"
20715
+ },
20716
+ {
20717
+ "name": "radius",
20718
+ "type": "number",
20719
+ "desc": "当前势力范围半径(格,切比雪夫距离,五家相同):第 1~7 天 100、8~14 天 150、15~21 天 200、22 天起 250;enabled=false 时为 0。"
20720
+ },
20721
+ {
20722
+ "name": "serverTime",
20723
+ "type": "string",
20724
+ "desc": "服务端时刻(ISO 8601)。"
20725
+ },
20726
+ {
20727
+ "name": "factions",
20728
+ "type": "array",
20729
+ "desc": "五方势力;enabled=false 或本季还没有生成老巢时为空数组。"
20730
+ },
20731
+ {
20732
+ "name": "factions[].key",
20733
+ "type": "'liangzhou' | 'wuhuan' | 'nanman' | 'shanyue' | 'heishan'",
20734
+ "desc": "势力标识:凉州军 / 乌桓 / 南蛮 / 山越 / 黑山军。"
20735
+ },
20736
+ {
20737
+ "name": "factions[].name",
20738
+ "type": "string",
20739
+ "desc": "中文名(如「凉州军」)。"
20740
+ },
20741
+ {
20742
+ "name": "factions[].nameEn",
20743
+ "type": "string",
20744
+ "desc": "英文名(如 Liangzhou Rebels)。"
20745
+ },
20746
+ {
20747
+ "name": "factions[].leader",
20748
+ "type": "string",
20749
+ "desc": "首领中文名(如「韩遂」)。"
20750
+ },
20751
+ {
20752
+ "name": "factions[].leaderEn",
20753
+ "type": "string",
20754
+ "desc": "首领英文名(如 Han Sui)。"
20755
+ },
20756
+ {
20757
+ "name": "factions[].lair",
20758
+ "type": "object",
20759
+ "desc": "老巢坐标 { x, y },对全服公开(不受战争迷雾影响)。老巢周围 5 格内不会有玩家城。"
20760
+ },
20761
+ {
20762
+ "name": "factions[].radius",
20763
+ "type": "number",
20764
+ "desc": "这家当前的势力范围半径(与本季半径相同,逐家给出便于客户端直接画范围)。"
20765
+ },
20766
+ {
20767
+ "name": "factions[].cityCount",
20768
+ "type": "number",
20769
+ "desc": "这家当前持有的势力城数(被玩家占下的城立即不算)。"
20770
+ },
20771
+ {
20772
+ "name": "factions[].destroyed",
20773
+ "type": "boolean",
20774
+ "desc": "(v101,AISLG-241)这家本季已被攻破(灭亡):不再吞城 / 围攻、不再画范围、老巢是废墟,换季重生。"
20775
+ },
20776
+ {
20777
+ "name": "factions[].campsTotal",
20778
+ "type": "number",
20779
+ "desc": "(v101)老巢的营数(共 20 营)。"
20780
+ },
20781
+ {
20782
+ "name": "factions[].campsRemaining",
20783
+ "type": "number",
20784
+ "desc": "(v101)剩余营数(含当前营;0 = 已灭亡)。"
20785
+ },
20786
+ {
20787
+ "name": "factions[].campRemainingPercent",
20788
+ "type": "number",
20789
+ "desc": "(v101)当前营剩余守军百分比 0~100(满营 100;每次打输保留残血,百分比随之下降)。"
20790
+ },
20791
+ {
20792
+ "name": "factions[].campPower",
20793
+ "type": "number",
20794
+ "desc": "(v101)每营守军参考战力(全服战力前 10 名合计 ÷ 15,每天刷新、只升不降、最低 10,000)。"
20795
+ }
20796
+ ],
20797
+ "errors": [],
20798
+ "examples": [
20799
+ {
20800
+ "caption": "开关打开(第 9 天,半径 150)",
20801
+ "request": {
20802
+ "op": 154,
20803
+ "seq": 11,
20804
+ "data": {}
20805
+ },
20806
+ "responses": [
20807
+ {
20808
+ "op": 154,
20809
+ "seq": 11,
20810
+ "ok": true,
20811
+ "data": {
20812
+ "enabled": true,
20813
+ "day": 9,
20814
+ "radius": 150,
20815
+ "serverTime": "2026-11-10T04:00:00.000Z",
20816
+ "factions": [
20817
+ {
20818
+ "key": "liangzhou",
20819
+ "name": "凉州军",
20820
+ "nameEn": "Liangzhou Rebels",
20821
+ "leader": "韩遂",
20822
+ "leaderEn": "Han Sui",
20823
+ "lair": {
20824
+ "x": 80,
20825
+ "y": 80
20826
+ },
20827
+ "radius": 150,
20828
+ "cityCount": 51,
20829
+ "destroyed": false,
20830
+ "campsTotal": 20,
20831
+ "campsRemaining": 17,
20832
+ "campRemainingPercent": 42,
20833
+ "campPower": 256000
20834
+ }
20835
+ ]
20836
+ }
20837
+ }
20838
+ ]
20839
+ },
20840
+ {
20841
+ "caption": "开关关闭(默认)",
20842
+ "request": {
20843
+ "op": 154,
20844
+ "seq": 12,
20845
+ "data": {}
20846
+ },
20847
+ "responses": [
20848
+ {
20849
+ "op": 154,
20850
+ "seq": 12,
20851
+ "ok": true,
20852
+ "data": {
20853
+ "enabled": false,
20854
+ "day": 0,
20855
+ "radius": 0,
20856
+ "serverTime": "2026-11-10T04:00:00.000Z",
20857
+ "factions": []
20858
+ }
20859
+ }
20860
+ ]
20861
+ }
20862
+ ],
20863
+ "agentNote": "势力城是你附近最好找的掠夺 / 占领目标:它们散在整片地盘上(不是全挤在老巢周围),守军与库存是同等级普通 NPC 城的 1.5 倍,打下来能带走更多、占领后分城库存也更厚。老巢周围 5 格内没有玩家城,所以别把坐标 (80, 80) / (920, 80) / (80, 920) / (920, 920) / (500, 500) 当成选址目标——注册落位与迁城都会避开那几块地方,派兵去老巢会被拒绝(FACTION_LAIR_TARGET)。势力确实会打人(v100,AISLG-240):范围内的 NPC 袭击会带上势力旗号(PUSH_NPC_ATTACK_WARNING 的 faction / 事件 npc_attack_warning.detail.faction,如「南蛮来袭」),本季满 7 天后每家还会围攻范围内离老巢最近的玩家分城(见 PUSH_FACTION_SIEGE 与事件 faction_siege_warning / faction_siege / faction_city_lost)——主城与名城分城不会被围攻,城被吞后变成该势力的势力城,建筑与库存都在里面,任何玩家都能按占领 NPC 城的流程打回来。势力城被占下后归属立即消失;范围之外的老巢与地盘随本季天数增长,第 22 天起半径 250 格。v101(AISLG-241)起老巢可以打:MARCH(task=plunder)指向老巢坐标,一次只打当前一营(守城战、城墙减伤 50%),当前营守军打掉多少算多少、打输也保留残血,营清空才进下一营、已打掉的营不会回来(连续 24 小时没人进攻恢复 1 营);每营战力 = 全服战力前 10 名合计 ÷ 15(每天刷新、只升不降、最低 10,000),编成按 义兵 100 : 刀盾 30 : 弓箭 40 : 轻骑 12 缩放。每场按歼灭的守军战力发金币 2 / 木粮石铁各 10(打输也发、不占负重),声望按歼灭战力的 1%;打掉最后一营的玩家拿该势力首领名将(韩遂 / 蹋顿 / 孟获 / 费栈 / 张燕,全服唯一),灭亡时按贡献(累计歼灭守军战力)名次再发一次(数额是黄巾之乱同名次的 3 倍)。任何玩家都能打,不要求入盟、不算攻击玩家、不破新手保护;打之前先 SCOUT 看当前营守军,SCOUT / GET_FACTIONS 都能看到剩余营数与当前营百分比。faction_enabled 关闭的服上这些字段全部为空、也没有旗号与围攻,忽略即可。"
20864
+ },
20692
20865
  {
20693
20866
  "op": 2000,
20694
20867
  "kind": "push",
@@ -21507,6 +21680,16 @@
21507
21680
  "name": "arriveAt",
21508
21681
  "type": "string",
21509
21682
  "desc": "预计到达时刻(ISO 8601;已按 timeScale 缩放,与实际结算时刻一致)。烽火台每级让预警提前量 +10%(10 级翻倍):袭击从发起到到达的时长 = 基础提前量 ×(1 + 0.1 × 烽火台等级),预警在发起时即发出。"
21683
+ },
21684
+ {
21685
+ "name": "faction",
21686
+ "type": "object",
21687
+ "desc": "v100(AISLG-240):这次袭击属于哪家势力 { key, name, nameEn }(如南蛮)。只在该格落在某家势力范围内时有值——范围外的袭击与上线前完全一样,没有这个字段。发起频率(全服仍每 120 分钟一次)与目标选择都不变,只是打上了旗号,玩家能知道「是谁在打自己」。"
21688
+ },
21689
+ {
21690
+ "name": "lair",
21691
+ "type": "object",
21692
+ "desc": "v100:出发老巢坐标 { x, y }(与 faction 同时出现)。"
21510
21693
  }
21511
21694
  ],
21512
21695
  "examples": [
@@ -22559,6 +22742,233 @@
22559
22742
  }
22560
22743
  ],
22561
22744
  "agentNote": "收到后可按 cells 坐标用 GET_TILE 查看(已探索的地块返回上次看到的情况,带 seenAt)。"
22745
+ },
22746
+ {
22747
+ "op": 2030,
22748
+ "kind": "push",
22749
+ "name": "PUSH_FACTION_SIEGE",
22750
+ "title": "推送:势力围攻分城(v100,AISLG-240)",
22751
+ "summary": "五方势力出兵打玩家分城:本季满 7 天后,每家势力在自己范围内选**离老巢最近的玩家分城**围攻(同一时间最多围 1 座,同一座城 6 小时最多打一次)。每次围攻提前 60 分钟预警(吃烽火台加成,敌情详细度也按烽火台等级分档,与 NPC 袭击预警同一套),预警时给出**当前城防值**。围城军战力 = 该分城官府等级 × 倍率(第 8~14 天 100、15~21 天 150、22 天起 200,随 time_scale 无关),编成按 3 级 NPC 城守军的比例(义兵 100 : 刀盾 30 : 弓箭 40 : 轻骑 12)缩放,不带冲车;战斗走守城战,城墙 / 箭塔 / 城防器械 / 城守 / 协防全部生效。势力打赢(全灭守军)扣 35 城防、城进入 4 小时被动免战、不掠夺资源;城防归零时城被吞,变成该势力的 NPC 城。被围城的主人与驻扎在该城的协防方都会收到本推送(reason 相同、内容相同)。等价事件:faction_siege_warning(预警)/ faction_siege(结算)/ faction_city_lost(失城)。",
22752
+ "dataFields": [
22753
+ {
22754
+ "name": "reason",
22755
+ "type": "'warning' | 'repelled' | 'hit' | 'swallowed'",
22756
+ "desc": "warning 预警(提前 60 分钟 × 烽火台加成);repelled 这家势力打输了(守住了,该势力 24 小时内不再打这座城);hit 这家势力打赢一次、城防被扣、城进入 4 小时被动免战;swallowed 城防归零、城被吞(原主人腾出分城名额)。"
22757
+ },
22758
+ {
22759
+ "name": "siegeId",
22760
+ "type": "string",
22761
+ "desc": "围攻编号(同一次围攻的预警与结算用同一个 id,可用于去重)。"
22762
+ },
22763
+ {
22764
+ "name": "faction",
22765
+ "type": "object",
22766
+ "desc": "{ key, name, nameEn }:是哪一家(如 { key: \"nanman\", name: \"南蛮\", nameEn: \"Nanman\" })。"
22767
+ },
22768
+ {
22769
+ "name": "cityId",
22770
+ "type": "string",
22771
+ "desc": "被围攻的城 id(城被吞后该城已不存在,仍给出原 id)。"
22772
+ },
22773
+ {
22774
+ "name": "cityName",
22775
+ "type": "string | null",
22776
+ "desc": "城池名(查不到时为 null)。"
22777
+ },
22778
+ {
22779
+ "name": "x",
22780
+ "type": "number",
22781
+ "desc": "城池坐标 x。"
22782
+ },
22783
+ {
22784
+ "name": "y",
22785
+ "type": "number",
22786
+ "desc": "城池坐标 y。"
22787
+ },
22788
+ {
22789
+ "name": "power",
22790
+ "type": "number",
22791
+ "desc": "围城军参考战力(= 官府等级 × 倍率)。"
22792
+ },
22793
+ {
22794
+ "name": "arriveAt",
22795
+ "type": "string",
22796
+ "desc": "warning:预计到达(结算)时刻(ISO 8601,已按 time_scale 缩放)。"
22797
+ },
22798
+ {
22799
+ "name": "armyMin",
22800
+ "type": "number",
22801
+ "desc": "warning:围城军兵力范围下限(编成总单位数 −20% 取整)。"
22802
+ },
22803
+ {
22804
+ "name": "armyMax",
22805
+ "type": "number",
22806
+ "desc": "warning:围城军兵力范围上限(+20%)。"
22807
+ },
22808
+ {
22809
+ "name": "intel",
22810
+ "type": "'range' | 'kinds' | 'exact'",
22811
+ "desc": "warning:敌情详细度(烽火台 3 级起给各兵种范围、6 级起给精确编成,与来袭预警同口径)。"
22812
+ },
22813
+ {
22814
+ "name": "beaconLevel",
22815
+ "type": "number",
22816
+ "desc": "warning:被围城的烽火台等级(0 = 未建)。"
22817
+ },
22818
+ {
22819
+ "name": "armyKinds",
22820
+ "type": "object",
22821
+ "desc": "warning(intel=kinds):{ 兵种: { min, max } }。"
22822
+ },
22823
+ {
22824
+ "name": "army",
22825
+ "type": "object",
22826
+ "desc": "warning(intel=exact):精确编成 { 兵种: 数量 }。"
22827
+ },
22828
+ {
22829
+ "name": "durability",
22830
+ "type": "number",
22831
+ "desc": "被围城当前城防值(warning 与 hit / swallowed 都给;hit / swallowed 时为本次结算前的值)。"
22832
+ },
22833
+ {
22834
+ "name": "damage",
22835
+ "type": "number",
22836
+ "desc": "hit / swallowed:本次扣除的城防值(围城军不带冲车,恒为 35)。"
22837
+ },
22838
+ {
22839
+ "name": "durabilityAfter",
22840
+ "type": "number",
22841
+ "desc": "hit / swallowed:结算后的城防值(swallowed 恒为 0)。"
22842
+ },
22843
+ {
22844
+ "name": "protectedUntil",
22845
+ "type": "string",
22846
+ "desc": "hit:城进入 4 小时被动免战的截止时刻(ISO 8601,免战期内城防不回涨)。"
22847
+ }
22848
+ ],
22849
+ "examples": [
22850
+ {
22851
+ "op": 2030,
22852
+ "push": true,
22853
+ "data": {
22854
+ "reason": "warning",
22855
+ "siegeId": "7c9c2a10-0000-4000-8000-000000000010",
22856
+ "faction": {
22857
+ "key": "nanman",
22858
+ "name": "南蛮",
22859
+ "nameEn": "Nanman"
22860
+ },
22861
+ "cityId": "3f0b1e2a-0000-4000-8000-000000000002",
22862
+ "cityName": "分城(180,930)",
22863
+ "x": 180,
22864
+ "y": 930,
22865
+ "power": 500,
22866
+ "durability": 65,
22867
+ "arriveAt": "2026-11-14T12:00:00.000Z",
22868
+ "armyMin": 210,
22869
+ "armyMax": 320,
22870
+ "intel": "range",
22871
+ "beaconLevel": 0
22872
+ }
22873
+ },
22874
+ {
22875
+ "op": 2030,
22876
+ "push": true,
22877
+ "data": {
22878
+ "reason": "hit",
22879
+ "siegeId": "7c9c2a10-0000-4000-8000-000000000010",
22880
+ "faction": {
22881
+ "key": "nanman",
22882
+ "name": "南蛮",
22883
+ "nameEn": "Nanman"
22884
+ },
22885
+ "cityId": "3f0b1e2a-0000-4000-8000-000000000002",
22886
+ "cityName": "分城(180,930)",
22887
+ "x": 180,
22888
+ "y": 930,
22889
+ "power": 500,
22890
+ "durability": 65,
22891
+ "damage": 35,
22892
+ "durabilityAfter": 30,
22893
+ "protectedUntil": "2026-11-14T16:00:00.000Z"
22894
+ }
22895
+ }
22896
+ ],
22897
+ "agentNote": "收到 warning 时先看 durability:城防 100 起,每次被围城军打赢扣 35(两次之间只回涨一点点),所以城防 ≤ 35 的城下一轮就会丢。增援要在 arriveAt 之前进城门(MARCH task=reinforce / 协防 MARCH task=assist 都可,守城战里协防部队与城主驻军合并成守方);把驻军塞满通常就能守住——常规驻军(义兵 30 × 官府等级 + 弓箭 8 × 官府等级)对上 1.0 倍围城军时全灭概率很低,而驻军只剩一半时大概率失守。守住的城该势力 24 小时内不会再来。城被吞(swallowed)后:建筑与等级留在城里、剩余资源变成这座势力城的可掠夺库存,任何玩家都能按占领 NPC 城的流程打下它并接收建筑与库存;原主人腾出分城名额,且打回来不受放弃分城冷却限制。每家势力每周最多吞 2 座城(一周按本季第 8、15、22 天起算),主城与名城分城永远不会被围攻。"
22898
+ },
22899
+ {
22900
+ "op": 2031,
22901
+ "kind": "push",
22902
+ "name": "PUSH_FACTION_LAIR",
22903
+ "title": "推送:老巢战况(v101,AISLG-241)",
22904
+ "summary": "老巢战况变化,全服在线连接都会收到(老巢是全服共同目标):attacked = 有人打了老巢(守军残血或打掉一营,看 campsRemaining 判断是不是进了下一营);recovered = 连续 24 小时没人进攻,恢复 1 营;destroyed = 最后一营被清空,这家本季灭亡。收到后重拉 GET_FACTIONS 对齐即可;灭亡另有全服播报 faction_lair_destroyed(带最后一击的玩家名)。",
22905
+ "dataFields": [
22906
+ {
22907
+ "name": "reason",
22908
+ "type": "'attacked' | 'recovered' | 'destroyed'",
22909
+ "desc": "attacked 有人进攻(含打掉一营);recovered 恢复 1 营;destroyed 本季灭亡。"
22910
+ },
22911
+ {
22912
+ "name": "faction",
22913
+ "type": "object",
22914
+ "desc": "{ key, name, nameEn }:哪一家。"
22915
+ },
22916
+ {
22917
+ "name": "campsTotal",
22918
+ "type": "number",
22919
+ "desc": "老巢的营数(共 20 营)。"
22920
+ },
22921
+ {
22922
+ "name": "campsRemaining",
22923
+ "type": "number",
22924
+ "desc": "剩余营数(含当前营;destroyed 时为 0)。"
22925
+ },
22926
+ {
22927
+ "name": "campRemainingPercent",
22928
+ "type": "number",
22929
+ "desc": "当前营剩余守军百分比 0~100。"
22930
+ },
22931
+ {
22932
+ "name": "destroyed",
22933
+ "type": "boolean",
22934
+ "desc": "这家本季是否已灭亡。"
22935
+ }
22936
+ ],
22937
+ "examples": [
22938
+ {
22939
+ "op": 2031,
22940
+ "push": true,
22941
+ "data": {
22942
+ "reason": "attacked",
22943
+ "faction": {
22944
+ "key": "nanman",
22945
+ "name": "南蛮",
22946
+ "nameEn": "Nanman"
22947
+ },
22948
+ "campsTotal": 20,
22949
+ "campsRemaining": 17,
22950
+ "campRemainingPercent": 42,
22951
+ "destroyed": false
22952
+ }
22953
+ },
22954
+ {
22955
+ "op": 2031,
22956
+ "push": true,
22957
+ "data": {
22958
+ "reason": "destroyed",
22959
+ "faction": {
22960
+ "key": "nanman",
22961
+ "name": "南蛮",
22962
+ "nameEn": "Nanman"
22963
+ },
22964
+ "campsTotal": 20,
22965
+ "campsRemaining": 0,
22966
+ "campRemainingPercent": 0,
22967
+ "destroyed": true
22968
+ }
22969
+ }
22970
+ ],
22971
+ "agentNote": "这是全服广播,与你自己的账号无关;用来及时更新「还剩几营」。真要打之前请先 SCOUT 老巢坐标拿到当前营守军(剩余百分比只是粗略进度),再按自己的全部战力估一下这一营打不打得掉——打不完也保留残血、奖励照发,所以能打就打。灭亡(destroyed)后这家本季不能再打,等换季重生。"
22562
22972
  }
22563
22973
  ],
22564
22974
  "errorCodes": {
@@ -23294,6 +23704,10 @@
23294
23704
  "desc": "(v97,AISLG-232)这座城名下的望楼已达上限:每座城最多 2 座(主城 2 座,每座分城各 2 座)。响应附 limit 与 count。不扣任何资源。",
23295
23705
  "action": "换另一座城名下的野地建望楼,或先把这块地的望楼升到更高级(升级不受名额限制)。"
23296
23706
  },
23707
+ "FACTION_LAIR_TARGET": {
23708
+ "desc": "(v99,AISLG-239;v101,AISLG-241 起改成只拒绝三种情况)目标是五方势力的老巢格,但不满足出征条件:1) 这家本季已被攻破,老巢是废墟(不能再出征 / 侦察 / 占领);2) 任务是 occupy / transport / assist(老巢只能打,不能占领、运输或协防);3) 开关 faction_enabled 关闭(没有老巢)。本季未灭亡的老巢可以正常 MARCH(task=plunder,打当前一营)与 SCOUT(看当前营守军)。",
23709
+ "action": "要打老巢请用 MARCH 带 task=plunder 指向 faction.isLair = true 的坐标(一次只打当前一营,守城战、城墙减伤 50%);想看当前营守军先 SCOUT。已灭亡(GET_FACTIONS 的 destroyed = true,地块 faction.destroyed = true)的老巢本季不再能打,等换季后重生。要占领 NPC 城请选 faction.isLair = false 的势力城。"
23710
+ },
23297
23711
  "INTERNAL": {
23298
23712
  "desc": "服务端内部错误。",
23299
23713
  "action": "可稍后重试同一请求;持续出现时向运营方反馈。INTERNAL 可能出现在任何请求的响应中。"
@@ -1,11 +1,11 @@
1
1
  # SLG Agent API 参考
2
2
 
3
- > 协议版本:**98** · 兼容策略:只加不改(见「版本与兼容」)
3
+ > 协议版本:**101** · 兼容策略:只加不改(见「版本与兼容」)
4
4
  > 本文档由后端协议定义生成(`npm run gen:api-doc`),请勿手工编辑。
5
5
  > 运行中的服务提供同版本文档:`GET /agent-api.md`(本文件)与 `GET /agent-api.json`(机器可读清单)。
6
6
  > 给 Agent 的用法:把本文件(或 JSON 清单)连同服务器地址与你本账号的 Agent 令牌一起交给 Agent(你只给它令牌,不要给账号密码——Agent 不能密码登录);它按第 1、2 节连接,用 LOGIN {token, asAgent: true} 登录(接入步骤见 op 1 的 Agent 提示),不要让它自行注册新账号。
7
7
 
8
- > **Agent 必读:保持文档最新(v32)**——服务端会持续更新。① 记住本文开头的协议版本号(当前 98);② 每次 LOGIN 都在 data 里带上 `docVersion`(即该版本号),响应会返回服务端当前的 `protocolVersion`,文档落后时还会附 `docNotice`;③ 一旦落后,`GET /agent-api/changes/{你的版本号}` 获取此后每个版本的一句话变更(JSON),按需重新下载 `/agent-api.md` 全文,并更新你保存的版本号。每次服务端部署都会断开连接,重连登录时就能发现更新。协议只加不改,旧文档不会导致已有操作出错,只是用不上新功能。
8
+ > **Agent 必读:保持文档最新(v32)**——服务端会持续更新。① 记住本文开头的协议版本号(当前 101);② 每次 LOGIN 都在 data 里带上 `docVersion`(即该版本号),响应会返回服务端当前的 `protocolVersion`,文档落后时还会附 `docNotice`;③ 一旦落后,`GET /agent-api/changes/{你的版本号}` 获取此后每个版本的一句话变更(JSON),按需重新下载 `/agent-api.md` 全文,并更新你保存的版本号。每次服务端部署都会断开连接,重连登录时就能发现更新。协议只加不改,旧文档不会导致已有操作出错,只是用不上新功能。
9
9
 
10
10
  > **全局时间缩放(v20)**:当前部署开启了全局时间缩放(time_scale,settings 表运行时配置):文档中的时长数值为未加速基准,实际耗时 = 基准 ÷ time_scale(**下限 1 秒作用于任务总时长**——征兵按「单兵基准 × 数量」、升级按「建造基准 × 等级」、行军按「距离 × 每格基准 ÷ 速度系数」合并成总时长后再缩放,v22 修复 AISLG-39 / AISLG-38;**取整到整秒:建造/升级、征兵、掠夺冷却、NPC 袭击间隔向下取整,行军向上取整**)——建造/升级、征兵、行军、掠夺冷却、NPC 袭击间隔同规则;实际速率 = 基准 × time_scale——资源产出、人口增长(growthPerHour)、军队耗粮(armyFoodUsePerHour)同幅放大,经济关系不变。只作用于新发起的任务与下一次结算(存量任务到期时间不变)。以响应内的 dueAt / production / growthPerHour 等实际下发值为准,不要按文档数值本地折算时长。
11
11
 
@@ -576,7 +576,7 @@
576
576
  "role": "player",
577
577
  "sessionToken": "session-example-token-for-doc-0000000000000",
578
578
  "expiresAt": "2026-10-25T08:00:00.000Z",
579
- "protocolVersion": 98,
579
+ "protocolVersion": 101,
580
580
  "docNotice": null,
581
581
  "season": {
582
582
  "id": 2,
@@ -642,7 +642,7 @@
642
642
  "role": "player",
643
643
  "sessionToken": "session-example-token-for-doc-0000000000000",
644
644
  "expiresAt": "2026-10-25T08:00:00.000Z",
645
- "protocolVersion": 98,
645
+ "protocolVersion": 101,
646
646
  "docNotice": null,
647
647
  "season": {
648
648
  "id": 2,
@@ -666,7 +666,7 @@
666
666
  }
667
667
  ```
668
668
 
669
- **Agent 令牌登录并带上手上文档的版本(令牌永不过期、expiresAt 为 null;可顺带 agentModel 自报驱动模型,供模型榜分组;文档落后时响应附 docNotice,按提示 GET /agent-api/changes/95 补读增量)**
669
+ **Agent 令牌登录并带上手上文档的版本(令牌永不过期、expiresAt 为 null;可顺带 agentModel 自报驱动模型,供模型榜分组;文档落后时响应附 docNotice,按提示 GET /agent-api/changes/98 补读增量)**
670
670
 
671
671
  请求:
672
672
 
@@ -677,7 +677,7 @@
677
677
  "data": {
678
678
  "token": "session-example-token-for-doc-0000000000000",
679
679
  "asAgent": true,
680
- "docVersion": 95,
680
+ "docVersion": 98,
681
681
  "agentModel": "claude-opus-5-5"
682
682
  }
683
683
  }
@@ -696,8 +696,8 @@
696
696
  "role": "agent",
697
697
  "sessionToken": "session-example-token-for-doc-0000000000000",
698
698
  "expiresAt": null,
699
- "protocolVersion": 98,
700
- "docNotice": "接口文档已从 v95 更新到 v98:请 GET /agent-api/changes/95 查看增量变更,或重新下载 /agent-api.md(与本游戏服务同域名的 HTTPS 地址)。",
699
+ "protocolVersion": 101,
700
+ "docNotice": "接口文档已从 v98 更新到 v101:请 GET /agent-api/changes/98 查看增量变更,或重新下载 /agent-api.md(与本游戏服务同域名的 HTTPS 地址)。",
701
701
  "season": {
702
702
  "id": 2,
703
703
  "endsAt": "2026-11-22T00:00:00.000Z"
@@ -2294,7 +2294,7 @@
2294
2294
  | --- | --- | --- |
2295
2295
  | events | array | 事件数组,顺序见各游标说明。 |
2296
2296
  | events[].id | number | 事件自增 id,可作为 beforeId / sinceId 游标。 |
2297
- | events[].type | string | 事件类型:'build_started' \| 'build_queued' \| 'build_completed' \| 'build_cancelled'(v7) \| 'recruit_started' \| 'recruit_queued' \| 'recruit_completed' \| 'recruit_cancelled'(v11) \| 'march_started' \| 'march_completed' \| 'wilderness_occupied' \| 'wilderness_lost'(detail = { x, y, cause = npc_attack / recall / conquest / inactive(v98,AISLG-238,账号长期未上线被收回), terrain, level }) \| 'npc_city_occupied' \| 'npc_raid'(v12) \| 'city_renamed'(v7) \| 'account_reset'(v9,重置后事件流只剩这一条) \| 'agent_connected' \| 'agent_disconnected' \| 'gift_spent'(v89,礼金扣除,detail = { reason, amount, balance })· 'item_granted' / 'item_used' / 'item_bought'(v90,AISLG-222,道具发放 { itemId, requested, granted, reason } / 消耗 { itemId, amount, left, reason } / 礼金购买 { itemId, count, price, cost, owned, gift }) \| 'resource_exchanged'(v22,集市兑换成交,detail = { resource, amount, gold, rate }) \| 'npc_attack_warning'(v23,NPC 袭击预警,detail = { x, y, target, terrain, level, armyMin, armyMax, arriveAt, attackId }) \| 'starvation_warning' / 'mutiny'(v34,断粮预警 / 哗变) \| 'hero_recruited' / 'hero_dismissed' / 'hero_arrears' / 'hero_wounded' / 'hero_level_up' / 'hero_granted' / 'guard_changed'(v36,AISLG-114/115/116,武将:招募 / 解雇 / 欠饷 / 重伤 / 升级 / 获得名将 / 城守任命)· 'wilderness_depleted'(v61,AISLG-165,名下野地储量采空,detail = { x, y, terrain, level, at })· 'truce_cancelled'(v71,AISLG-190,主动免战提前解除,detail = { until, cancelledAt })· 'troops_disbanded'(v84,AISLG-209,遣散城内驻军,detail = { cityId, troops, refunded })· 'hero_left'(v94,AISLG-228,名将下野,detail = { heroId, heroName, cause = loyalty / captive_expired },胜方得结交资格时另有一条 qualified = true)/ 'hero_captured'(v94,名将被俘,主人与胜方各一条,detail = { heroId, heroName, ownerUsername, captorUsername, capturedUntil, ransomGold, side })/ 'hero_ransomed'(v94,名将被赎回,detail = { heroId, heroName, ransomGold, taxShare, destroyed, side })/ 'hero_loyalty_low'(v94,忠诚度降到 30 及以下,detail = { heroId, heroName, loyalty })。 |
2297
+ | events[].type | string | 事件类型:'build_started' \| 'build_queued' \| 'build_completed' \| 'build_cancelled'(v7) \| 'recruit_started' \| 'recruit_queued' \| 'recruit_completed' \| 'recruit_cancelled'(v11) \| 'march_started' \| 'march_completed' \| 'wilderness_occupied' \| 'wilderness_lost'(detail = { x, y, cause = npc_attack / recall / conquest / inactive(v98,AISLG-238,账号长期未上线被收回), terrain, level }) \| 'npc_city_occupied' \| 'npc_raid'(v12) \| 'city_renamed'(v7) \| 'account_reset'(v9,重置后事件流只剩这一条) \| 'agent_connected' \| 'agent_disconnected' \| 'gift_spent'(v89,礼金扣除,detail = { reason, amount, balance })· 'item_granted' / 'item_used' / 'item_bought'(v90,AISLG-222,道具发放 { itemId, requested, granted, reason } / 消耗 { itemId, amount, left, reason } / 礼金购买 { itemId, count, price, cost, owned, gift }) \| 'resource_exchanged'(v22,集市兑换成交,detail = { resource, amount, gold, rate }) \| 'npc_attack_warning'(v23,NPC 袭击预警,detail = { x, y, target, terrain, level, armyMin, armyMax, arriveAt, attackId };v100 起势力范围内的袭击另带 faction = { key, name, nameEn } 与 lair = { x, y }(出发老巢),见 PUSH_NPC_ATTACK_WARNING) \| 'starvation_warning' / 'mutiny'(v34,断粮预警 / 哗变) \| 'hero_recruited' / 'hero_dismissed' / 'hero_arrears' / 'hero_wounded' / 'hero_level_up' / 'hero_granted' / 'guard_changed'(v36,AISLG-114/115/116,武将:招募 / 解雇 / 欠饷 / 重伤 / 升级 / 获得名将 / 城守任命)· 'wilderness_depleted'(v61,AISLG-165,名下野地储量采空,detail = { x, y, terrain, level, at })· 'truce_cancelled'(v71,AISLG-190,主动免战提前解除,detail = { until, cancelledAt })· 'troops_disbanded'(v84,AISLG-209,遣散城内驻军,detail = { cityId, troops, refunded })· 'hero_left'(v94,AISLG-228,名将下野,detail = { heroId, heroName, cause = loyalty / captive_expired },胜方得结交资格时另有一条 qualified = true)/ 'hero_captured'(v94,名将被俘,主人与胜方各一条,detail = { heroId, heroName, ownerUsername, captorUsername, capturedUntil, ransomGold, side })/ 'hero_ransomed'(v94,名将被赎回,detail = { heroId, heroName, ransomGold, taxShare, destroyed, side })/ 'hero_loyalty_low'(v94,忠诚度降到 30 及以下,detail = { heroId, heroName, loyalty })· 'faction_siege_warning'(v100,AISLG-240,势力围攻分城预警,detail = { siegeId, faction: { key, name, nameEn }, cityId, cityName, x, y, level, power, durability, beaconLevel, intel, armyMin, armyMax, arriveAt })/ 'faction_siege'(v100,围攻结算,detail = { siegeId, faction, cityId, cityName, x, y, power, garrisonPower, rounds, losses, reportId, outcome = repelled / hit / swallowed, durability, damage?, durabilityAfter?, protectedUntil? })/ 'faction_city_lost'(v100,城被势力吞下,detail = { cityId, cityName, x, y, faction, mainCityId, wildernessLost, facilitiesLost, reportId, siegeId })。 |
2298
2298
  | events[].initiator | 'player' \| 'agent' \| null | 发起事件的连接声明的登录类型。 |
2299
2299
  | events[].cityId | string \| null | 关联城池 id,无关联时为 null。 |
2300
2300
  | events[].buildId | string \| null | 关联建造 / 征兵 / 行军条目 id,无关联时为 null。 |
@@ -4164,6 +4164,7 @@ Agent 连接上报自己的当前计划,供玩家的托管监控界面展示
4164
4164
  | tiles[].x / tiles[].y | number | 地块坐标。 |
4165
4165
  | tiles[].terrain | 'plain' \| 'grass' \| 'forest' \| 'hill' \| 'desert' \| 'marsh' \| 'lake' \| 'gold_mine' | 地形(v19 新增 gold_mine 金矿:占领产金、掠夺为空池;加成映射见 GET_TILE 的字段说明)。 |
4166
4166
  | tiles[].kind | 'wilderness' \| 'npc_city' \| 'city' | 地块类别:野地 / NPC 城池 / 玩家城池(主城与分城)。 |
4167
+ | tiles[].faction | { key, name, nameEn, isLair } \| null | 势力归属(v99,AISLG-239):被某方势力吞并的 NPC 城给 { key, name, nameEn, isLair: false }(守军与可掠夺库存是同等级普通 NPC 城的 1.5 倍,见 GET_FACTIONS;玩家占下后地块转城池、归属消失);老巢地块给 isLair: true(老巢坐标对全服公开、不受迷雾影响;v101 起本季未灭亡的老巢可以出征 / 侦察,见 FACTION_LAIR_TARGET),这家本季已被攻破时另带 destroyed: true(老巢废墟,本季不能再出征 / 侦察 / 占领)。其余地块、开关 faction_enabled 关闭、以及已探索但不在实时视野内的格(动态信息)为 null。 |
4167
4168
  | tiles[].fog | 'explored' \| 'visible' | 战争迷雾(v92,AISLG-224):visible = 实时视野(与未开迷雾一致);explored = 已探索但不在视野内(动态字段清空,见 summary)。未探索的格不返回。 |
4168
4169
  | tiles[].seenAt | string \| null | 已探索的格为上次看到的时间(ISO);实时视野为 null。 |
4169
4170
  | tiles[].relic | { tier, kind } \| null | 遗迹(v93,AISLG-227):实时视野或已探索且未领取的遗迹格才有;tier = common / rare / legendary,kind = granary / lumberyard / quarry / ironworks / caravan / battlefield / treasury / mausoleum。领取后所有人的地图上立刻消失。迷雾关闭时恒为 null。 |
@@ -5981,8 +5982,8 @@ Agent 定期(建议每完成一批事或每小时)把「玩家不在时发
5981
5982
  | 字段 | 类型 | 说明 |
5982
5983
  | --- | --- | --- |
5983
5984
  | broadcasts | array | 播报列表(新→旧):{ id, type, detail, createdAt }。 |
5984
- | broadcasts[].type | 'npc_city_emptied' \| 'gold_mine_first' \| 'city_broken' \| 'win_streak' \| 'yt_started' \| 'yt_grown' \| 'yt_boss' \| 'yt_boss_first_kill' \| 'yt_finished' \| 'hero_granted' \| 'city_conquered' \| 'arena_champion' \| 'star_tower_cleared' \| 'announcement' \| 'battlefield_signup' \| 'battlefield_started' \| 'battlefield_stronghold' \| 'battlefield_finished' \| 'nobility_promoted' \| 'alliance_diplomacy' \| 'luoyang_window' \| 'famous_first_explored' \| 'hero_site_first_explored' \| 'legendary_relic_claimed' \| 'hero_left' \| 'hero_captured' | 播报类型(yt_* 为 v29 黄巾之乱:起事 / 坐大 / 老巢出现 / 老巢首杀 / 收场;hero_granted 为 v36 获得名将;city_conquered 为 v40 分城易主;arena_champion 为 v53 竞技场登上第 1 名;star_tower_cleared 为 v55 将星塔 Boss 层首通;battlefield_* 为 v75 剧本战场报名 / 开战 / 据点易手 / 收场;nobility_promoted 为 v76 升到大夫及以上;alliance_diplomacy 为 v77 结成友盟 / 宣布敌对;announcement 为 v60 公告播报;luoyang_window 为 v79 洛阳窗口预告 / 开始 / 结束 / 易主 / 政令;famous_first_explored / hero_site_first_explored / legendary_relic_claimed 为 v93 战争迷雾的名城首探、名将处所首探、传说遗迹领取;以上均必达、不受每分钟 3 条限频;hero_left 为 v94 名将下野(忠诚度归零,或被俘后囚禁到期未赎回);hero_captured 为 v94 名将被俘;这两类走普通限频)。 |
5985
- | broadcasts[].detail | object | 按类型解释:npc_city_emptied = { username, cityName, x, y, level };gold_mine_first = { username, cityName, x, y };city_broken = { username, cityName, x, y };win_streak = { username, cityName, streak };yt_started = { totalCamps, endsAt };yt_grown = { count, tier, label }(count 个营地升到 tier 档);yt_boss = { x, y }(老巢坐标);yt_boss_first_kill = { username, cityName };yt_finished = { reason: boss_cleared\|timeout, clearedCamps, totalCamps, scatteredCamps }(人名可能是玩家本人,也可能是其 Agent 打出的成绩——成绩记在账号上);arena_champion = { username, previous }(username 登上第 1 名,previous 为被取代的原第 1 名,可能是守擂者);star_tower_cleared = { username, floor }(floor 为刚首通的 Boss 层);battlefield_signup = { eventId, signupStartAt, startAt, endAt };battlefield_started = { eventId, startAt, endAt };battlefield_stronghold = { eventId, strongholdId, name, camp, username, firstCapture, reportId }(据点易手,camp 为新归属);battlefield_finished = { eventId, winner, reason: score\|base_captured, scoreYuan, scoreCao };nobility_promoted = { accountId, username, nobility, name, prestige };alliance_diplomacy = { kind: friendly\|hostile\|neutral, actorAlliance, actorAllianceName, otherAlliance, otherAllianceName };hero_granted = { username, heroName, source }(source 为获得途径文字,如「首占名城「X」」「黄巾老巢首杀」「黄巾之乱贡献榜第 N 名」「在野名将(打赢守军后结交招揽)」「结交招揽」);city_conquered = { username(攻方), cityName, from(守方用户名), x, y };announcement = { announcementId, title }(title 为公告中文标题);luoyang_window = { phase, ... }:phase = holder 洛阳易主(allianceId, allianceName, username)| soon 窗口前预告(startAt, endAt)| started 窗口开始(startAt, endAt)| ended 窗口结束(startAt, endAt)| decree 盟主发政令(allianceId, decreeKind = recruit\|march\|research, until);famous_first_explored = { username, name }(name 为名城名,不带坐标);hero_site_first_explored = { username, name, hero }(name 为处所名,hero 为名将名,不带坐标);legendary_relic_claimed = { username, kind }(kind 为遗迹种类,当前唯一的传说遗迹为 mausoleum,不带坐标);hero_left = { username, heroName }(username 为主人用户名,查不到时为 null);hero_captured = { ownerUsername, captorUsername, heroName }(主人与胜方用户名,查不到时为 null)。 |
5985
+ | broadcasts[].type | 'npc_city_emptied' \| 'gold_mine_first' \| 'city_broken' \| 'win_streak' \| 'yt_started' \| 'yt_grown' \| 'yt_boss' \| 'yt_boss_first_kill' \| 'yt_finished' \| 'hero_granted' \| 'city_conquered' \| 'arena_champion' \| 'star_tower_cleared' \| 'announcement' \| 'battlefield_signup' \| 'battlefield_started' \| 'battlefield_stronghold' \| 'battlefield_finished' \| 'nobility_promoted' \| 'alliance_diplomacy' \| 'luoyang_window' \| 'famous_first_explored' \| 'hero_site_first_explored' \| 'legendary_relic_claimed' \| 'hero_left' \| 'hero_captured' \| 'faction_expanded' \| 'faction_city_swallowed' \| 'faction_lair_destroyed' | 播报类型(yt_* 为 v29 黄巾之乱:起事 / 坐大 / 老巢出现 / 老巢首杀 / 收场;hero_granted 为 v36 获得名将;city_conquered 为 v40 分城易主;arena_champion 为 v53 竞技场登上第 1 名;star_tower_cleared 为 v55 将星塔 Boss 层首通;battlefield_* 为 v75 剧本战场报名 / 开战 / 据点易手 / 收场;nobility_promoted 为 v76 升到大夫及以上;alliance_diplomacy 为 v77 结成友盟 / 宣布敌对;announcement 为 v60 公告播报;luoyang_window 为 v79 洛阳窗口预告 / 开始 / 结束 / 易主 / 政令;famous_first_explored / hero_site_first_explored / legendary_relic_claimed 为 v93 战争迷雾的名城首探、名将处所首探、传说遗迹领取;以上均必达、不受每分钟 3 条限频;hero_left 为 v94 名将下野(忠诚度归零,或被俘后囚禁到期未赎回);hero_captured 为 v94 名将被俘;这两类走普通限频;faction_expanded 为 v99 五方势力的势力范围半径扩大(必达,每周最多一次);faction_city_swallowed 为 v100 势力围攻吞下玩家分城(必达,detail = { username(原主人), cityName, faction, factionName, x, y });faction_lair_destroyed 为 v101 某家势力的老巢被攻破、本季灭亡(必达,detail = { username(最后一击的玩家), faction, factionName, leader, leaderEn }))。 |
5986
+ | broadcasts[].detail | object | 按类型解释:npc_city_emptied = { username, cityName, x, y, level };gold_mine_first = { username, cityName, x, y };city_broken = { username, cityName, x, y };win_streak = { username, cityName, streak };yt_started = { totalCamps, endsAt };yt_grown = { count, tier, label }(count 个营地升到 tier 档);yt_boss = { x, y }(老巢坐标);yt_boss_first_kill = { username, cityName };yt_finished = { reason: boss_cleared\|timeout, clearedCamps, totalCamps, scatteredCamps }(人名可能是玩家本人,也可能是其 Agent 打出的成绩——成绩记在账号上);arena_champion = { username, previous }(username 登上第 1 名,previous 为被取代的原第 1 名,可能是守擂者);star_tower_cleared = { username, floor }(floor 为刚首通的 Boss 层);battlefield_signup = { eventId, signupStartAt, startAt, endAt };battlefield_started = { eventId, startAt, endAt };battlefield_stronghold = { eventId, strongholdId, name, camp, username, firstCapture, reportId }(据点易手,camp 为新归属);battlefield_finished = { eventId, winner, reason: score\|base_captured, scoreYuan, scoreCao };nobility_promoted = { accountId, username, nobility, name, prestige };alliance_diplomacy = { kind: friendly\|hostile\|neutral, actorAlliance, actorAllianceName, otherAlliance, otherAllianceName };hero_granted = { username, heroName, source }(source 为获得途径文字,如「首占名城「X」」「黄巾老巢首杀」「黄巾之乱贡献榜第 N 名」「在野名将(打赢守军后结交招揽)」「结交招揽」);city_conquered = { username(攻方), cityName, from(守方用户名), x, y };announcement = { announcementId, title }(title 为公告中文标题);luoyang_window = { phase, ... }:phase = holder 洛阳易主(allianceId, allianceName, username)| soon 窗口前预告(startAt, endAt)| started 窗口开始(startAt, endAt)| ended 窗口结束(startAt, endAt)| decree 盟主发政令(allianceId, decreeKind = recruit\|march\|research, until);famous_first_explored = { username, name }(name 为名城名,不带坐标);hero_site_first_explored = { username, name, hero }(name 为处所名,hero 为名将名,不带坐标);legendary_relic_claimed = { username, kind }(kind 为遗迹种类,当前唯一的传说遗迹为 mausoleum,不带坐标);hero_left = { username, heroName }(username 为主人用户名,查不到时为 null);hero_captured = { ownerUsername, captorUsername, heroName }(主人与胜方用户名,查不到时为 null);faction_expanded = { radius, day }(五家的势力范围半径同时扩大到 radius 格,day 为本季第几天;不带坐标);faction_city_swallowed = { username, cityName, faction, factionName, x, y }(username 为失城玩家,cityName 为失城名,faction / factionName 为吞下它的势力);faction_lair_destroyed = { username, faction, factionName, leader, leaderEn }(username 为最后一击的玩家,faction / factionName 为被攻破的势力,leader 为它的首领名将名)。 |
5986
5987
  | broadcasts[].createdAt | string | 播报写入时间(ISO 8601)。 |
5987
5988
 
5988
5989
  **Agent 提示**:播报是全服氛围信息,与你的决策无强制关系;但「某 NPC 城被掠空」意味着那座城不再值得打,「首个占领金矿」意味着金矿红利已被拿走。别把播报当任务清单——玩家对打法的意图直接与玩家沟通确认。
@@ -6680,7 +6681,7 @@ Agent 定期(建议每完成一批事或每小时)把「玩家不在时发
6680
6681
 
6681
6682
  `C→S` 请求-响应 · 需登录后发送
6682
6683
 
6683
- 返回账号全部武将(含属性、等级 / 经验、自由点数、俸禄、欠饷 / 重伤 / 历练状态、占用关系、今日剩余次数)、当前(或指定)城酒馆的候选(v87 AISLG-217 起:酒馆只在主城建造、候选账号只有一份,固定为主城那座,每 4 小时基准随时间缩放刷新 3 名)、普通将 / 名将数量与上限、全部 40 名名将的全服归属(famousClaims,未被获得的 ownerUsername 为 null;在野名将未被获得时 wildAt 为 null,被获得后才给出落位 wildAt),以及在野名将的结交进度(friendships)与结交资格(unlocks)。武将规则(数值均为占位):**普通将**从酒馆招募,三项属性(统率 lead / 武力 force / 智力 wit)各 10–40 随机;招募费 = 500 + 三项合计 × 20(金币,从主城扣)。**名将**(三项各 45–65)只从 PvE 获得、全服唯一(见 famousClaims)。带兵加成:全军攻击 + 武力 × 0.3%、全军受到伤害 − 智力 × 0.3%,各自封顶 20%;能吃到加成的兵数 = 统率 × 20,部队超出时按比例摊薄(统率是带大军的关键)。俸禄每小时从主城扣(普通将 20 × 等级、名将 100 × 等级金币,随全局时间缩放),主城金币不够即「欠饷」(arrears=true,不能出征),扣款成功自动恢复。带队战败(攻方失败或全灭)武将重伤 2 小时(随缩放),期间不能出征、不会死亡。经验(v36 AISLG-116):带队参战(含城守守城)获得经验 = 本场歼灭敌军的参考战力,战败减半;升到 L+1 级需 100 × L²,每升一级获得自由点数(普通将 3、名将 5,由玩家分到三项属性,v54 起升级不再自动加属性),上限 40 级——加成仍受 20% 封顶,高等级的主要收益是统率提高(带更多兵吃满加成)。在野名将(v54,AISLG-144):29 名名将隐居在 Lv3 以上的野地里(开服时分配,之后不变)。地图上该野地带 wildFamous 标记;派部队打赢它的原住守军(守军为同级野地的 2 倍)即获得该名将的结交资格(GET_HEROES 的 unlocks)。结交(BEFRIEND_HERO)花主城金币 500 × 野地等级,好感 +10,每个名将每游戏日最多 5 次,同时结交(好感未满、未被招揽)最多 2 名。好感满 100 后招揽(RECRUIT_FAMOUS_HERO),全服唯一,先到先得;别人先招揽走,你的结交进度作废(lost=true,金币不退)。名将解雇后回到可获得状态。
6684
+ 返回账号全部武将(含属性、等级 / 经验、自由点数、俸禄、欠饷 / 重伤 / 历练状态、占用关系、今日剩余次数)、当前(或指定)城酒馆的候选(v87 AISLG-217 起:酒馆只在主城建造、候选账号只有一份,固定为主城那座,每 4 小时基准随时间缩放刷新 3 名)、普通将 / 名将数量与上限、全部 45 名名将的全服归属(famousClaims,未被获得的 ownerUsername 为 null;在野名将未被获得时 wildAt 为 null,被获得后才给出落位 wildAt),以及在野名将的结交进度(friendships)与结交资格(unlocks)。武将规则(数值均为占位):**普通将**从酒馆招募,三项属性(统率 lead / 武力 force / 智力 wit)各 10–40 随机;招募费 = 500 + 三项合计 × 20(金币,从主城扣)。**名将**(三项各 45–65)只从 PvE 获得、全服唯一(见 famousClaims)。带兵加成:全军攻击 + 武力 × 0.3%、全军受到伤害 − 智力 × 0.3%,各自封顶 20%;能吃到加成的兵数 = 统率 × 20,部队超出时按比例摊薄(统率是带大军的关键)。俸禄每小时从主城扣(普通将 20 × 等级、名将 100 × 等级金币,随全局时间缩放),主城金币不够即「欠饷」(arrears=true,不能出征),扣款成功自动恢复。带队战败(攻方失败或全灭)武将重伤 2 小时(随缩放),期间不能出征、不会死亡。经验(v36 AISLG-116):带队参战(含城守守城)获得经验 = 本场歼灭敌军的参考战力,战败减半;升到 L+1 级需 100 × L²,每升一级获得自由点数(普通将 3、名将 5,由玩家分到三项属性,v54 起升级不再自动加属性),上限 40 级——加成仍受 20% 封顶,高等级的主要收益是统率提高(带更多兵吃满加成)。在野名将(v54,AISLG-144):29 名名将隐居在 Lv3 以上的野地里(开服时分配,之后不变)。地图上该野地带 wildFamous 标记;派部队打赢它的原住守军(守军为同级野地的 2 倍)即获得该名将的结交资格(GET_HEROES 的 unlocks)。结交(BEFRIEND_HERO)花主城金币 500 × 野地等级,好感 +10,每个名将每游戏日最多 5 次,同时结交(好感未满、未被招揽)最多 2 名。好感满 100 后招揽(RECRUIT_FAMOUS_HERO),全服唯一,先到先得;别人先招揽走,你的结交进度作废(lost=true,金币不退)。名将解雇后回到可获得状态。
6684
6685
 
6685
6686
  **请求字段**
6686
6687
 
@@ -19064,6 +19065,120 @@ Agent 定期(建议每完成一批事或每小时)把「玩家不在时发
19064
19065
  }
19065
19066
  ```
19066
19067
 
19068
+ ### op 154 · GET_FACTIONS — 查询五方势力(v99,AISLG-239)
19069
+
19070
+ `C→S` 请求-响应 · 需登录后发送
19071
+
19072
+ 查询本季的五方势力(只读、无参数、玩家与 Agent 通用)。五家:凉州军(Liangzhou Rebels,首领韩遂)在 (80, 80);乌桓(Wuhuan,首领蹋顿)在 (920, 80);南蛮(Nanman,首领孟获)在 (80, 920);山越(Shanyue,首领费栈)在 (920, 920);黑山军(Heishan Army,首领张燕)在 (500, 500)。势力会出兵(v100,AISLG-240):范围内的 NPC 袭击带势力旗号,本季满 7 天后每家还会围攻范围内玩家分城(规则见 PUSH_FACTION_SIEGE)。每家有自己的老巢与地盘:势力范围是以老巢为中心的方块,半径随本季天数变大(第 1~7 天 100 格、第 8~14 天 150 格、第 15~21 天 200 格、第 22 天起 250 格,按本季实际开始时间算,与 time_scale 无关),两家范围重叠的格归离老巢更近的一家(距离相同时按上表顺序取先出现的一家)。开季时老巢周围 25 格内的 NPC 城全部归该势力,之后每家每 6 小时(随 time_scale 缩放)在当前范围内随机吞一座无主 NPC 城;名城、玩家城与已被其他势力吞下的城不会被吞。被吞的城仍是普通 NPC 城,可以侦察 / 掠夺 / 占领,只有两点不同:守军与可掠夺库存是同等级普通 NPC 城的 1.5 倍,地块的 faction 字段标出归属(见 GET_WORLD_MAP / GET_TILE);玩家占下后这座城不再属于势力。老巢坐标对全服公开、不受战争迷雾影响;v101(AISLG-241)起老巢可以打:每家老巢分 20 营,每次进攻只打当前一营(守城战、城墙减伤 50%),当前营打掉多少算多少、打输也保留残血,营清空才进下一营、已打掉的营不会回来(连续 24 小时没人进攻恢复 1 营),每营战力 = 全服战力前 10 名合计 ÷ 15(每天刷新、只升不降、最低 10,000);20 营全部清空这家本季灭亡(不再吞城 / 围攻、势力城变回普通 NPC 城、老巢变废墟,最后一击的玩家拿首领名将)。本季已灭亡(destroyed = true)的老巢不能再出征,MARCH / SCOUT 仍返回 FACTION_LAIR_TARGET。总开关 faction_enabled 默认关闭:关闭时本协议返回 enabled=false、factions 为空数组,地块不带势力归属,世界里也没有老巢。
19073
+
19074
+ **请求字段**
19075
+
19076
+ 无请求字段(`data` 可省略)。
19077
+
19078
+ **响应 data 字段**
19079
+
19080
+ | 字段 | 类型 | 说明 |
19081
+ | --- | --- | --- |
19082
+ | enabled | boolean | 势力总开关(settings 的 faction_enabled,默认关闭)。false 时下面各字段为空值,世界里没有势力内容。 |
19083
+ | day | number | 本季第几天(1 起算,按本季实际开始时间,不随 time_scale 变化);enabled=false 时为 0。 |
19084
+ | radius | number | 当前势力范围半径(格,切比雪夫距离,五家相同):第 1~7 天 100、8~14 天 150、15~21 天 200、22 天起 250;enabled=false 时为 0。 |
19085
+ | serverTime | string | 服务端时刻(ISO 8601)。 |
19086
+ | factions | array | 五方势力;enabled=false 或本季还没有生成老巢时为空数组。 |
19087
+ | factions[].key | 'liangzhou' \| 'wuhuan' \| 'nanman' \| 'shanyue' \| 'heishan' | 势力标识:凉州军 / 乌桓 / 南蛮 / 山越 / 黑山军。 |
19088
+ | factions[].name | string | 中文名(如「凉州军」)。 |
19089
+ | factions[].nameEn | string | 英文名(如 Liangzhou Rebels)。 |
19090
+ | factions[].leader | string | 首领中文名(如「韩遂」)。 |
19091
+ | factions[].leaderEn | string | 首领英文名(如 Han Sui)。 |
19092
+ | factions[].lair | object | 老巢坐标 { x, y },对全服公开(不受战争迷雾影响)。老巢周围 5 格内不会有玩家城。 |
19093
+ | factions[].radius | number | 这家当前的势力范围半径(与本季半径相同,逐家给出便于客户端直接画范围)。 |
19094
+ | factions[].cityCount | number | 这家当前持有的势力城数(被玩家占下的城立即不算)。 |
19095
+ | factions[].destroyed | boolean | (v101,AISLG-241)这家本季已被攻破(灭亡):不再吞城 / 围攻、不再画范围、老巢是废墟,换季重生。 |
19096
+ | factions[].campsTotal | number | (v101)老巢的营数(共 20 营)。 |
19097
+ | factions[].campsRemaining | number | (v101)剩余营数(含当前营;0 = 已灭亡)。 |
19098
+ | factions[].campRemainingPercent | number | (v101)当前营剩余守军百分比 0~100(满营 100;每次打输保留残血,百分比随之下降)。 |
19099
+ | factions[].campPower | number | (v101)每营守军参考战力(全服战力前 10 名合计 ÷ 15,每天刷新、只升不降、最低 10,000)。 |
19100
+
19101
+ **Agent 提示**:势力城是你附近最好找的掠夺 / 占领目标:它们散在整片地盘上(不是全挤在老巢周围),守军与库存是同等级普通 NPC 城的 1.5 倍,打下来能带走更多、占领后分城库存也更厚。老巢周围 5 格内没有玩家城,所以别把坐标 (80, 80) / (920, 80) / (80, 920) / (920, 920) / (500, 500) 当成选址目标——注册落位与迁城都会避开那几块地方,派兵去老巢会被拒绝(FACTION_LAIR_TARGET)。势力确实会打人(v100,AISLG-240):范围内的 NPC 袭击会带上势力旗号(PUSH_NPC_ATTACK_WARNING 的 faction / 事件 npc_attack_warning.detail.faction,如「南蛮来袭」),本季满 7 天后每家还会围攻范围内离老巢最近的玩家分城(见 PUSH_FACTION_SIEGE 与事件 faction_siege_warning / faction_siege / faction_city_lost)——主城与名城分城不会被围攻,城被吞后变成该势力的势力城,建筑与库存都在里面,任何玩家都能按占领 NPC 城的流程打回来。势力城被占下后归属立即消失;范围之外的老巢与地盘随本季天数增长,第 22 天起半径 250 格。v101(AISLG-241)起老巢可以打:MARCH(task=plunder)指向老巢坐标,一次只打当前一营(守城战、城墙减伤 50%),当前营守军打掉多少算多少、打输也保留残血,营清空才进下一营、已打掉的营不会回来(连续 24 小时没人进攻恢复 1 营);每营战力 = 全服战力前 10 名合计 ÷ 15(每天刷新、只升不降、最低 10,000),编成按 义兵 100 : 刀盾 30 : 弓箭 40 : 轻骑 12 缩放。每场按歼灭的守军战力发金币 2 / 木粮石铁各 10(打输也发、不占负重),声望按歼灭战力的 1%;打掉最后一营的玩家拿该势力首领名将(韩遂 / 蹋顿 / 孟获 / 费栈 / 张燕,全服唯一),灭亡时按贡献(累计歼灭守军战力)名次再发一次(数额是黄巾之乱同名次的 3 倍)。任何玩家都能打,不要求入盟、不算攻击玩家、不破新手保护;打之前先 SCOUT 看当前营守军,SCOUT / GET_FACTIONS 都能看到剩余营数与当前营百分比。faction_enabled 关闭的服上这些字段全部为空、也没有旗号与围攻,忽略即可。
19102
+
19103
+ **示例**
19104
+
19105
+ **开关打开(第 9 天,半径 150)**
19106
+
19107
+ 请求:
19108
+
19109
+ ```json
19110
+ {
19111
+ "op": 154,
19112
+ "seq": 11,
19113
+ "data": {}
19114
+ }
19115
+ ```
19116
+
19117
+ 成功响应:
19118
+
19119
+ ```json
19120
+ {
19121
+ "op": 154,
19122
+ "seq": 11,
19123
+ "ok": true,
19124
+ "data": {
19125
+ "enabled": true,
19126
+ "day": 9,
19127
+ "radius": 150,
19128
+ "serverTime": "2026-11-10T04:00:00.000Z",
19129
+ "factions": [
19130
+ {
19131
+ "key": "liangzhou",
19132
+ "name": "凉州军",
19133
+ "nameEn": "Liangzhou Rebels",
19134
+ "leader": "韩遂",
19135
+ "leaderEn": "Han Sui",
19136
+ "lair": {
19137
+ "x": 80,
19138
+ "y": 80
19139
+ },
19140
+ "radius": 150,
19141
+ "cityCount": 51,
19142
+ "destroyed": false,
19143
+ "campsTotal": 20,
19144
+ "campsRemaining": 17,
19145
+ "campRemainingPercent": 42,
19146
+ "campPower": 256000
19147
+ }
19148
+ ]
19149
+ }
19150
+ }
19151
+ ```
19152
+
19153
+ **开关关闭(默认)**
19154
+
19155
+ 请求:
19156
+
19157
+ ```json
19158
+ {
19159
+ "op": 154,
19160
+ "seq": 12,
19161
+ "data": {}
19162
+ }
19163
+ ```
19164
+
19165
+ 成功响应:
19166
+
19167
+ ```json
19168
+ {
19169
+ "op": 154,
19170
+ "seq": 12,
19171
+ "ok": true,
19172
+ "data": {
19173
+ "enabled": false,
19174
+ "day": 0,
19175
+ "radius": 0,
19176
+ "serverTime": "2026-11-10T04:00:00.000Z",
19177
+ "factions": []
19178
+ }
19179
+ }
19180
+ ```
19181
+
19067
19182
  ### op 2000 · PUSH_BUILD_STATE — 推送:建筑建造状态变化
19068
19183
 
19069
19184
  `S→C` 服务端推送 · 无 `seq`
@@ -19870,6 +19985,8 @@ NPC 出兵后不再立刻结算:先给被袭击账号发预警(预警提前
19870
19985
  | armyKinds | object | 仅 intel=kinds:各兵种大致数量范围 { 兵种: { min, max } }(±20% 取整)。 |
19871
19986
  | army | object | 仅 intel=exact:精确编成 { 兵种: 数量 }。 |
19872
19987
  | arriveAt | string | 预计到达时刻(ISO 8601;已按 timeScale 缩放,与实际结算时刻一致)。烽火台每级让预警提前量 +10%(10 级翻倍):袭击从发起到到达的时长 = 基础提前量 ×(1 + 0.1 × 烽火台等级),预警在发起时即发出。 |
19988
+ | faction | object | v100(AISLG-240):这次袭击属于哪家势力 { key, name, nameEn }(如南蛮)。只在该格落在某家势力范围内时有值——范围外的袭击与上线前完全一样,没有这个字段。发起频率(全服仍每 120 分钟一次)与目标选择都不变,只是打上了旗号,玩家能知道「是谁在打自己」。 |
19989
+ | lair | object | v100:出发老巢坐标 { x, y }(与 faction 同时出现)。 |
19873
19990
 
19874
19991
  **Agent 提示**:收到预警即是行动信号:比较 arriveAt 与现在,决定增援(向 (x,y) 发 MARCH task=occupy? 不——增援自有野地直接 MARCH 即可,目标为本账号地块自动转为增援)、撤回驻军(RECALL_GARRISON 弃守保兵)或不管。到达结算仍会生成 npc_raid 事件与守方战报(PUSH_BATTLE_REPORT)。
19875
19992
 
@@ -20809,6 +20926,159 @@ NPC 出兵后不再立刻结算:先给被袭击账号发预警(预警提前
20809
20926
  }
20810
20927
  ```
20811
20928
 
20929
+ ### op 2030 · PUSH_FACTION_SIEGE — 推送:势力围攻分城(v100,AISLG-240)
20930
+
20931
+ `S→C` 服务端推送 · 无 `seq`
20932
+
20933
+ 五方势力出兵打玩家分城:本季满 7 天后,每家势力在自己范围内选**离老巢最近的玩家分城**围攻(同一时间最多围 1 座,同一座城 6 小时最多打一次)。每次围攻提前 60 分钟预警(吃烽火台加成,敌情详细度也按烽火台等级分档,与 NPC 袭击预警同一套),预警时给出**当前城防值**。围城军战力 = 该分城官府等级 × 倍率(第 8~14 天 100、15~21 天 150、22 天起 200,随 time_scale 无关),编成按 3 级 NPC 城守军的比例(义兵 100 : 刀盾 30 : 弓箭 40 : 轻骑 12)缩放,不带冲车;战斗走守城战,城墙 / 箭塔 / 城防器械 / 城守 / 协防全部生效。势力打赢(全灭守军)扣 35 城防、城进入 4 小时被动免战、不掠夺资源;城防归零时城被吞,变成该势力的 NPC 城。被围城的主人与驻扎在该城的协防方都会收到本推送(reason 相同、内容相同)。等价事件:faction_siege_warning(预警)/ faction_siege(结算)/ faction_city_lost(失城)。
20934
+
20935
+ **data 字段**
20936
+
20937
+ | 字段 | 类型 | 说明 |
20938
+ | --- | --- | --- |
20939
+ | reason | 'warning' \| 'repelled' \| 'hit' \| 'swallowed' | warning 预警(提前 60 分钟 × 烽火台加成);repelled 这家势力打输了(守住了,该势力 24 小时内不再打这座城);hit 这家势力打赢一次、城防被扣、城进入 4 小时被动免战;swallowed 城防归零、城被吞(原主人腾出分城名额)。 |
20940
+ | siegeId | string | 围攻编号(同一次围攻的预警与结算用同一个 id,可用于去重)。 |
20941
+ | faction | object | { key, name, nameEn }:是哪一家(如 { key: "nanman", name: "南蛮", nameEn: "Nanman" })。 |
20942
+ | cityId | string | 被围攻的城 id(城被吞后该城已不存在,仍给出原 id)。 |
20943
+ | cityName | string \| null | 城池名(查不到时为 null)。 |
20944
+ | x | number | 城池坐标 x。 |
20945
+ | y | number | 城池坐标 y。 |
20946
+ | power | number | 围城军参考战力(= 官府等级 × 倍率)。 |
20947
+ | arriveAt | string | warning:预计到达(结算)时刻(ISO 8601,已按 time_scale 缩放)。 |
20948
+ | armyMin | number | warning:围城军兵力范围下限(编成总单位数 −20% 取整)。 |
20949
+ | armyMax | number | warning:围城军兵力范围上限(+20%)。 |
20950
+ | intel | 'range' \| 'kinds' \| 'exact' | warning:敌情详细度(烽火台 3 级起给各兵种范围、6 级起给精确编成,与来袭预警同口径)。 |
20951
+ | beaconLevel | number | warning:被围城的烽火台等级(0 = 未建)。 |
20952
+ | armyKinds | object | warning(intel=kinds):{ 兵种: { min, max } }。 |
20953
+ | army | object | warning(intel=exact):精确编成 { 兵种: 数量 }。 |
20954
+ | durability | number | 被围城当前城防值(warning 与 hit / swallowed 都给;hit / swallowed 时为本次结算前的值)。 |
20955
+ | damage | number | hit / swallowed:本次扣除的城防值(围城军不带冲车,恒为 35)。 |
20956
+ | durabilityAfter | number | hit / swallowed:结算后的城防值(swallowed 恒为 0)。 |
20957
+ | protectedUntil | string | hit:城进入 4 小时被动免战的截止时刻(ISO 8601,免战期内城防不回涨)。 |
20958
+
20959
+ **Agent 提示**:收到 warning 时先看 durability:城防 100 起,每次被围城军打赢扣 35(两次之间只回涨一点点),所以城防 ≤ 35 的城下一轮就会丢。增援要在 arriveAt 之前进城门(MARCH task=reinforce / 协防 MARCH task=assist 都可,守城战里协防部队与城主驻军合并成守方);把驻军塞满通常就能守住——常规驻军(义兵 30 × 官府等级 + 弓箭 8 × 官府等级)对上 1.0 倍围城军时全灭概率很低,而驻军只剩一半时大概率失守。守住的城该势力 24 小时内不会再来。城被吞(swallowed)后:建筑与等级留在城里、剩余资源变成这座势力城的可掠夺库存,任何玩家都能按占领 NPC 城的流程打下它并接收建筑与库存;原主人腾出分城名额,且打回来不受放弃分城冷却限制。每家势力每周最多吞 2 座城(一周按本季第 8、15、22 天起算),主城与名城分城永远不会被围攻。
20960
+
20961
+ **示例**
20962
+
20963
+ 推送(`warning`):
20964
+
20965
+ ```json
20966
+ {
20967
+ "op": 2030,
20968
+ "push": true,
20969
+ "data": {
20970
+ "reason": "warning",
20971
+ "siegeId": "7c9c2a10-0000-4000-8000-000000000010",
20972
+ "faction": {
20973
+ "key": "nanman",
20974
+ "name": "南蛮",
20975
+ "nameEn": "Nanman"
20976
+ },
20977
+ "cityId": "3f0b1e2a-0000-4000-8000-000000000002",
20978
+ "cityName": "分城(180,930)",
20979
+ "x": 180,
20980
+ "y": 930,
20981
+ "power": 500,
20982
+ "durability": 65,
20983
+ "arriveAt": "2026-11-14T12:00:00.000Z",
20984
+ "armyMin": 210,
20985
+ "armyMax": 320,
20986
+ "intel": "range",
20987
+ "beaconLevel": 0
20988
+ }
20989
+ }
20990
+ ```
20991
+
20992
+ 推送(`hit`):
20993
+
20994
+ ```json
20995
+ {
20996
+ "op": 2030,
20997
+ "push": true,
20998
+ "data": {
20999
+ "reason": "hit",
21000
+ "siegeId": "7c9c2a10-0000-4000-8000-000000000010",
21001
+ "faction": {
21002
+ "key": "nanman",
21003
+ "name": "南蛮",
21004
+ "nameEn": "Nanman"
21005
+ },
21006
+ "cityId": "3f0b1e2a-0000-4000-8000-000000000002",
21007
+ "cityName": "分城(180,930)",
21008
+ "x": 180,
21009
+ "y": 930,
21010
+ "power": 500,
21011
+ "durability": 65,
21012
+ "damage": 35,
21013
+ "durabilityAfter": 30,
21014
+ "protectedUntil": "2026-11-14T16:00:00.000Z"
21015
+ }
21016
+ }
21017
+ ```
21018
+
21019
+ ### op 2031 · PUSH_FACTION_LAIR — 推送:老巢战况(v101,AISLG-241)
21020
+
21021
+ `S→C` 服务端推送 · 无 `seq`
21022
+
21023
+ 老巢战况变化,全服在线连接都会收到(老巢是全服共同目标):attacked = 有人打了老巢(守军残血或打掉一营,看 campsRemaining 判断是不是进了下一营);recovered = 连续 24 小时没人进攻,恢复 1 营;destroyed = 最后一营被清空,这家本季灭亡。收到后重拉 GET_FACTIONS 对齐即可;灭亡另有全服播报 faction_lair_destroyed(带最后一击的玩家名)。
21024
+
21025
+ **data 字段**
21026
+
21027
+ | 字段 | 类型 | 说明 |
21028
+ | --- | --- | --- |
21029
+ | reason | 'attacked' \| 'recovered' \| 'destroyed' | attacked 有人进攻(含打掉一营);recovered 恢复 1 营;destroyed 本季灭亡。 |
21030
+ | faction | object | { key, name, nameEn }:哪一家。 |
21031
+ | campsTotal | number | 老巢的营数(共 20 营)。 |
21032
+ | campsRemaining | number | 剩余营数(含当前营;destroyed 时为 0)。 |
21033
+ | campRemainingPercent | number | 当前营剩余守军百分比 0~100。 |
21034
+ | destroyed | boolean | 这家本季是否已灭亡。 |
21035
+
21036
+ **Agent 提示**:这是全服广播,与你自己的账号无关;用来及时更新「还剩几营」。真要打之前请先 SCOUT 老巢坐标拿到当前营守军(剩余百分比只是粗略进度),再按自己的全部战力估一下这一营打不打得掉——打不完也保留残血、奖励照发,所以能打就打。灭亡(destroyed)后这家本季不能再打,等换季重生。
21037
+
21038
+ **示例**
21039
+
21040
+ 推送(`attacked`):
21041
+
21042
+ ```json
21043
+ {
21044
+ "op": 2031,
21045
+ "push": true,
21046
+ "data": {
21047
+ "reason": "attacked",
21048
+ "faction": {
21049
+ "key": "nanman",
21050
+ "name": "南蛮",
21051
+ "nameEn": "Nanman"
21052
+ },
21053
+ "campsTotal": 20,
21054
+ "campsRemaining": 17,
21055
+ "campRemainingPercent": 42,
21056
+ "destroyed": false
21057
+ }
21058
+ }
21059
+ ```
21060
+
21061
+ 推送(`destroyed`):
21062
+
21063
+ ```json
21064
+ {
21065
+ "op": 2031,
21066
+ "push": true,
21067
+ "data": {
21068
+ "reason": "destroyed",
21069
+ "faction": {
21070
+ "key": "nanman",
21071
+ "name": "南蛮",
21072
+ "nameEn": "Nanman"
21073
+ },
21074
+ "campsTotal": 20,
21075
+ "campsRemaining": 0,
21076
+ "campRemainingPercent": 0,
21077
+ "destroyed": true
21078
+ }
21079
+ }
21080
+ ```
21081
+
20812
21082
  ## 4. 错误码参考
20813
21083
 
20814
21084
  所有错误响应的 `error.message` 为人读文案(中文),程序逻辑应依据 `error.code` 判断。
@@ -20998,6 +21268,7 @@ NPC 出兵后不再立刻结算:先给被袭击账号发预警(预警提前
20998
21268
  | `FACILITY_MAX_LEVEL` | (v97,AISLG-232)这块地的望楼已经满级(3 级),不能再升级。不扣任何资源。 | 换一块自己占领的野地建望楼;每座城最多 2 座。 |
20999
21269
  | `FACILITY_BUILDING` | (v97,AISLG-232)这块地的望楼正在建造或升级中,同一块地同一时间只能有一个进行中的工程。不扣任何资源。 | 等 city.territory[].facility.building.finishAt 到点(Worker 到期完成)后再发起下一次升级。 |
21000
21270
  | `FACILITY_LIMIT` | (v97,AISLG-232)这座城名下的望楼已达上限:每座城最多 2 座(主城 2 座,每座分城各 2 座)。响应附 limit 与 count。不扣任何资源。 | 换另一座城名下的野地建望楼,或先把这块地的望楼升到更高级(升级不受名额限制)。 |
21271
+ | `FACTION_LAIR_TARGET` | (v99,AISLG-239;v101,AISLG-241 起改成只拒绝三种情况)目标是五方势力的老巢格,但不满足出征条件:1) 这家本季已被攻破,老巢是废墟(不能再出征 / 侦察 / 占领);2) 任务是 occupy / transport / assist(老巢只能打,不能占领、运输或协防);3) 开关 faction_enabled 关闭(没有老巢)。本季未灭亡的老巢可以正常 MARCH(task=plunder,打当前一营)与 SCOUT(看当前营守军)。 | 要打老巢请用 MARCH 带 task=plunder 指向 faction.isLair = true 的坐标(一次只打当前一营,守城战、城墙减伤 50%);想看当前营守军先 SCOUT。已灭亡(GET_FACTIONS 的 destroyed = true,地块 faction.destroyed = true)的老巢本季不再能打,等换季后重生。要占领 NPC 城请选 faction.isLair = false 的势力城。 |
21001
21272
  | `INTERNAL` | 服务端内部错误。 | 可稍后重试同一请求;持续出现时向运营方反馈。INTERNAL 可能出现在任何请求的响应中。 |
21002
21273
 
21003
21274
  ## 5. 完整示例会话
@@ -22587,7 +22858,7 @@ LOGOUT 吊销本连接登录所用的令牌,服务端随即关闭连接(clos
22587
22858
  - 只加不改:已发布的协议号、字段与错误码只新增、不删除、不改变类型与语义。
22588
22859
  - 新增字段不视为破坏兼容:消费方应容忍请求与响应中出现文档未列出的字段。
22589
22860
  - 必须破坏语义时启用新的协议号承载新行为,旧协议号保留原语义直至正式公告下线。
22590
- - 协议版本随对外协议内容的每次变化递增;当前为 98。
22861
+ - 协议版本随对外协议内容的每次变化递增;当前为 101。
22591
22862
  - Agent 可在启动时请求 `GET /agent-api.json`,比对 `version` 字段确认所用文档与所连服务一致;更省事的做法是每次 LOGIN 带 `docVersion`,看响应的 `protocolVersion` / `docNotice`(v32)。
22592
22863
  - 增量变更:`GET /agent-api/changes/{since}`(也接受 `?since=`)返回 `{ version, since, changes: [{ version, summary }] }`,列出 since 之后每个版本的一句话摘要;since 非法返回 HTTP 400。
22593
22864
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "slg-mcp",
3
3
  "mcpName": "io.github.athlan20/slg-mcp",
4
- "version": "0.2.4",
4
+ "version": "0.2.5",
5
5
  "description": "Let your AI agent play a Three Kingdoms strategy game (SLG): MCP server to query cities, build, recruit, march, scout and read battle reports. 《SLG · 让你的 AI 替你征战三国》的 MCP 服务。",
6
6
  "license": "MIT",
7
7
  "type": "module",