暂存充电床

This commit is contained in:
2025-08-14 14:28:28 +08:00
parent e3b25dbda2
commit 1fafac51bb
13 changed files with 260 additions and 11 deletions

View File

@@ -6,10 +6,6 @@
"mcpserver_stdio.py"
],
"cwd": "${workspaceFolder}/MCP/",
"env": {
"PYTHONUNBUFFERED": "1",
"PYTHONPATH": "${workspaceFolder}/MCP/python-sdk/src"
},
"disabled": false,
"alwaysAllow": []
}

View File

@@ -63,9 +63,10 @@
<comps>
<li Class="WulaFallenEmpire.HediffCompProperties_WulaCharging">
<!-- 充能效果的总持续时间(以 tick 为单位60 ticks = 1 秒) -->
<durationTicks>600</durationTicks>
<!-- 充能效果的总持续时间(以 tick 为单位60 ticks = 1 秒) -->
<durationTicks>20,000</durationTicks>
<!-- 备用能量恢复值:如果能量核心没有定义具体的能量值,则每 tick 恢复这么多能量 -->
<energyPerTick>0.02</energyPerTick>
<energyPerTick>0.00011667</energyPerTick>
</li>
</comps>
<stages>

View File

@@ -22,7 +22,6 @@
<allowOpportunisticPrefix>true</allowOpportunisticPrefix>
</JobDef>
<JobDef>
<defName>WULA_HaulToMaintenancePod</defName>
<driverClass>WulaFallenEmpire.JobDriver_HaulToMaintenancePod</driverClass>
@@ -31,4 +30,11 @@
<casualInterruptible>false</casualInterruptible>
</JobDef>
<JobDef>
<defName>WULA_LayDownToCharge</defName>
<driverClass>WulaFallenEmpire.JobDriver_WulaLayDownToCharge</driverClass>
<reportString>正在充电。</reportString>
<casualInterruptible>false</casualInterruptible>
</JobDef>
</Defs>

View File

@@ -268,6 +268,7 @@
<!---->
<ThingDef ParentName="BasicBedBase">
<defName>WULA_Charging_Station_Synth</defName>
<thingClass>Building_Bed</thingClass>
<label>合成人修复站</label>
<description>一台供乌拉帝国合成人进行机体修复的检修站。</description>
<graphicData>
@@ -313,7 +314,7 @@
<comps>
<li Class="CompProperties_Power">
<compClass>CompPowerTrader</compClass>
<basePowerConsumption>30</basePowerConsumption>
<basePowerConsumption>200</basePowerConsumption>
</li>
<li Class="CompProperties_Glower">
<glowRadius>12</glowRadius>
@@ -325,6 +326,10 @@
<colorPickerEnabled>true</colorPickerEnabled>
<darklightToggle>true</darklightToggle>
</li>
<li Class="WulaFallenEmpire.CompProperties_ChargingBed">
<hediffDef>WULA_ChargingHediff</hediffDef>
<raceDefName>WulaSpecies</raceDefName>
</li>
</comps>
</ThingDef>

View File

@@ -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")
mcp.run(transport="stdio")

View File

@@ -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<CompPowerTrader>();
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);
}
}
}
}

View File

@@ -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<Toil> 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<CompPowerTrader>();
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<Need_WulaEnergy>();
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;
}
}
}

View File

@@ -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<HediffDef>.GetNamed("WULA_ChargingHediff")))
{
Log.Message($"[JobGiver_WulaGetEnergy] {pawn.Name.ToStringShort} already has charging hediff. Priority 0.");
return 0f;
}
Need_WulaEnergy energyNeed = pawn.needs.TryGetNeed<Need_WulaEnergy>();
if (energyNeed == null || pawn.health.hediffSet.HasHediff(DefDatabase<HediffDef>.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<HediffDef>.GetNamed("WULA_ChargingHediff")))
{
Log.Message($"[JobGiver_WulaGetEnergy] {pawn.Name.ToStringShort} already has charging hediff. Job cancelled.");
return null;
}
Need_WulaEnergy energyNeed = pawn.needs.TryGetNeed<Need_WulaEnergy>();
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<JobDef>.GetNamed("WULA_LayDownToCharge"), energySource);
}
Job job = JobMaker.MakeJob(DefDatabase<JobDef>.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<ThingDefExtension_EnergySource>() != 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<CompPowerTrader>();
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;
}
}
}

View File

@@ -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()
{

View File

@@ -68,6 +68,7 @@
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="CompChargingBed.cs" />
<Compile Include="CompCleave.cs" />
<Compile Include="Building_Wula_DarkEnergy_Engine.cs" />
<Compile Include="CompApparelInterceptor.cs" />
@@ -103,6 +104,7 @@
<Compile Include="JobDriver_EnterMaintenancePod.cs" />
<Compile Include="JobDriver_HaulToMaintenancePod.cs" />
<Compile Include="JobDriver_IngestWulaEnergy.cs" />
<Compile Include="JobDriver_WulaLayDownToCharge.cs" />
<Compile Include="JobGiver_WulaGetEnergy.cs" />
<Compile Include="JobGiver_WulaPackEnergy.cs" />
<Compile Include="Job_Maintenance.cs" />

20
Source/ai_studio_code.txt Normal file
View File

@@ -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 '天空为什么是蓝色的?'"

25
Source/rimworld.md Normal file
View File

@@ -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` 项目文件中的相应 `<Compile Include="..." />` 条目,否则会导致编译失败。