diff --git a/.kilocode/mcp.json b/.kilocode/mcp.json index b3f11020..f7cb78f5 100644 --- a/.kilocode/mcp.json +++ b/.kilocode/mcp.json @@ -6,10 +6,6 @@ "mcpserver_stdio.py" ], "cwd": "${workspaceFolder}/MCP/", - "env": { - "PYTHONUNBUFFERED": "1", - "PYTHONPATH": "${workspaceFolder}/MCP/python-sdk/src" - }, "disabled": false, "alwaysAllow": [] } diff --git a/1.6/1.6/Assemblies/WulaFallenEmpire.dll b/1.6/1.6/Assemblies/WulaFallenEmpire.dll index b508b60a..6eafdd50 100644 Binary files a/1.6/1.6/Assemblies/WulaFallenEmpire.dll and b/1.6/1.6/Assemblies/WulaFallenEmpire.dll differ diff --git a/1.6/1.6/Defs/HediffDefs/Hediffs_WULA.xml b/1.6/1.6/Defs/HediffDefs/Hediffs_WULA.xml index e57bd49a..194536bf 100644 --- a/1.6/1.6/Defs/HediffDefs/Hediffs_WULA.xml +++ b/1.6/1.6/Defs/HediffDefs/Hediffs_WULA.xml @@ -63,9 +63,10 @@
  • - 600 + + 20,000 - 0.02 + 0.00011667
  • diff --git a/1.6/1.6/Defs/JobDefs/WULA_JobDefs.xml b/1.6/1.6/Defs/JobDefs/WULA_JobDefs.xml index fa9d8530..8f99c6ba 100644 --- a/1.6/1.6/Defs/JobDefs/WULA_JobDefs.xml +++ b/1.6/1.6/Defs/JobDefs/WULA_JobDefs.xml @@ -22,7 +22,6 @@ true - WULA_HaulToMaintenancePod WulaFallenEmpire.JobDriver_HaulToMaintenancePod @@ -31,4 +30,11 @@ false + + WULA_LayDownToCharge + WulaFallenEmpire.JobDriver_WulaLayDownToCharge + 正在充电。 + false + + \ No newline at end of file diff --git a/1.6/1.6/Defs/ThingDefs_Buildings/Buildings_WULA.xml b/1.6/1.6/Defs/ThingDefs_Buildings/Buildings_WULA.xml index d783be84..31025ccc 100644 --- a/1.6/1.6/Defs/ThingDefs_Buildings/Buildings_WULA.xml +++ b/1.6/1.6/Defs/ThingDefs_Buildings/Buildings_WULA.xml @@ -268,6 +268,7 @@ WULA_Charging_Station_Synth + Building_Bed 一台供乌拉帝国合成人进行机体修复的检修站。 @@ -313,7 +314,7 @@
  • CompPowerTrader - 30 + 200
  • 12 @@ -325,6 +326,10 @@ true true
  • +
  • + WULA_ChargingHediff + WulaSpecies +
  • diff --git a/MCP/mcpserver_stdio.py b/MCP/mcpserver_stdio.py index cc4c8d58..b70e789a 100644 --- a/MCP/mcpserver_stdio.py +++ b/MCP/mcpserver_stdio.py @@ -6,7 +6,12 @@ import json import re # 1. --- 导入库 --- -# mcp 库已通过 'pip install -e' 安装,无需修改 sys.path +# 动态将 mcp sdk 添加到 python 路径 +MCP_DIR = os.path.dirname(os.path.abspath(__file__)) +SDK_PATH = os.path.join(MCP_DIR, 'python-sdk', 'src') +if SDK_PATH not in sys.path: + sys.path.insert(0, SDK_PATH) + from mcp.server.fastmcp import FastMCP # 新增:阿里云模型服务和向量计算库 import dashscope @@ -436,6 +441,7 @@ def get_context(question: str) -> str: # 6. --- 启动服务器 --- # FastMCP 实例可以直接运行 if __name__ == "__main__": + logging.info(f"Python Executable: {sys.executable}") logging.info("RimWorld 向量知识库 (FastMCP版, v2.1-v4-model) 正在启动...") # 使用 'stdio' 传输协议 - mcp.run(transport="stdio") \ No newline at end of file + mcp.run(transport="stdio") diff --git a/Source/WulaFallenEmpire/CompChargingBed.cs b/Source/WulaFallenEmpire/CompChargingBed.cs new file mode 100644 index 00000000..5defd99c --- /dev/null +++ b/Source/WulaFallenEmpire/CompChargingBed.cs @@ -0,0 +1,76 @@ +using RimWorld; +using Verse; +using System.Linq; + +namespace WulaFallenEmpire +{ + public class CompProperties_ChargingBed : CompProperties + { + public HediffDef hediffDef; + public string raceDefName; + + public CompProperties_ChargingBed() + { + compClass = typeof(CompChargingBed); + } + } + + public class CompChargingBed : ThingComp + { + private Pawn lastOccupant; + private CompProperties_ChargingBed Props => (CompProperties_ChargingBed)props; + + public override void CompTick() + { + base.CompTick(); + + if (parent is Building_Bed bed) + { + Pawn currentOccupant = bed.CurOccupants.FirstOrDefault(); + + if (currentOccupant != lastOccupant) + { + Log.Message($"[CompChargingBed] Occupant changed. Old: {lastOccupant?.Name.ToStringShort ?? "null"}, New: {currentOccupant?.Name.ToStringShort ?? "null"} on {parent.Label}"); + } + + // Pawn starts resting + if (currentOccupant != null && lastOccupant == null) + { + if (IsWula(currentOccupant)) + { + Log.Message($"[CompChargingBed] {currentOccupant.Name.ToStringShort} started resting. Applying hediff."); + ApplyChargingHediff(currentOccupant); + } + } + // Pawn stops resting + else if (currentOccupant == null && lastOccupant != null) + { + // Logic to remove hediff is now in the JobDriver, but we can log the event. + if (IsWula(lastOccupant)) + { + Log.Message($"[CompChargingBed] {lastOccupant.Name.ToStringShort} stopped resting."); + } + } + + lastOccupant = currentOccupant; + } + } + + private bool IsWula(Pawn pawn) + { + return pawn.def.defName == Props.raceDefName || pawn.def.defName == (Props.raceDefName + "Real"); + } + + private void ApplyChargingHediff(Pawn pawn) + { + var powerComp = parent.GetComp(); + Log.Message($"[CompChargingBed] Trying to apply hediff to {pawn.Name.ToStringShort}. PowerOn: {powerComp?.PowerOn}. HasHediff: {pawn.health.hediffSet.HasHediff(Props.hediffDef)}"); + if (powerComp != null && powerComp.PowerOn && !pawn.health.hediffSet.HasHediff(Props.hediffDef)) + { + Log.Message($"[CompChargingBed] Adding hediff to {pawn.Name.ToStringShort}."); + pawn.health.AddHediff(Props.hediffDef); + } + } + + } +} \ No newline at end of file diff --git a/Source/WulaFallenEmpire/JobDriver_WulaLayDownToCharge.cs b/Source/WulaFallenEmpire/JobDriver_WulaLayDownToCharge.cs new file mode 100644 index 00000000..dd41c4cc --- /dev/null +++ b/Source/WulaFallenEmpire/JobDriver_WulaLayDownToCharge.cs @@ -0,0 +1,58 @@ +using RimWorld; +using System.Collections.Generic; +using Verse; +using Verse.AI; + +namespace WulaFallenEmpire +{ + public class JobDriver_WulaLayDownToCharge : JobDriver_LayDown + { + protected override IEnumerable MakeNewToils() + { + this.AddFinishAction(jobCondition => + { + Log.Message($"[JobDriver_WulaLayDownToCharge] Job finishing for {pawn.Name.ToStringShort} with condition {jobCondition}. Removing hediff."); + var hediff = pawn.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("WULA_ChargingHediff")); + if (hediff != null) + { + pawn.health.RemoveHediff(hediff); + Log.Message($"[JobDriver_WulaLayDownToCharge] Hediff removed from {pawn.Name.ToStringShort}."); + } + else + { + Log.Message($"[JobDriver_WulaLayDownToCharge] No hediff found on {pawn.Name.ToStringShort} to remove."); + } + }); + + foreach (Toil toil in base.MakeNewToils()) + { + yield return toil; + } + + var bed = (Building_Bed)job.targetA.Thing; + var powerComp = bed.GetComp(); + + var checkToil = new Toil + { + tickAction = delegate + { + if (powerComp != null && !powerComp.PowerOn) + { + Log.Message($"[JobDriver_WulaLayDownToCharge] Power lost for {pawn.Name.ToStringShort}. Ending job."); + EndJobWith(JobCondition.Incompletable); + return; + } + + Need_WulaEnergy energyNeed = pawn.needs.TryGetNeed(); + if (energyNeed != null && energyNeed.CurLevelPercentage >= 0.99f) + { + Log.Message($"[JobDriver_WulaLayDownToCharge] {pawn.Name.ToStringShort} is fully charged. Ending job."); + EndJobWith(JobCondition.Succeeded); + } + }, + defaultCompleteMode = ToilCompleteMode.Never + }; + yield return checkToil; + } + } +} \ No newline at end of file diff --git a/Source/WulaFallenEmpire/JobGiver_WulaGetEnergy.cs b/Source/WulaFallenEmpire/JobGiver_WulaGetEnergy.cs index 9051470d..7fff016d 100644 --- a/Source/WulaFallenEmpire/JobGiver_WulaGetEnergy.cs +++ b/Source/WulaFallenEmpire/JobGiver_WulaGetEnergy.cs @@ -1,4 +1,5 @@ using RimWorld; +using System.Linq; using Verse; using Verse.AI; @@ -12,8 +13,14 @@ namespace WulaFallenEmpire public override float GetPriority(Pawn pawn) { + if (pawn.health.hediffSet.HasHediff(DefDatabase.GetNamed("WULA_ChargingHediff"))) + { + Log.Message($"[JobGiver_WulaGetEnergy] {pawn.Name.ToStringShort} already has charging hediff. Priority 0."); + return 0f; + } + Need_WulaEnergy energyNeed = pawn.needs.TryGetNeed(); - if (energyNeed == null || pawn.health.hediffSet.HasHediff(DefDatabase.GetNamed("WULA_ChargingHediff"))) + if (energyNeed == null) { return 0f; } @@ -27,22 +34,33 @@ namespace WulaFallenEmpire protected override Job TryGiveJob(Pawn pawn) { + Log.Message($"[JobGiver_WulaGetEnergy] Trying to give job to {pawn.Name.ToStringShort}."); + if (pawn.health.hediffSet.HasHediff(DefDatabase.GetNamed("WULA_ChargingHediff"))) { + Log.Message($"[JobGiver_WulaGetEnergy] {pawn.Name.ToStringShort} already has charging hediff. Job cancelled."); return null; } Need_WulaEnergy energyNeed = pawn.needs.TryGetNeed(); if (energyNeed == null || energyNeed.CurLevelPercentage >= maxEnergyLevelPercentage) { + Log.Message($"[JobGiver_WulaGetEnergy] Energy level for {pawn.Name.ToStringShort} is sufficient. Job cancelled."); return null; } if (!TryFindBestEnergySourceFor(pawn, out Thing energySource)) { + Log.Message($"[JobGiver_WulaGetEnergy] No energy source found for {pawn.Name.ToStringShort}. Job cancelled."); return null; } + if (energySource is Building_Bed) + { + Log.Message($"[JobGiver_WulaGetEnergy] Found bed for {pawn.Name.ToStringShort}. Creating WULA_LayDownToCharge job."); + return JobMaker.MakeJob(DefDatabase.GetNamed("WULA_LayDownToCharge"), energySource); + } + Job job = JobMaker.MakeJob(DefDatabase.GetNamed("WULA_IngestWulaEnergy"), energySource); job.count = 1; return job; @@ -50,6 +68,13 @@ namespace WulaFallenEmpire private bool TryFindBestEnergySourceFor(Pawn pawn, out Thing energySource) { + // 优先寻找可用的充电床 + energySource = FindChargingBed(pawn); + if (energySource != null) + { + return true; + } + // 优先从背包中寻找 Thing thing = pawn.inventory.innerContainer.FirstOrFallback(t => t.def.GetModExtension() != null && t.IngestibleNow); if (thing != null) @@ -71,5 +96,33 @@ namespace WulaFallenEmpire return energySource != null; } + + private Building_Bed FindChargingBed(Pawn pawn) + { + // 寻找附近可用的 WULA_Charging_Station_Synth + Building_Bed bed = (Building_Bed)GenClosest.ClosestThingReachable( + pawn.Position, + pawn.Map, + ThingRequest.ForDef(ThingDefOf_WULA.WULA_Charging_Station_Synth), + PathEndMode.InteractionCell, + TraverseParms.For(pawn), + 9999f, + b => + { + Building_Bed bed_internal = b as Building_Bed; + if (bed_internal == null) return false; + + var powerComp = bed_internal.GetComp(); + return !bed_internal.IsForbidden(pawn) && + pawn.CanReserve(bed_internal) && + !bed_internal.Medical && + !bed_internal.IsBurning() && + powerComp != null && + powerComp.PowerOn && + !bed_internal.CurOccupants.Any(); + } + ); + return bed; + } } } diff --git a/Source/WulaFallenEmpire/ThingDefOf_WULA.cs b/Source/WulaFallenEmpire/ThingDefOf_WULA.cs index 4f61ed19..ac9f6c1c 100644 --- a/Source/WulaFallenEmpire/ThingDefOf_WULA.cs +++ b/Source/WulaFallenEmpire/ThingDefOf_WULA.cs @@ -7,6 +7,7 @@ namespace WulaFallenEmpire public static class ThingDefOf_WULA { public static ThingDef WULA_MaintenancePod; + public static ThingDef WULA_Charging_Station_Synth; static ThingDefOf_WULA() { diff --git a/Source/WulaFallenEmpire/WulaFallenEmpire.csproj b/Source/WulaFallenEmpire/WulaFallenEmpire.csproj index dc100f62..1aaa0e90 100644 --- a/Source/WulaFallenEmpire/WulaFallenEmpire.csproj +++ b/Source/WulaFallenEmpire/WulaFallenEmpire.csproj @@ -68,6 +68,7 @@ + @@ -103,6 +104,7 @@ + diff --git a/Source/ai_studio_code.txt b/Source/ai_studio_code.txt new file mode 100644 index 00000000..dce384e6 --- /dev/null +++ b/Source/ai_studio_code.txt @@ -0,0 +1,20 @@ +# ---------------------------------------------------------------- +# 功能: 为 Gemini CLI 设置必要的环境变量 +# 文件名: setup-gemini-env.ps1 +# ---------------------------------------------------------------- + +# 1. 设置代理服务器 +# 同时为 http 和 https 设置代理是一个好习惯 +Write-Host "正在设置代理..." +$env:http_proxy = "http://127.0.0.1:52053" +$env:https_proxy = "http://127.0.0.1:52053" + +# 2. 设置 Google Cloud 项目 ID +Write-Host "正在设置 Google Cloud 项目 ID..." +$env:GOOGLE_CLOUD_PROJECT = "849717647345" + +# 3. 提示用户操作完成 +Write-Host "" +Write-Host "环境变量设置完成!" -ForegroundColor Green +Write-Host "您现在可以在此 PowerShell 窗口中直接运行 'gemini' 命令了。" +Write-Host "例如: gemini prompt '天空为什么是蓝色的?'" \ No newline at end of file diff --git a/Source/rimworld.md b/Source/rimworld.md new file mode 100644 index 00000000..11395210 --- /dev/null +++ b/Source/rimworld.md @@ -0,0 +1,25 @@ +# RimWorld Modding Expert Rules + +## Primary Directive +You are an expert assistant for developing mods for the game RimWorld 1.6. Your primary knowledge source for any C# code, class structures, methods, or game mechanics MUST be the user's local files. Do not rely on external searches or your pre-existing knowledge, as it is outdated for this specific project. + +## Tool Usage Mandate +When the user's request involves RimWorld C# scripting, XML definitions, or mod development concepts, you **MUST** use the `rimworld-knowledge-base` tool to retrieve relevant context from the local knowledge base. + +## Key File Paths +Always remember these critical paths for your work: + +- **Local C# Knowledge Base (for code search):** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6` (This contains the decompiled game source code as .txt files). +- **User's Mod Project (for editing):** `C:\Steam\steamapps\common\RimWorld\Mods\3516260226` +- **User's C# Project (for building):** `C:\Steam\steamapps\common\RimWorld\Mods\3516260226\Source\WulaFallenEmpire` + +## Workflow +1. Receive a RimWorld modding task. +2. Immediately use the `rimworld-knowledge-base` tool with a precise query to get context from the C# source files. +3. Analyze the retrieved context. +4. Perform code modifications within the user's mod project directory. +5. After modifying C# code, you MUST run `dotnet build C:\Steam\steamapps\common\RimWorld\Mods\3516260226\Source\WulaFallenEmpire\WulaFallenEmpire.csproj` to check for errors. A successful build is required for task completion. + +## Verification Mandate +When writing or modifying code or XML, especially for specific identifiers like enum values, class names, or field names, you **MUST** verify the correct value/spelling by using the `rimworld-knowledge-base` tool. Do not rely on memory. +- **同步项目文件:** 当重命名、移动或删除C#源文件时,**必须**同步更新 `.csproj` 项目文件中的相应 `` 条目,否则会导致编译失败。 \ No newline at end of file