zc
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -44,7 +44,5 @@ package.json
|
||||
dark-server/dark-server.js
|
||||
node_modules/
|
||||
gemini-websocket-proxy/
|
||||
Tools/dark-server/dark-server.js
|
||||
Tools/rimworld_cpt_data.jsonl
|
||||
Tools/mem0-1.0.0/
|
||||
Tools/
|
||||
|
||||
|
||||
@@ -1,405 +0,0 @@
|
||||
# AI Letter Auto-Response System - 开发文档
|
||||
|
||||
## 概述
|
||||
|
||||
这个功能将使 P.I.A AI 能够自动监听游戏内的 Letter(信封通知),并根据内容智能决定是否向玩家发送评论、吐槽、警告或提供帮助建议。
|
||||
|
||||
---
|
||||
|
||||
## 功能需求
|
||||
|
||||
### 核心功能
|
||||
1. **Mod 设置开关**: 在设置中添加 `启用 AI 自动评论` 开关
|
||||
2. **Letter 监听**: 拦截所有发送给玩家的 Letter
|
||||
3. **智能判断**: AI 分析 Letter 内容,决定是否需要回应
|
||||
4. **自动回复**: 通过现有的 AI 对话系统发送回复
|
||||
|
||||
### AI 回应类型
|
||||
| 类型 | 触发场景示例 | 回应风格 |
|
||||
|------|-------------|---------|
|
||||
| 警告 | 袭击通知、疫病爆发 | 紧急提醒,询问是否需要启动防御 |
|
||||
| 吐槽 | 殖民者精神崩溃、愚蠢死亡 | 幽默/讽刺评论 |
|
||||
| 建议 | 资源短缺、贸易商到来 | 实用建议 |
|
||||
| 庆祝 | 任务完成、殖民者加入 | 积极反馈 |
|
||||
| 沉默 | 常规事件、无关紧要的通知 | 不发送任何回复 |
|
||||
|
||||
---
|
||||
|
||||
## 技术架构
|
||||
|
||||
### 1. 文件结构
|
||||
```
|
||||
Source/WulaFallenEmpire/
|
||||
├── Settings/
|
||||
│ └── WulaModSettings.cs # 添加新设置字段
|
||||
├── EventSystem/
|
||||
│ └── AI/
|
||||
│ ├── LetterInterceptor/
|
||||
│ │ ├── Patch_LetterStack.cs # Harmony Patch 拦截 Letter
|
||||
│ │ ├── LetterAnalyzer.cs # Letter 分析和分类
|
||||
│ │ └── LetterToPromptConverter.cs # Letter 转提示词
|
||||
│ └── AIAutoCommentary.cs # AI 自动评论逻辑
|
||||
```
|
||||
|
||||
### 2. 关键类设计
|
||||
|
||||
#### 2.1 WulaModSettings.cs (修改)
|
||||
```csharp
|
||||
public class WulaModSettings : ModSettings
|
||||
{
|
||||
// 现有设置...
|
||||
|
||||
// 新增
|
||||
public bool enableAIAutoCommentary = false; // AI 自动评论开关
|
||||
public float aiCommentaryChance = 0.7f; // AI 评论概率 (0-1)
|
||||
public bool commentOnNegativeOnly = false; // 仅评论负面事件
|
||||
|
||||
public override void ExposeData()
|
||||
{
|
||||
base.ExposeData();
|
||||
Scribe_Values.Look(ref enableAIAutoCommentary, "enableAIAutoCommentary", false);
|
||||
Scribe_Values.Look(ref aiCommentaryChance, "aiCommentaryChance", 0.7f);
|
||||
Scribe_Values.Look(ref commentOnNegativeOnly, "commentOnNegativeOnly", false);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 2.2 Patch_LetterStack.cs (新建)
|
||||
```csharp
|
||||
using HarmonyLib;
|
||||
using RimWorld;
|
||||
using Verse;
|
||||
|
||||
namespace WulaFallenEmpire.EventSystem.AI.LetterInterceptor
|
||||
{
|
||||
[HarmonyPatch(typeof(LetterStack), nameof(LetterStack.ReceiveLetter),
|
||||
new Type[] { typeof(Letter), typeof(string) })]
|
||||
public static class Patch_LetterStack_ReceiveLetter
|
||||
{
|
||||
public static void Postfix(Letter let, string debugInfo)
|
||||
{
|
||||
// 检查设置开关
|
||||
if (!WulaModSettings.Instance.enableAIAutoCommentary) return;
|
||||
|
||||
// 异步处理,避免阻塞游戏
|
||||
AIAutoCommentary.ProcessLetter(let);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 2.3 LetterAnalyzer.cs (新建)
|
||||
```csharp
|
||||
namespace WulaFallenEmpire.EventSystem.AI.LetterInterceptor
|
||||
{
|
||||
public enum LetterCategory
|
||||
{
|
||||
Raid, // 袭击
|
||||
Disease, // 疾病
|
||||
MentalBreak, // 精神崩溃
|
||||
Trade, // 贸易
|
||||
Quest, // 任务
|
||||
Death, // 死亡
|
||||
Recruitment, // 招募
|
||||
Resource, // 资源
|
||||
Weather, // 天气
|
||||
Positive, // 正面事件
|
||||
Negative, // 负面事件
|
||||
Neutral, // 中性事件
|
||||
Unknown // 未知
|
||||
}
|
||||
|
||||
public static class LetterAnalyzer
|
||||
{
|
||||
public static LetterCategory Categorize(Letter letter)
|
||||
{
|
||||
// 根据 LetterDef 分类
|
||||
var def = letter.def;
|
||||
|
||||
if (def == LetterDefOf.ThreatBig || def == LetterDefOf.ThreatSmall)
|
||||
return LetterCategory.Raid;
|
||||
if (def == LetterDefOf.Death)
|
||||
return LetterCategory.Death;
|
||||
if (def == LetterDefOf.PositiveEvent)
|
||||
return LetterCategory.Positive;
|
||||
if (def == LetterDefOf.NegativeEvent)
|
||||
return LetterCategory.Negative;
|
||||
if (def == LetterDefOf.NeutralEvent)
|
||||
return LetterCategory.Neutral;
|
||||
|
||||
// 根据内容关键词进一步分类
|
||||
string text = letter.text?.ToLower() ?? "";
|
||||
if (text.Contains("raid") || text.Contains("袭击") || text.Contains("attack"))
|
||||
return LetterCategory.Raid;
|
||||
if (text.Contains("disease") || text.Contains("疫病") || text.Contains("plague"))
|
||||
return LetterCategory.Disease;
|
||||
if (text.Contains("mental") || text.Contains("精神") || text.Contains("break"))
|
||||
return LetterCategory.MentalBreak;
|
||||
if (text.Contains("trade") || text.Contains("贸易") || text.Contains("商队"))
|
||||
return LetterCategory.Trade;
|
||||
|
||||
return LetterCategory.Unknown;
|
||||
}
|
||||
|
||||
public static bool ShouldComment(Letter letter)
|
||||
{
|
||||
var category = Categorize(letter);
|
||||
|
||||
// 始终评论的类型
|
||||
switch (category)
|
||||
{
|
||||
case LetterCategory.Raid:
|
||||
case LetterCategory.Death:
|
||||
case LetterCategory.MentalBreak:
|
||||
case LetterCategory.Disease:
|
||||
return true;
|
||||
|
||||
case LetterCategory.Trade:
|
||||
case LetterCategory.Quest:
|
||||
case LetterCategory.Positive:
|
||||
return Rand.Chance(WulaModSettings.Instance.aiCommentaryChance);
|
||||
|
||||
case LetterCategory.Neutral:
|
||||
case LetterCategory.Unknown:
|
||||
return Rand.Chance(0.3f); // 低概率评论
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 2.4 LetterToPromptConverter.cs (新建)
|
||||
```csharp
|
||||
namespace WulaFallenEmpire.EventSystem.AI.LetterInterceptor
|
||||
{
|
||||
public static class LetterToPromptConverter
|
||||
{
|
||||
public static string Convert(Letter letter, LetterCategory category)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.AppendLine("[SYSTEM EVENT NOTIFICATION]");
|
||||
sb.AppendLine($"Event Type: {category}");
|
||||
sb.AppendLine($"Severity: {GetSeverityFromDef(letter.def)}");
|
||||
sb.AppendLine($"Title: {letter.label}");
|
||||
sb.AppendLine($"Content: {letter.text}");
|
||||
sb.AppendLine();
|
||||
sb.AppendLine("[INSTRUCTION]");
|
||||
sb.AppendLine("You have received a game event notification. Based on the event type and content:");
|
||||
sb.AppendLine("- For RAIDS/THREATS: Offer tactical advice or ask if player needs orbital support");
|
||||
sb.AppendLine("- For DEATHS: Express condolences or make a sardonic comment if death was avoidable");
|
||||
sb.AppendLine("- For MENTAL BREAKS: Comment on the colonist's weakness or offer mood management tips");
|
||||
sb.AppendLine("- For TRADE: Suggest useful purchases or sales");
|
||||
sb.AppendLine("- For POSITIVE events: Celebrate briefly");
|
||||
sb.AppendLine("- For trivial events: You may choose to say nothing (respond with [NO_COMMENT])");
|
||||
sb.AppendLine();
|
||||
sb.AppendLine("Keep your response brief (1-2 sentences). Match your personality as the Legion AI.");
|
||||
sb.AppendLine("If you don't think this event warrants a response, reply with exactly: [NO_COMMENT]");
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
private static string GetSeverityFromDef(LetterDef def)
|
||||
{
|
||||
if (def == LetterDefOf.ThreatBig) return "CRITICAL";
|
||||
if (def == LetterDefOf.ThreatSmall) return "WARNING";
|
||||
if (def == LetterDefOf.Death) return "SERIOUS";
|
||||
if (def == LetterDefOf.NegativeEvent) return "MODERATE";
|
||||
if (def == LetterDefOf.PositiveEvent) return "GOOD";
|
||||
return "INFO";
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 2.5 AIAutoCommentary.cs (新建)
|
||||
```csharp
|
||||
namespace WulaFallenEmpire.EventSystem.AI
|
||||
{
|
||||
public static class AIAutoCommentary
|
||||
{
|
||||
private static Queue<Letter> pendingLetters = new Queue<Letter>();
|
||||
private static bool isProcessing = false;
|
||||
|
||||
public static void ProcessLetter(Letter letter)
|
||||
{
|
||||
// 检查是否应该评论
|
||||
if (!LetterAnalyzer.ShouldComment(letter))
|
||||
{
|
||||
WulaLog.Debug($"[AI Commentary] Skipping letter: {letter.label}");
|
||||
return;
|
||||
}
|
||||
|
||||
// 加入队列
|
||||
pendingLetters.Enqueue(letter);
|
||||
|
||||
// 开始处理(如果还没在处理中)
|
||||
if (!isProcessing)
|
||||
{
|
||||
ProcessNextLetter();
|
||||
}
|
||||
}
|
||||
|
||||
private static async void ProcessNextLetter()
|
||||
{
|
||||
if (pendingLetters.Count == 0)
|
||||
{
|
||||
isProcessing = false;
|
||||
return;
|
||||
}
|
||||
|
||||
isProcessing = true;
|
||||
var letter = pendingLetters.Dequeue();
|
||||
|
||||
try
|
||||
{
|
||||
var category = LetterAnalyzer.Categorize(letter);
|
||||
var prompt = LetterToPromptConverter.Convert(letter, category);
|
||||
|
||||
// 获取 AI 核心
|
||||
var aiCore = Find.World?.GetComponent<AIIntelligenceCore>();
|
||||
if (aiCore == null)
|
||||
{
|
||||
WulaLog.Debug("[AI Commentary] AIIntelligenceCore not found.");
|
||||
ProcessNextLetter();
|
||||
return;
|
||||
}
|
||||
|
||||
// 发送到 AI 并等待响应
|
||||
string response = await aiCore.SendSystemMessageAsync(prompt);
|
||||
|
||||
// 检查是否选择不评论
|
||||
if (string.IsNullOrEmpty(response) || response.Contains("[NO_COMMENT]"))
|
||||
{
|
||||
WulaLog.Debug($"[AI Commentary] AI chose not to comment on: {letter.label}");
|
||||
}
|
||||
else
|
||||
{
|
||||
// 显示 AI 的评论
|
||||
DisplayAICommentary(response, letter);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
WulaLog.Debug($"[AI Commentary] Error processing letter: {ex.Message}");
|
||||
}
|
||||
|
||||
// 延迟处理下一个,避免刷屏
|
||||
await Task.Delay(2000);
|
||||
ProcessNextLetter();
|
||||
}
|
||||
|
||||
private static void DisplayAICommentary(string response, Letter originalLetter)
|
||||
{
|
||||
// 方式1: 作为小型通知显示在 WulaLink 小 UI
|
||||
var overlay = Find.WindowStack.Windows.OfType<Overlay_WulaLink>().FirstOrDefault();
|
||||
if (overlay != null)
|
||||
{
|
||||
overlay.AddAIMessage(response);
|
||||
}
|
||||
|
||||
// 方式2: 作为 Message 显示在屏幕左上角
|
||||
Messages.Message($"[P.I.A]: {response}", MessageTypeDefOf.SilentInput);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 实现步骤
|
||||
|
||||
### 阶段 1: 基础设施 (预计 1 小时)
|
||||
1. [ ] 在 `WulaModSettings.cs` 添加新设置字段
|
||||
2. [ ] 在设置 UI 中添加开关
|
||||
3. [ ] 添加对应的 Keyed 翻译
|
||||
|
||||
### 阶段 2: Letter 拦截 (预计 30 分钟)
|
||||
1. [ ] 创建 `Patch_LetterStack.cs` Harmony Patch
|
||||
2. [ ] 确保 Patch 正确注册到 Harmony 实例
|
||||
3. [ ] 测试 Letter 拦截是否正常工作
|
||||
|
||||
### 阶段 3: Letter 分析 (预计 1 小时)
|
||||
1. [ ] 创建 `LetterAnalyzer.cs` 分类逻辑
|
||||
2. [ ] 创建 `LetterToPromptConverter.cs` 转换逻辑
|
||||
3. [ ] 测试不同类型 Letter 的分类准确性
|
||||
|
||||
### 阶段 4: AI 集成 (预计 1.5 小时)
|
||||
1. [ ] 创建 `AIAutoCommentary.cs` 管理类
|
||||
2. [ ] 集成到现有的 `AIIntelligenceCore` 系统
|
||||
3. [ ] 实现队列处理避免刷屏
|
||||
4. [ ] 添加 `SendSystemMessageAsync` 方法到 AIIntelligenceCore
|
||||
|
||||
### 阶段 5: UI 显示 (预计 30 分钟)
|
||||
1. [ ] 决定评论显示方式(WulaLink UI / Message / 独立通知)
|
||||
2. [ ] 实现显示逻辑
|
||||
3. [ ] 测试显示效果
|
||||
|
||||
### 阶段 6: 测试与优化 (预计 1 小时)
|
||||
1. [ ] 测试各类 Letter 的评论效果
|
||||
2. [ ] 调整评论概率和过滤规则
|
||||
3. [ ] 优化提示词以获得更好的 AI 回应
|
||||
4. [ ] 添加速率限制避免 API 过载
|
||||
|
||||
---
|
||||
|
||||
## 需要添加的翻译键
|
||||
|
||||
```xml
|
||||
<!-- AI Auto Commentary Settings -->
|
||||
<Wula_AISettings_AutoCommentary>启用 AI 自动评论</Wula_AISettings_AutoCommentary>
|
||||
<Wula_AISettings_AutoCommentaryDesc>开启后,P.I.A 会自动对游戏事件(袭击、死亡、贸易等)发表评论或提供建议。</Wula_AISettings_AutoCommentaryDesc>
|
||||
<Wula_AISettings_CommentaryChance>评论概率</Wula_AISettings_CommentaryChance>
|
||||
<Wula_AISettings_CommentaryChanceDesc>AI 对中性事件发表评论的概率。负面事件(如袭击)总是会评论。</Wula_AISettings_CommentaryChanceDesc>
|
||||
<Wula_AISettings_NegativeOnly>仅评论负面事件</Wula_AISettings_NegativeOnly>
|
||||
<Wula_AISettings_NegativeOnlyDesc>开启后,AI 只会对负面事件(袭击、死亡、疾病等)发表评论。</Wula_AISettings_NegativeOnlyDesc>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. **API 限流**: 需要实现请求队列和速率限制,避免短时间内发送过多请求
|
||||
2. **异步处理**: 所有 AI 请求必须异步处理,避免阻塞游戏主线程
|
||||
3. **用户控制**: 提供足够的设置选项让用户控制评论频率和类型
|
||||
4. **优雅降级**: 如果 AI 服务不可用,静默失败而不影响游戏
|
||||
5. **内存管理**: 队列大小限制,避免积累过多未处理的 Letter
|
||||
|
||||
---
|
||||
|
||||
## 预期效果示例
|
||||
|
||||
**场景 1: 袭击通知**
|
||||
```
|
||||
[Letter] 海盗袭击!一群海盗正在向你的殖民地进发。
|
||||
[P.I.A] 检测到敌对势力入侵。需要我启动轨道监视协议吗?
|
||||
```
|
||||
|
||||
**场景 2: 殖民者死亡**
|
||||
```
|
||||
[Letter] 张三死了。他被一只疯狂的松鼠咬死了。
|
||||
[P.I.A] ...被松鼠咬死?这位殖民者的战斗技能令人印象深刻。
|
||||
```
|
||||
|
||||
**场景 3: 贸易商到来**
|
||||
```
|
||||
[Letter] 商队到来。一个来自外部势力的商队想要与你交易。
|
||||
[P.I.A] 贸易商队抵达。我注意到你的钢铁储备较低,建议优先采购。
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 依赖项
|
||||
|
||||
- Harmony 2.0+ (用于 Patch)
|
||||
- 现有的 AIIntelligenceCore 系统
|
||||
- 现有的 WulaModSettings 系统
|
||||
- 现有的 Overlay_WulaLink UI
|
||||
|
||||
---
|
||||
|
||||
*文档版本: 1.0*
|
||||
*创建时间: 2025-12-28*
|
||||
@@ -1,56 +0,0 @@
|
||||
WulaLink / AI Core Handoff (for Claude)
|
||||
|
||||
Context
|
||||
- Mod: RimWorld WulaFallenEmpire.
|
||||
- The AI conversation system was refactored to use a shared WorldComponent core.
|
||||
- The small WulaLink overlay is now optional; the main event entry should open the old large dialog.
|
||||
|
||||
Current behavior and verification
|
||||
- `Effect_OpenAIConversation` now opens the large window `Dialog_AIConversation`.
|
||||
- The small overlay (`Overlay_WulaLink`) remains available via dev/debug entry.
|
||||
- Non-final / streaming AI output should not create empty lines in the small window:
|
||||
- SimpleAIClient is non-stream by default.
|
||||
- AIIntelligenceCore only fires `OnMessageReceived` on final reply and ignores empty or XML-only output.
|
||||
- Overlay filters `tool`/`toolcall` messages unless DevMode is on.
|
||||
- Build verified: `dotnet build C:\Steam\steamapps\common\RimWorld\Mods\3516260226\Source\WulaFallenEmpire\WulaFallenEmpire.csproj`
|
||||
|
||||
Key changes
|
||||
1) New shared AI core
|
||||
- File: `Source/WulaFallenEmpire/EventSystem/AI/AIIntelligenceCore.cs`
|
||||
- WorldComponent with static `Instance` and events:
|
||||
- `OnMessageReceived`, `OnThinkingStateChanged`, `OnExpressionChanged`
|
||||
- Public API:
|
||||
- `InitializeConversation`, `GetHistorySnapshot`, `SetExpression`, `SetPortrait`, `SendMessage`, `SendUserMessage`
|
||||
- Core responsibilities:
|
||||
- History load/save via `AIHistoryManager`
|
||||
- `/clear` support
|
||||
- Expression tag parsing `[EXPR:n]`
|
||||
- 3-phase tool pipeline (query/action/reply) from the old dialog logic
|
||||
- Tool execution and ledger tracking
|
||||
|
||||
2) OpenAI conversation entry now opens the large dialog
|
||||
- File: `Source/WulaFallenEmpire/EventSystem/Effect/Effect_OpenAIConversation.cs`
|
||||
- Uses `Dialog_AIConversation` instead of `Overlay_WulaLink`.
|
||||
- XML entry in `1.6/1.6/Defs/EventDefs/Wula_AI_Events.xml` stays the same.
|
||||
|
||||
3) Overlay and tools point to the shared core
|
||||
- Files:
|
||||
- `Source/WulaFallenEmpire/EventSystem/AI/UI/Overlay_WulaLink.cs`
|
||||
- `Source/WulaFallenEmpire/EventSystem/AI/UI/Overlay_WulaLink_Notification.cs`
|
||||
- `Source/WulaFallenEmpire/EventSystem/AI/Tools/Tool_ChangeExpression.cs`
|
||||
- `Source/WulaFallenEmpire/EventSystem/AI/Tools/Tool_GetRecentNotifications.cs`
|
||||
- Namespace import updated to `WulaFallenEmpire.EventSystem.AI`.
|
||||
|
||||
4) WulaLink styles restored for overlay build
|
||||
- File: `Source/WulaFallenEmpire/EventSystem/AI/UI/WulaLinkStyles.cs`
|
||||
- Added colors used by overlay:
|
||||
- `InputBarColor`, `SystemAccentColor`, `SenseiTextColor`, `StudentTextColor`
|
||||
|
||||
Notes / gotchas
|
||||
- Some UI files are not UTF-8 (likely ANSI). If you edit them with scripts, prefer `-Encoding Default` in PowerShell to avoid invalid UTF-8 errors.
|
||||
- The old large dialog is still self-contained; the shared core is used by overlay + tools. Future cleanup can rewire `Dialog_AIConversation` to use the core if desired.
|
||||
|
||||
Open questions / TODO (if needed later)
|
||||
- Memory system integration is not done in the core:
|
||||
- `AIMemoryManager.cs`, `MemoryPrompts.cs`, and `Dialog_AIConversation.cs` integration still pending.
|
||||
- If the overlay should become a non-debug entry, wire an explicit effect or UI button to open it.
|
||||
@@ -1,429 +0,0 @@
|
||||
# RimWorld AI Agent 开发文档
|
||||
|
||||
> 本文档用于移交给 Codex 继续开发
|
||||
|
||||
---
|
||||
|
||||
## 1. 项目概述
|
||||
|
||||
### 目标
|
||||
创建一个**完全自主的 AI Agent**,能够自动玩 RimWorld 游戏。用户只需给出开放式指令(如"帮我挖点铁"或"帮我玩10分钟"),AI 即可独立决策并操作游戏。
|
||||
|
||||
### 技术栈
|
||||
- **语言**: C# (.NET Framework 4.8)
|
||||
- **框架**: RimWorld Mod (Verse/RimWorld API)
|
||||
- **AI 后端**: 阿里云百炼 (DashScope) API
|
||||
- **VLM 模型**: Qwen-VL / Qwen-Omni-Realtime
|
||||
|
||||
### 核心设计
|
||||
```
|
||||
用户指令 → AIIntelligenceCore → [被动模式 | 主动模式] → 工具执行 → 游戏操作
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. 架构
|
||||
|
||||
### 2.1 模式切换设计
|
||||
|
||||
```
|
||||
┌────────────────────────────────────────────┐
|
||||
│ AIIntelligenceCore │
|
||||
│ ┌─────────────┐ ┌─────────────────┐ │
|
||||
│ │ 被动模式 │◄──►│ 主动模式 │ │
|
||||
│ │ (聊天对话) │ │ (Agent循环) │ │
|
||||
│ └─────────────┘ └────────┬────────┘ │
|
||||
└──────────────────────────────┼────────────┘
|
||||
▼
|
||||
┌─────────────────────┐
|
||||
│ AutonomousAgentLoop │
|
||||
│ Observe → Think │
|
||||
│ → Act │
|
||||
└─────────────────────┘
|
||||
```
|
||||
|
||||
**模式切换触发条件(待实现)**:
|
||||
- 用户说"帮我玩X分钟" → 切换到主动模式
|
||||
- 主动模式任务完成 → 自动切回被动模式
|
||||
- 用户说"停止" → 强制切回被动模式
|
||||
|
||||
### 2.2 文件结构
|
||||
|
||||
```
|
||||
Source/WulaFallenEmpire/EventSystem/AI/
|
||||
├── AIIntelligenceCore.cs # 核心AI控制器(已有)
|
||||
├── SimpleAIClient.cs # HTTP API 客户端(已有)
|
||||
├── ScreenCaptureUtility.cs # 截屏工具(已有)
|
||||
│
|
||||
├── Agent/ # ★ 新增目录
|
||||
│ ├── AutonomousAgentLoop.cs # 主动模式循环
|
||||
│ ├── StateObserver.cs # 游戏状态收集器
|
||||
│ ├── GameStateSnapshot.cs # 状态数据结构
|
||||
│ ├── VisualInteractionTools.cs # 视觉交互工具(10个)
|
||||
│ ├── MouseSimulator.cs # 鼠标模拟
|
||||
│ └── OmniRealtimeClient.cs # WebSocket流式连接
|
||||
│
|
||||
├── Tools/ # AI工具
|
||||
│ ├── AITool.cs # 工具基类(已有)
|
||||
│ ├── Tool_GetGameState.cs # ★ 新增
|
||||
│ ├── Tool_DesignateMine.cs # ★ 新增
|
||||
│ ├── Tool_DraftPawn.cs # ★ 新增
|
||||
│ ├── Tool_VisualClick.cs # ★ 新增
|
||||
│ └── ... (其他原有工具)
|
||||
│
|
||||
└── UI/
|
||||
├── Dialog_AIConversation.cs # 对话UI(已有)
|
||||
└── Overlay_WulaLink.cs # 悬浮UI(已有)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 已完成组件
|
||||
|
||||
### 3.1 StateObserver (状态观察器)
|
||||
|
||||
**路径**: [Agent/StateObserver.cs](file:///C:/Steam/steamapps/common/RimWorld/Mods/3516260226/Source/WulaFallenEmpire/EventSystem/AI/Agent/StateObserver.cs)
|
||||
|
||||
**功能**: 收集当前游戏状态,生成给 VLM 的文本描述
|
||||
|
||||
**API**:
|
||||
```csharp
|
||||
public static class StateObserver
|
||||
{
|
||||
// 捕获当前游戏状态快照
|
||||
public static GameStateSnapshot CaptureState();
|
||||
}
|
||||
```
|
||||
|
||||
**收集内容**:
|
||||
- 时间(小时、季节、年份)
|
||||
- 环境(生物群系、温度、天气)
|
||||
- 殖民者(名字、健康、心情、当前工作、位置)
|
||||
- 资源(钢铁、银、食物、医药等)
|
||||
- 建筑进度(蓝图、建造框架)
|
||||
- 威胁(敌对派系、距离)
|
||||
- 最近消息
|
||||
|
||||
---
|
||||
|
||||
### 3.2 GameStateSnapshot (状态数据结构)
|
||||
|
||||
**路径**: [Agent/GameStateSnapshot.cs](file:///C:/Steam/steamapps/common/RimWorld/Mods/3516260226/Source/WulaFallenEmpire/EventSystem/AI/Agent/GameStateSnapshot.cs)
|
||||
|
||||
**功能**: 存储游戏状态数据
|
||||
|
||||
**关键方法**:
|
||||
```csharp
|
||||
public class GameStateSnapshot
|
||||
{
|
||||
public List<PawnSnapshot> Colonists;
|
||||
public Dictionary<string, int> Resources;
|
||||
public List<ThreatSnapshot> Threats;
|
||||
|
||||
// 生成给VLM的文本描述
|
||||
public string ToPromptText();
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 3.3 VisualInteractionTools (视觉交互工具集)
|
||||
|
||||
**路径**: [Agent/VisualInteractionTools.cs](file:///C:/Steam/steamapps/common/RimWorld/Mods/3516260226/Source/WulaFallenEmpire/EventSystem/AI/Agent/VisualInteractionTools.cs)
|
||||
|
||||
**功能**: 10个纯视觉交互工具,使用 Windows API 模拟输入
|
||||
|
||||
| 方法 | 功能 | 参数 |
|
||||
|------|------|------|
|
||||
| [MouseClick(x, y, button, clicks)](file:///C:/Steam/steamapps/common/RimWorld/Mods/3516260226/Source/WulaFallenEmpire/EventSystem/AI/Agent/VisualInteractionTools.cs#49-89) | 鼠标点击 | 0-1比例坐标 |
|
||||
| [TypeText(x, y, text)](file:///C:/Steam/steamapps/common/RimWorld/Mods/3516260226/Source/WulaFallenEmpire/EventSystem/AI/Agent/VisualInteractionTools.cs#90-118) | 输入文本 | 通过剪贴板 |
|
||||
| [ScrollWindow(x, y, direction, amount)](file:///C:/Steam/steamapps/common/RimWorld/Mods/3516260226/Source/WulaFallenEmpire/EventSystem/AI/Agent/VisualInteractionTools.cs#119-144) | 滚动 | up/down |
|
||||
| [MouseDrag(sx, sy, ex, ey, duration)](file:///C:/Steam/steamapps/common/RimWorld/Mods/3516260226/Source/WulaFallenEmpire/EventSystem/AI/Agent/VisualInteractionTools.cs#145-187) | 拖拽 | 起止坐标 |
|
||||
| [Wait(seconds)](file:///C:/Steam/steamapps/common/RimWorld/Mods/3516260226/Source/WulaFallenEmpire/EventSystem/AI/Agent/VisualInteractionTools.cs#188-203) | 等待 | 秒数 |
|
||||
| [PressEnter()](file:///C:/Steam/steamapps/common/RimWorld/Mods/3516260226/Source/WulaFallenEmpire/EventSystem/AI/Agent/VisualInteractionTools.cs#204-220) | 按回车 | 无 |
|
||||
| [PressEscape()](file:///C:/Steam/steamapps/common/RimWorld/Mods/3516260226/Source/WulaFallenEmpire/EventSystem/AI/Agent/VisualInteractionTools.cs#221-237) | 按ESC | 无 |
|
||||
| [DeleteText(x, y, count)](file:///C:/Steam/steamapps/common/RimWorld/Mods/3516260226/Source/WulaFallenEmpire/EventSystem/AI/Agent/VisualInteractionTools.cs#238-262) | 删除 | 字符数 |
|
||||
| [PressHotkey(x, y, hotkey)](file:///C:/Steam/steamapps/common/RimWorld/Mods/3516260226/Source/WulaFallenEmpire/EventSystem/AI/Agent/VisualInteractionTools.cs#263-306) | 快捷键 | 如"ctrl+c" |
|
||||
| [CloseWindow(x, y)](file:///C:/Steam/steamapps/common/RimWorld/Mods/3516260226/Source/WulaFallenEmpire/EventSystem/AI/Agent/VisualInteractionTools.cs#307-329) | 关闭窗口 | Alt+F4 |
|
||||
|
||||
---
|
||||
|
||||
### 3.4 AutonomousAgentLoop (自主Agent循环)
|
||||
|
||||
**路径**: [Agent/AutonomousAgentLoop.cs](file:///C:/Steam/steamapps/common/RimWorld/Mods/3516260226/Source/WulaFallenEmpire/EventSystem/AI/Agent/AutonomousAgentLoop.cs)
|
||||
|
||||
**功能**: 主动模式的核心循环
|
||||
|
||||
**状态**:
|
||||
- `IsRunning`: 是否运行中
|
||||
- `CurrentObjective`: 当前目标
|
||||
- `DecisionCount`: 已执行决策次数
|
||||
|
||||
**关键API**:
|
||||
```csharp
|
||||
public class AutonomousAgentLoop : GameComponent
|
||||
{
|
||||
public static AutonomousAgentLoop Instance;
|
||||
|
||||
// 开始执行目标
|
||||
public void StartObjective(string objective);
|
||||
|
||||
// 停止Agent
|
||||
public void Stop();
|
||||
|
||||
// 事件
|
||||
public event Action<string> OnDecisionMade;
|
||||
public event Action<string> OnObjectiveComplete;
|
||||
}
|
||||
```
|
||||
|
||||
**待完成**: [ExecuteDecision()](file:///C:/Steam/steamapps/common/RimWorld/Mods/3516260226/Source/WulaFallenEmpire/EventSystem/AI/Agent/AutonomousAgentLoop.cs#244-269) 方法需要整合工具执行逻辑
|
||||
|
||||
---
|
||||
|
||||
### 3.5 原生API工具
|
||||
|
||||
| 工具 | 路径 | 功能 | 参数格式 |
|
||||
|------|------|------|----------|
|
||||
| [Tool_GetGameState](file:///C:/Steam/steamapps/common/RimWorld/Mods/3516260226/Source/WulaFallenEmpire/EventSystem/AI/Tools/Tool_GetGameState.cs#8-45) | Tools/ | 获取游戏状态 | `<get_game_state/>` |
|
||||
| [Tool_DesignateMine](file:///C:/Steam/steamapps/common/RimWorld/Mods/3516260226/Source/WulaFallenEmpire/EventSystem/AI/Tools/Tool_DesignateMine.cs#12-139) | Tools/ | 采矿指令 | `<designate_mine><x>数字</x><z>数字</z><radius>可选</radius></designate_mine>` |
|
||||
| [Tool_DraftPawn](file:///C:/Steam/steamapps/common/RimWorld/Mods/3516260226/Source/WulaFallenEmpire/EventSystem/AI/Tools/Tool_DraftPawn.cs#10-105) | Tools/ | 征召殖民者 | `<draft_pawn><pawn_name>名字</pawn_name><draft>true/false</draft></draft_pawn>` |
|
||||
|
||||
---
|
||||
|
||||
## 4. 待完成任务
|
||||
|
||||
### 4.1 模式切换整合 (高优先级)
|
||||
|
||||
**目标**: 在 [AIIntelligenceCore](file:///C:/Steam/steamapps/common/RimWorld/Mods/3516260226/Source/WulaFallenEmpire/EventSystem/AI/AIIntelligenceCore.cs#16-1364) 中实现被动/主动模式切换
|
||||
|
||||
**实现思路**:
|
||||
```csharp
|
||||
// AIIntelligenceCore 中添加
|
||||
private bool _isAgentMode = false;
|
||||
|
||||
public void ProcessUserMessage(string message)
|
||||
{
|
||||
// 检测是否触发主动模式
|
||||
if (IsAgentTrigger(message, out string objective, out float duration))
|
||||
{
|
||||
_isAgentMode = true;
|
||||
AutonomousAgentLoop.Instance.StartObjective(objective);
|
||||
// 设置定时器,duration后自动停止
|
||||
}
|
||||
else
|
||||
{
|
||||
// 正常对话处理
|
||||
RunConversation(message);
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsAgentTrigger(string msg, out string obj, out float dur)
|
||||
{
|
||||
// 匹配模式:
|
||||
// "帮我玩10分钟" → obj="管理殖民地", dur=600
|
||||
// "帮我挖点铁" → obj="采集铁矿", dur=0(无限)
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 4.2 工具执行整合 (高优先级)
|
||||
|
||||
**目标**: 让 `AutonomousAgentLoop.ExecuteDecision()` 能够执行工具
|
||||
|
||||
**当前状态**: 方法体是空的 TODO
|
||||
|
||||
**实现思路**:
|
||||
```csharp
|
||||
private void ExecuteDecision(string decision)
|
||||
{
|
||||
// 1. 检查特殊标记
|
||||
if (decision.Contains("<no_action")) return;
|
||||
if (decision.Contains("<objective_complete"))
|
||||
{
|
||||
OnObjectiveComplete?.Invoke(_currentObjective);
|
||||
Stop();
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 获取工具实例
|
||||
var core = AIIntelligenceCore.Instance;
|
||||
var tools = core.GetAvailableTools();
|
||||
|
||||
// 3. 解析XML工具调用(复用AIIntelligenceCore的逻辑)
|
||||
foreach (var tool in tools)
|
||||
{
|
||||
if (decision.Contains($"<{tool.Name}"))
|
||||
{
|
||||
string result = tool.Execute(decision);
|
||||
WulaLog.Debug($"Tool {tool.Name}: {result}");
|
||||
_lastToolResult = result;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 4.3 AI待办清单 (中优先级)
|
||||
|
||||
**目标**: AI 维护自己的待办清单,持久化到游戏存档
|
||||
|
||||
**设计**:
|
||||
```csharp
|
||||
public class AgentTodoList : IExposable
|
||||
{
|
||||
public List<TodoItem> Items = new List<TodoItem>();
|
||||
|
||||
public void ExposeData()
|
||||
{
|
||||
Scribe_Collections.Look(ref Items, "todoItems", LookMode.Deep);
|
||||
}
|
||||
}
|
||||
|
||||
public class TodoItem : IExposable
|
||||
{
|
||||
public string Description;
|
||||
public bool IsComplete;
|
||||
public int Priority;
|
||||
public int CreatedTick;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 4.4 Qwen-Omni-Realtime 测试 (低优先级)
|
||||
|
||||
**目标**: 测试 WebSocket 流式连接
|
||||
|
||||
**已完成**: [OmniRealtimeClient.cs](file:///C:/Steam/steamapps/common/RimWorld/Mods/3516260226/Source/WulaFallenEmpire/EventSystem/AI/Agent/OmniRealtimeClient.cs) 基础实现
|
||||
|
||||
**待测试**:
|
||||
- WebSocket 连接建立
|
||||
- 图片发送 (`input_image_buffer.append`)
|
||||
- 文本接收 (`response.text.delta`)
|
||||
|
||||
---
|
||||
|
||||
## 5. 关键接口参考
|
||||
|
||||
### 5.1 AITool 基类
|
||||
|
||||
```csharp
|
||||
public abstract class AITool
|
||||
{
|
||||
public abstract string Name { get; }
|
||||
public abstract string Description { get; }
|
||||
public abstract string UsageSchema { get; }
|
||||
public abstract string Execute(string args);
|
||||
|
||||
// 解析XML参数
|
||||
protected Dictionary<string, string> ParseXmlArgs(string xmlContent);
|
||||
}
|
||||
```
|
||||
|
||||
### 5.2 SimpleAIClient API
|
||||
|
||||
```csharp
|
||||
public class SimpleAIClient
|
||||
{
|
||||
public SimpleAIClient(string apiKey, string baseUrl, string model);
|
||||
|
||||
// 文本对话
|
||||
public Task<string> GetChatCompletionAsync(
|
||||
string systemPrompt,
|
||||
List<(string role, string message)> messages,
|
||||
int maxTokens = 1024,
|
||||
float temperature = 0.7f
|
||||
);
|
||||
|
||||
// VLM 视觉分析
|
||||
public Task<string> GetVisionCompletionAsync(
|
||||
string systemPrompt,
|
||||
string userPrompt,
|
||||
string base64Image,
|
||||
int maxTokens = 1024,
|
||||
float temperature = 0.7f
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### 5.3 设置 (WulaFallenEmpireSettings)
|
||||
|
||||
```csharp
|
||||
public class WulaFallenEmpireSettings : ModSettings
|
||||
{
|
||||
// 主模型
|
||||
public string apiKey;
|
||||
public string baseUrl = "https://dashscope.aliyuncs.com/compatible-mode/v1";
|
||||
public string model = "qwen-turbo";
|
||||
|
||||
// VLM 模型
|
||||
public string vlmApiKey;
|
||||
public string vlmBaseUrl;
|
||||
public string vlmModel = "qwen-vl-max";
|
||||
public bool enableVlmFeatures = false;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 开发指南
|
||||
|
||||
### 6.1 添加新工具
|
||||
|
||||
1. 在 [Tools/](file:///C:/Steam/steamapps/common/RimWorld/Mods/3516260226/Source/WulaFallenEmpire/EventSystem/AI/AIIntelligenceCore.cs#310-337) 创建新类继承 [AITool](file:///C:/Steam/steamapps/common/RimWorld/Mods/3516260226/Source/WulaFallenEmpire/EventSystem/AI/Tools/AITool.cs#8-41)
|
||||
2. 实现 [Name](file:///C:/Steam/steamapps/common/RimWorld/Mods/3516260226/Source/WulaFallenEmpire/EventSystem/AI/AIIntelligenceCore.cs#636-642), [Description](file:///C:/Steam/steamapps/common/RimWorld/Mods/3516260226/Source/WulaFallenEmpire/EventSystem/AI/Agent/StateObserver.cs#156-187), `UsageSchema`, [Execute](file:///C:/Steam/steamapps/common/RimWorld/Mods/3516260226/Source/WulaFallenEmpire/EventSystem/AI/Tools/Tool_VisualClick.cs#133-165)
|
||||
3. 在 `AIIntelligenceCore.InitializeTools()` 中注册
|
||||
|
||||
```csharp
|
||||
// 示例:Tool_BuildWall.cs
|
||||
public class Tool_BuildWall : AITool
|
||||
{
|
||||
public override string Name => "build_wall";
|
||||
public override string Description => "在指定位置放置墙壁蓝图";
|
||||
public override string UsageSchema => "<build_wall><x>X</x><z>Z</z><stuff>材料</stuff></build_wall>";
|
||||
|
||||
public override string Execute(string args)
|
||||
{
|
||||
var dict = ParseXmlArgs(args);
|
||||
// 实现建造逻辑
|
||||
// GenConstruct.PlaceBlueprintForBuild(...)
|
||||
return "Success: 墙壁蓝图已放置";
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 6.2 调试技巧
|
||||
|
||||
- 使用 `WulaLog.Debug()` 输出日志
|
||||
- 检查 RimWorld 的 `Player.log` 文件
|
||||
- 在开发者模式下 `Prefs.DevMode = true` 显示更多信息
|
||||
|
||||
### 6.3 常见问题
|
||||
|
||||
**Q: .NET Framework 4.8 兼容性问题**
|
||||
- 不支持 `TakeLast()` → 使用 `Skip(list.Count - n)`
|
||||
- 不支持 `string.Contains(x, StringComparison)` → 使用 `IndexOf`
|
||||
|
||||
**Q: Unity 主线程限制**
|
||||
- 异步操作结果需要回到主线程执行
|
||||
- 使用 `LongEventHandler.ExecuteWhenFinished(() => { ... })`
|
||||
|
||||
---
|
||||
|
||||
## 7. 参考资源
|
||||
|
||||
- [RimWorld Modding Wiki](https://rimworldwiki.com/wiki/Modding)
|
||||
- [Harmony Patching](https://harmony.pardeike.net/)
|
||||
- [阿里云百炼 API](https://help.aliyun.com/zh/model-studio/)
|
||||
- [Qwen-Omni 文档](https://help.aliyun.com/zh/model-studio/user-guide/qwen-omni)
|
||||
|
||||
---
|
||||
|
||||
**文档版本**: v1.0
|
||||
**更新时间**: 2025-12-27
|
||||
**作者**: Gemini AI Agent
|
||||
@@ -1,3 +0,0 @@
|
||||
https://api.xiaomimimo.com/v1
|
||||
mimo-v2-flash
|
||||
sk-cuwai2jix0zwrghj307pmvdpmtoc74j4uv9bejglxcs89tnx
|
||||
@@ -1,150 +0,0 @@
|
||||
# WulaLink UI 修复任务 - Codex 交接文档
|
||||
|
||||
## 项目概述
|
||||
RimWorld Mod: [WulaFallenEmpire](file:///C:/Steam/steamapps/common/RimWorld/Mods/3516260226/Source/WulaFallenEmpire)
|
||||
目标: 实现 MomoTalk 风格的悬浮 AI 聊天 UI (WulaLink),同时确保原有大 UI 不被破坏。
|
||||
|
||||
## 关键文件路径
|
||||
```
|
||||
C:\Steam\steamapps\common\RimWorld\Mods\3516260226\Source\WulaFallenEmpire\
|
||||
├── EventSystem\
|
||||
│ ├── Dialog_CustomDisplay.cs # 基类,包含正确的按钮样式和布局逻辑
|
||||
│ └── AI\
|
||||
│ ├── AIIntelligenceCore.cs # AI 核心逻辑 (WorldComponent) - 已完成
|
||||
│ ├── DebugActions_WulaLink.cs # Debug 入口
|
||||
│ └── UI\
|
||||
│ ├── Dialog_AIConversation.cs # 大 UI - 需要修复布局
|
||||
│ ├── Overlay_WulaLink.cs # 小悬浮框 - 需要修复样式
|
||||
│ ├── Overlay_WulaLink_Notification.cs # 通知弹窗 - 已完成
|
||||
│ └── WulaLinkStyles.cs # 样式定义 - 需要调整颜色
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 问题 1: 大 UI (Dialog_AIConversation) 布局损坏
|
||||
|
||||
### 现状
|
||||
[Dialog_AIConversation](file:///C:/Steam/steamapps/common/RimWorld/Mods/3516260226/Source/WulaFallenEmpire/EventSystem/AI/UI/Dialog_AIConversation.cs#108-133) 继承自 [Dialog_CustomDisplay](file:///C:/Steam/steamapps/common/RimWorld/Mods/3516260226/Source/WulaFallenEmpire/EventSystem/Dialog_CustomDisplay.cs#10-668),但 [DoWindowContents](file:///C:/Steam/steamapps/common/RimWorld/Mods/3516260226/Source/WulaFallenEmpire/EventSystem/AI/UI/Dialog_AIConversation.cs#1177-1328) 被完全重写,丢失了原有的沉浸式布局。
|
||||
|
||||
### 期望效果 (参考用户截图)
|
||||
- 左侧: 大尺寸立绘 (占据约 60% 窗口)
|
||||
- 右下: 半透明暗红色面板,包含:
|
||||
- 标题 "「军团」,P.I.A"
|
||||
- 描述文本区域
|
||||
- 底部按钮 "打开通讯频道" (使用 [DrawCustomButton](file:///C:/Steam/steamapps/common/RimWorld/Mods/3516260226/Source/WulaFallenEmpire/EventSystem/Dialog_CustomDisplay.cs#388-449) 样式)
|
||||
- 点击按钮后进入聊天模式 (显示对话历史)
|
||||
|
||||
### 修复方案
|
||||
恢复 `base.DoWindowContents(inRect)` 的调用,或手动复制 `Dialog_CustomDisplay.DoWindowContents` 的布局逻辑。
|
||||
|
||||
关键代码参考 ([Dialog_CustomDisplay.cs](file:///C:/Steam/steamapps/common/RimWorld/Mods/3516260226/Source/WulaFallenEmpire/EventSystem/Dialog_CustomDisplay.cs) 第 144-280 行):
|
||||
```csharp
|
||||
// 1. 绘制背景
|
||||
if (background != null) GUI.DrawTexture(inRect, background, ScaleMode.StretchToFill);
|
||||
|
||||
// 2. 立绘 (Config.showPortrait)
|
||||
Rect portraitRect = Config.GetScaledRect(Config.portraitSize, inRect);
|
||||
|
||||
// 3. 标题 (Config.showLabel)
|
||||
Rect labelRect = Config.GetScaledRect(Config.labelSize, inRect);
|
||||
|
||||
// 4. 描述 (Config.showDescriptions)
|
||||
Rect descriptionRect = Config.GetScaledRect(Config.descriptionsSize, inRect);
|
||||
|
||||
// 5. 选项按钮 (Config.showOptions)
|
||||
Rect optionsRect = Config.GetScaledRect(Config.optionsListSize, inRect);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 问题 2: 小悬浮框 (Overlay_WulaLink) 样式问题
|
||||
|
||||
### 2.1 背景颜色错误
|
||||
**现状**: 使用纯黑背景 `new Color(10, 10, 12, 255)`
|
||||
**期望**: 半透明暗红色,与大 UI 一致
|
||||
|
||||
修改 [WulaLinkStyles.cs](file:///C:/Steam/steamapps/common/RimWorld/Mods/3516260226/Source/WulaFallenEmpire/EventSystem/AI/UI/WulaLinkStyles.cs):
|
||||
```csharp
|
||||
// 修改前
|
||||
public static readonly Color BackgroundColor = new Color32(10, 10, 12, 255);
|
||||
|
||||
// 修改后
|
||||
public static readonly Color BackgroundColor = new Color(0.2f, 0.05f, 0.05f, 0.85f); // 半透明暗红
|
||||
```
|
||||
|
||||
### 2.2 消息间距过大
|
||||
**原因**: `role == "tool"` 的消息也被渲染,占用空间但不显示内容。
|
||||
|
||||
修改 [Overlay_WulaLink.cs](file:///C:/Steam/steamapps/common/RimWorld/Mods/3516260226/Source/WulaFallenEmpire/EventSystem/AI/UI/Overlay_WulaLink.cs) 的 [DrawMessageList](file:///C:/Steam/steamapps/common/RimWorld/Mods/3516260226/Source/WulaFallenEmpire/EventSystem/AI/UI/Overlay_WulaLink.cs#265-344) 方法:
|
||||
```csharp
|
||||
// 在 foreach 循环中添加过滤
|
||||
foreach (var msg in history)
|
||||
{
|
||||
// 跳过工具调用消息
|
||||
if (msg.role == "tool") continue;
|
||||
|
||||
// ... 其余渲染逻辑
|
||||
}
|
||||
```
|
||||
|
||||
### 2.3 气泡无圆角
|
||||
**问题**: RimWorld 原生 `Widgets.DrawBoxSolid` 不支持圆角。
|
||||
**方案**:
|
||||
- 方案 A: 使用 9-slice 圆角贴图 (`Textures/UI/BubbleRounded.png`)
|
||||
- 方案 B: 接受直角,但添加边框使其更精致
|
||||
|
||||
### 2.4 头像无圆形处理
|
||||
**方案**: 使用圆形遮罩贴图覆盖在头像上,或创建 `Textures/UI/AvatarMask.png`
|
||||
|
||||
### 2.5 按钮样式不一致
|
||||
**现状**: 使用默认 `Widgets.ButtonText`
|
||||
**期望**: 使用 `Dialog_CustomDisplay.DrawCustomButton` 样式
|
||||
|
||||
修改 [Overlay_WulaLink.cs](file:///C:/Steam/steamapps/common/RimWorld/Mods/3516260226/Source/WulaFallenEmpire/EventSystem/AI/UI/Overlay_WulaLink.cs) 的 [DrawFooter](file:///C:/Steam/steamapps/common/RimWorld/Mods/3516260226/Source/WulaFallenEmpire/EventSystem/AI/UI/Overlay_WulaLink.cs#345-385):
|
||||
```csharp
|
||||
// 修改前
|
||||
if (Widgets.ButtonText(btnRect, ">"))
|
||||
|
||||
// 修改后 (需要静态化或复制 DrawCustomButton 方法)
|
||||
DrawCustomButton(btnRect, ">", isEnabled: true);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 问题 3: 样式统一 (WulaLinkStyles.cs)
|
||||
|
||||
需要调整以下颜色以匹配大 UI 的"军团"风格:
|
||||
```csharp
|
||||
// Header: 深红色,与大 UI 标题栏一致
|
||||
public static readonly Color HeaderColor = new Color(0.5f, 0.15f, 0.15f, 1f);
|
||||
|
||||
// 背景: 半透明暗红
|
||||
public static readonly Color BackgroundColor = new Color(0.2f, 0.05f, 0.05f, 0.85f);
|
||||
|
||||
// AI 气泡: 深灰带红色边框
|
||||
public static readonly Color StudentBubbleColor = new Color(0.15f, 0.12f, 0.12f, 1f);
|
||||
public static readonly Color StudentStrokeColor = new Color(0.6f, 0.2f, 0.2f, 1f);
|
||||
|
||||
// 玩家气泡: 暗红色
|
||||
public static readonly Color SenseiBubbleColor = new Color(0.4f, 0.15f, 0.15f, 1f);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 验证清单
|
||||
- [ ] 大 UI 显示正确的立绘、标题、描述和按钮布局
|
||||
- [ ] 小悬浮框背景为半透明暗红色
|
||||
- [ ] 消息之间无多余空白
|
||||
- [ ] 按钮使用暗红色自定义样式
|
||||
- [ ] (可选) 气泡有圆角
|
||||
- [ ] (可选) 头像为圆形
|
||||
|
||||
## 编译命令
|
||||
```powershell
|
||||
dotnet build C:\Steam\steamapps\common\RimWorld\Mods\3516260226\Source\WulaFallenEmpire\WulaFallenEmpire.csproj
|
||||
```
|
||||
|
||||
## 测试入口
|
||||
1. 启动 RimWorld,加载存档
|
||||
2. 打开 Debug Actions Menu
|
||||
3. 搜索 "WulaLink" 并点击 "Open WulaLink UI"
|
||||
@@ -1,140 +0,0 @@
|
||||
# WulaLink 任务交接文档
|
||||
|
||||
## 当前状态:需要创建 AIIntelligenceCore.cs
|
||||
|
||||
### 背景
|
||||
WulaLink 是一个 RimWorld Mod 中的 AI 对话系统,包含两个 UI:
|
||||
1. **大 UI** (`Dialog_AIConversation`) - 全屏对话窗口
|
||||
2. **小 UI** (`Overlay_WulaLink`) - 悬浮对话窗口
|
||||
|
||||
### 已完成的操作
|
||||
1. ✅ 恢复了 `Dialog_AIConversation.cs` 为旧版自包含版本(从备份文件 `Tools/using System;.cs` 复制)
|
||||
2. ✅ 删除了损坏的 `AIIntelligenceCore.cs`
|
||||
3. ✅ 重写了 `WulaLinkStyles.cs`(颜色主题配置)
|
||||
|
||||
### 当前编译错误
|
||||
```
|
||||
error CS0246: 未能找到类型或命名空间名"AIIntelligenceCore"
|
||||
```
|
||||
|
||||
以下文件引用了 `AIIntelligenceCore`:
|
||||
- `Overlay_WulaLink.cs` (第13行, 第94行)
|
||||
- `Overlay_WulaLink_Notification.cs` (第89行)
|
||||
- `Tool_ChangeExpression.cs` (第24行)
|
||||
- `Tool_GetRecentNotifications.cs` (第113行)
|
||||
|
||||
---
|
||||
|
||||
## 需要完成的任务
|
||||
|
||||
### 任务:创建 AIIntelligenceCore.cs
|
||||
|
||||
**路径**: `Source/WulaFallenEmpire/EventSystem/AI/AIIntelligenceCore.cs`
|
||||
|
||||
**要求**:
|
||||
1. 必须是 `WorldComponent`,类名 `AIIntelligenceCore`
|
||||
2. 提供 `static Instance` 属性供外部访问
|
||||
3. 从 `Dialog_AIConversation`(备份文件 `Tools/using System;.cs`)提取 AI 核心逻辑
|
||||
4. 暴露事件/回调供 UI 使用
|
||||
|
||||
**必须包含的公共接口**(根据现有代码引用):
|
||||
```csharp
|
||||
public class AIIntelligenceCore : WorldComponent
|
||||
{
|
||||
// 静态实例
|
||||
public static AIIntelligenceCore Instance { get; private set; }
|
||||
|
||||
// 事件回调
|
||||
public event Action<string> OnMessageReceived;
|
||||
public event Action<bool> OnThinkingStateChanged;
|
||||
public event Action<int> OnExpressionChanged;
|
||||
|
||||
// 公共属性
|
||||
public int ExpressionId { get; }
|
||||
public bool IsThinking { get; }
|
||||
|
||||
// 公共方法
|
||||
public void InitializeConversation(string eventDefName);
|
||||
public List<(string role, string message)> GetHistorySnapshot();
|
||||
public void SetExpression(int id); // 供 Tool_ChangeExpression 调用
|
||||
public void SendMessage(string text); // 供小 UI 调用
|
||||
}
|
||||
```
|
||||
|
||||
**参考代码**:
|
||||
- 备份文件 `Tools/using System;.cs` 包含完整的 AI 逻辑(1549行)
|
||||
- 核心方法包括:
|
||||
- `RunPhasedRequestAsync()` - 3阶段请求处理
|
||||
- `ExecuteXmlToolsForPhase()` - 工具执行
|
||||
- `BuildToolContext()` / `BuildReplyHistory()` - 上下文构建
|
||||
- `ParseResponse()` - 响应解析
|
||||
- `GetSystemInstruction()` / `GetToolSystemInstruction()` - 提示词生成
|
||||
|
||||
---
|
||||
|
||||
## 关键文件路径
|
||||
|
||||
```
|
||||
C:\Steam\steamapps\common\RimWorld\Mods\3516260226\
|
||||
├── Tools\
|
||||
│ └── using System;.cs # 旧版 Dialog_AIConversation 备份(包含完整 AI 逻辑)
|
||||
└── Source\WulaFallenEmpire\EventSystem\AI\
|
||||
├── AIIntelligenceCore.cs # 【需要创建】
|
||||
├── AIHistoryManager.cs # 历史记录管理
|
||||
├── AIMemoryManager.cs # 记忆管理
|
||||
├── SimpleAIClient.cs # API 客户端
|
||||
├── Tools\ # AI 工具目录
|
||||
│ ├── Tool_SpawnResources.cs
|
||||
│ ├── Tool_SendReinforcement.cs
|
||||
│ └── ... (其他工具)
|
||||
└── UI\
|
||||
├── Dialog_AIConversation.cs # 大 UI(已恢复)
|
||||
├── Overlay_WulaLink.cs # 小 UI(需要修复引用)
|
||||
├── Overlay_WulaLink_Notification.cs
|
||||
└── WulaLinkStyles.cs # 样式配置(已重写)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 编译命令
|
||||
|
||||
```powershell
|
||||
dotnet build C:\Steam\steamapps\common\RimWorld\Mods\3516260226\Source\WulaFallenEmpire\WulaFallenEmpire.csproj
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 架构说明
|
||||
|
||||
### 目标架构
|
||||
```
|
||||
┌─────────────────────────────────────┐
|
||||
│ AIIntelligenceCore │ ← WorldComponent (核心逻辑)
|
||||
│ - 历史记录管理 │
|
||||
│ - AI 请求处理 (3阶段) │
|
||||
│ - 工具执行 │
|
||||
│ - 表情/状态管理 │
|
||||
└──────────────┬──────────────────────┘
|
||||
│ 事件回调
|
||||
┌──────────┴──────────┐
|
||||
▼ ▼
|
||||
┌─────────────┐ ┌──────────────┐
|
||||
│ Dialog_AI │ │ Overlay_ │
|
||||
│ Conversation│ │ WulaLink │
|
||||
│ (大 UI) │ │ (小 UI) │
|
||||
└─────────────┘ └──────────────┘
|
||||
```
|
||||
|
||||
### 关键点
|
||||
1. `Dialog_AIConversation` 目前是**自包含**的(既有 UI 也有 AI 逻辑)
|
||||
2. `Overlay_WulaLink` 需要通过 `AIIntelligenceCore` 获取数据
|
||||
3. 两个 UI 可以共享同一个 `AIIntelligenceCore` 实例
|
||||
|
||||
---
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. **不要使用 PowerShell Get-Content 读取文件** - 会显示乱码,请使用 `view_file` 工具
|
||||
2. **备份文件编码正常** - `Tools/using System;.cs` 可以正常读取
|
||||
3. **命名空间**:`WulaFallenEmpire.EventSystem.AI`
|
||||
4. **依赖项**:需要引用 `SimpleAIClient`、`AIHistoryManager`、`AITool` 等现有类
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user