zc777777
This commit is contained in:
Binary file not shown.
@@ -102,7 +102,6 @@
|
|||||||
<pawnExitSound>Shuttle_PawnExit</pawnExitSound>
|
<pawnExitSound>Shuttle_PawnExit</pawnExitSound>
|
||||||
<showMassInInspectString>true</showMassInInspectString>
|
<showMassInInspectString>true</showMassInInspectString>
|
||||||
</li>
|
</li>
|
||||||
<li Class="WulaFallenEmpire.CompProperties_PocketMapPortal"></li>
|
|
||||||
<li Class="CompProperties_Refuelable">
|
<li Class="CompProperties_Refuelable">
|
||||||
<fuelCapacity>500</fuelCapacity>
|
<fuelCapacity>500</fuelCapacity>
|
||||||
<targetFuelLevelConfigurable>true</targetFuelLevelConfigurable>
|
<targetFuelLevelConfigurable>true</targetFuelLevelConfigurable>
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -1,94 +0,0 @@
|
|||||||
using HarmonyLib;
|
|
||||||
using RimWorld;
|
|
||||||
using Verse;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Reflection.Emit;
|
|
||||||
|
|
||||||
namespace WulaFallenEmpire
|
|
||||||
{
|
|
||||||
[HarmonyPatch(typeof(Dialog_EnterPortal), "CalculateAndRecacheTransferables")]
|
|
||||||
public static class DialogEnterPortal_CalculateAndRecacheTransferables_Patch
|
|
||||||
{
|
|
||||||
// Transpiler 负责修改方法的 IL 代码
|
|
||||||
public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
|
|
||||||
{
|
|
||||||
var codes = new List<CodeInstruction>(instructions);
|
|
||||||
// 找到 Thing.Map 属性的 getter 方法 (MapPortal 继承自 Thing)
|
|
||||||
var mapPropertyGetter = AccessTools.PropertyGetter(typeof(Verse.Thing), "Map");
|
|
||||||
// 找到我们自定义的静态方法,它将返回正确的 Map
|
|
||||||
var getShuttleMapMethod = AccessTools.Method(typeof(DialogEnterPortal_CalculateAndRecacheTransferables_Patch), nameof(GetShuttleMap));
|
|
||||||
|
|
||||||
Log.Message("[WULA-DEBUG] Transpiler for CalculateAndRecacheTransferables started.");
|
|
||||||
|
|
||||||
for (int i = 0; i < codes.Count; i++)
|
|
||||||
{
|
|
||||||
// 查找对 Thing.Map 的 get 访问
|
|
||||||
if (codes[i].opcode == OpCodes.Call && codes[i].operand is MethodInfo method && method == mapPropertyGetter)
|
|
||||||
{
|
|
||||||
Log.Message($"[WULA-DEBUG] Transpiler found Thing.Map getter at index {i}.");
|
|
||||||
// 替换为调用我们的静态方法
|
|
||||||
yield return new CodeInstruction(OpCodes.Call, getShuttleMapMethod);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
yield return codes[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Log.Message("[WULA-DEBUG] Transpiler for CalculateAndRecacheTransferables finished.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 这个静态方法将由 Transpiler 注入,用于返回正确的 Map
|
|
||||||
// 参数 portalInstance 是原始方法中对 MapPortal 实例的引用
|
|
||||||
public static Map GetShuttleMap(MapPortal portalInstance)
|
|
||||||
{
|
|
||||||
if (portalInstance is ShuttlePortalAdapter adapter)
|
|
||||||
{
|
|
||||||
Log.Message($"[WULA-DEBUG] portalInstance is ShuttlePortalAdapter. adapter.shuttle: {adapter.shuttle?.def.defName ?? "null"}");
|
|
||||||
if (adapter.shuttle != null)
|
|
||||||
{
|
|
||||||
// 确保 adapter.shuttle.Map 不为 null
|
|
||||||
if (adapter.shuttle.Map != null)
|
|
||||||
{
|
|
||||||
return adapter.shuttle.Map;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Log.Error($"[WULA] Shuttle {adapter.shuttle.def.defName} is not spawned on any map when trying to get its map.");
|
|
||||||
return null; // 返回 null,让后续代码处理
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果不是我们的适配器,或者适配器中的 shuttle 为空,
|
|
||||||
// 则尝试获取原始 MapPortal 的 Map。
|
|
||||||
// 这里需要非常小心,因为 portalInstance 本身也可能是 null,
|
|
||||||
// 或者它继承自 Thing 的 Map 属性是 null。
|
|
||||||
if (portalInstance == null)
|
|
||||||
{
|
|
||||||
Log.Error("[WULA] GetShuttleMap received a null portalInstance.");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var originalMapGetter = AccessTools.PropertyGetter(typeof(Thing), "Map");
|
|
||||||
if (originalMapGetter == null)
|
|
||||||
{
|
|
||||||
Log.Error("[WULA] Could not get Thing.Map getter via AccessTools.");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
Map result = null;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
result = (Map)originalMapGetter.Invoke(portalInstance, null);
|
|
||||||
}
|
|
||||||
catch (System.Exception ex)
|
|
||||||
{
|
|
||||||
Log.Error($"[WULA] Error invoking original Thing.Map getter: {ex.Message}");
|
|
||||||
}
|
|
||||||
|
|
||||||
Log.Message($"[WULA-DEBUG] GetShuttleMap returning original Map. Result: {result?.ToString() ?? "null"}");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -7,6 +7,7 @@ using RimWorld.Planet;
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using Verse;
|
using Verse;
|
||||||
using Verse.AI;
|
using Verse.AI;
|
||||||
|
using Verse.AI.Group;
|
||||||
using Verse.Sound;
|
using Verse.Sound;
|
||||||
|
|
||||||
namespace WulaFallenEmpire
|
namespace WulaFallenEmpire
|
||||||
@@ -16,7 +17,7 @@ namespace WulaFallenEmpire
|
|||||||
/// 结合了武装防御能力和口袋空间技术的复合型载具
|
/// 结合了武装防御能力和口袋空间技术的复合型载具
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[StaticConstructorOnStartup]
|
[StaticConstructorOnStartup]
|
||||||
public class Building_ArmedShuttleWithPocket : Building_ArmedShuttle
|
public class Building_ArmedShuttleWithPocket : Building_ArmedShuttle, IThingHolder
|
||||||
{
|
{
|
||||||
#region 静态图标定义(使用原版MapPortal的图标)
|
#region 静态图标定义(使用原版MapPortal的图标)
|
||||||
|
|
||||||
@@ -54,6 +55,9 @@ namespace WulaFallenEmpire
|
|||||||
// 注意:我们不再使用自定义的innerContainer,
|
// 注意:我们不再使用自定义的innerContainer,
|
||||||
// 所有物品都存储在CompTransporter.innerContainer中,保持简单和一致
|
// 所有物品都存储在CompTransporter.innerContainer中,保持简单和一致
|
||||||
|
|
||||||
|
/// <summary>新的口袋空间物品容器</summary>
|
||||||
|
private PocketSpaceThingHolder pocketSpaceContainer;
|
||||||
|
|
||||||
/// <summary>口袋地图退出点(模仿原版 MapPortal.exit)</summary>
|
/// <summary>口袋地图退出点(模仿原版 MapPortal.exit)</summary>
|
||||||
public Building_PocketMapExit exit;
|
public Building_PocketMapExit exit;
|
||||||
|
|
||||||
@@ -134,12 +138,38 @@ namespace WulaFallenEmpire
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region IThingHolder 实现 (模仿 MapPortal)
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取直接持有的物品(模仿 MapPortal.GetDirectlyHeldThings)
|
||||||
|
/// </summary>
|
||||||
|
public ThingOwner GetDirectlyHeldThings()
|
||||||
|
{
|
||||||
|
return pocketSpaceContainer.innerContainer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取子持有者(模仿 MapPortal.GetChildHolders)
|
||||||
|
/// </summary>
|
||||||
|
public void GetChildHolders(List<IThingHolder> outChildren)
|
||||||
|
{
|
||||||
|
// 目前没有子持有者,留空
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 实现IThingHolder.ParentHolder属性
|
||||||
|
/// </summary>
|
||||||
|
public new IThingHolder ParentHolder => this;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region 构造函数
|
#region 构造函数
|
||||||
|
|
||||||
public Building_ArmedShuttleWithPocket()
|
public Building_ArmedShuttleWithPocket()
|
||||||
{
|
{
|
||||||
Log.Message("[WULA-DEBUG] Building_ArmedShuttleWithPocket constructor called");
|
Log.Message("[WULA-DEBUG] Building_ArmedShuttleWithPocket constructor called");
|
||||||
// 不再初始化innerContainer,只使用CompTransporter的容器
|
pocketSpaceContainer = new PocketSpaceThingHolder(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -167,8 +197,7 @@ namespace WulaFallenEmpire
|
|||||||
Scribe_Defs.Look(ref exitDef, "exitDef");
|
Scribe_Defs.Look(ref exitDef, "exitDef");
|
||||||
Scribe_Values.Look(ref allowDirectAccess, "allowDirectAccess", true);
|
Scribe_Values.Look(ref allowDirectAccess, "allowDirectAccess", true);
|
||||||
Scribe_Values.Look(ref transportDisabled, "transportDisabled", false);
|
Scribe_Values.Look(ref transportDisabled, "transportDisabled", false);
|
||||||
|
Scribe_Deep.Look(ref pocketSpaceContainer, "pocketSpaceContainer", this);
|
||||||
// 不再序列化innerContainer,只使用CompTransporter的容器
|
|
||||||
|
|
||||||
if (Scribe.mode == LoadSaveMode.PostLoadInit)
|
if (Scribe.mode == LoadSaveMode.PostLoadInit)
|
||||||
{
|
{
|
||||||
@@ -217,11 +246,9 @@ namespace WulaFallenEmpire
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
Log.Message("[WULA-DEBUG] Preserving pocket map during shuttle launch/transport");
|
Log.Message("[WULA-DEBUG] Preserving pocket map during shuttle launch/transport");
|
||||||
// 发射时暂停传送功能,但保留口袋空间
|
|
||||||
transportDisabled = true;
|
transportDisabled = true;
|
||||||
if (pocketMap != null && exit != null)
|
if (pocketMap != null && exit != null)
|
||||||
{
|
{
|
||||||
// 标记传送功能暂停
|
|
||||||
Log.Message("[WULA-DEBUG] Transport functionality disabled during flight");
|
Log.Message("[WULA-DEBUG] Transport functionality disabled during flight");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -234,20 +261,19 @@ namespace WulaFallenEmpire
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private bool ShouldDestroyPocketMapOnDeSpawn(DestroyMode mode)
|
private bool ShouldDestroyPocketMapOnDeSpawn(DestroyMode mode)
|
||||||
{
|
{
|
||||||
// 只在真正销毁时删除口袋空间
|
|
||||||
switch (mode)
|
switch (mode)
|
||||||
{
|
{
|
||||||
case DestroyMode.Vanish: // 发射时使用,保留口袋空间
|
case DestroyMode.Vanish:
|
||||||
return false;
|
return false;
|
||||||
case DestroyMode.Deconstruct: // 拆除,删除口袋空间
|
case DestroyMode.Deconstruct:
|
||||||
return true;
|
return true;
|
||||||
case DestroyMode.KillFinalize: // 被摧毁,删除口袋空间
|
case DestroyMode.KillFinalize:
|
||||||
return true;
|
return true;
|
||||||
case DestroyMode.Cancel: // 取消建造,删除口袋空间
|
case DestroyMode.Cancel:
|
||||||
return true;
|
return true;
|
||||||
case DestroyMode.Refund: // 退款,删除口袋空间
|
case DestroyMode.Refund:
|
||||||
return true;
|
return true;
|
||||||
case DestroyMode.FailConstruction: // 建造失败,删除口袋空间
|
case DestroyMode.FailConstruction:
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
Log.Warning($"[WULA-WARNING] Unknown DestroyMode: {mode}, defaulting to preserve pocket map");
|
Log.Warning($"[WULA-WARNING] Unknown DestroyMode: {mode}, defaulting to preserve pocket map");
|
||||||
@@ -263,7 +289,6 @@ namespace WulaFallenEmpire
|
|||||||
{
|
{
|
||||||
sb.AppendLine("WULA.PocketSpace.Status".Translate() + ": " + "WULA.PocketSpace.Ready".Translate());
|
sb.AppendLine("WULA.PocketSpace.Status".Translate() + ": " + "WULA.PocketSpace.Ready".Translate());
|
||||||
|
|
||||||
// 显示主容器中的物品数量
|
|
||||||
CompTransporter transporter = this.GetComp<CompTransporter>();
|
CompTransporter transporter = this.GetComp<CompTransporter>();
|
||||||
int mainContainerItems = transporter?.innerContainer?.Count ?? 0;
|
int mainContainerItems = transporter?.innerContainer?.Count ?? 0;
|
||||||
|
|
||||||
@@ -272,7 +297,6 @@ namespace WulaFallenEmpire
|
|||||||
sb.AppendLine($"容器物品: {mainContainerItems}");
|
sb.AppendLine($"容器物品: {mainContainerItems}");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 显示口袋空间中的物品和人员数量
|
|
||||||
if (pocketMap != null)
|
if (pocketMap != null)
|
||||||
{
|
{
|
||||||
int pocketItems = pocketMap.listerThings.AllThings.Count(t => t.def.category == ThingCategory.Item && t.def.EverHaulable);
|
int pocketItems = pocketMap.listerThings.AllThings.Count(t => t.def.category == ThingCategory.Item && t.def.EverHaulable);
|
||||||
@@ -288,7 +312,6 @@ namespace WulaFallenEmpire
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 在开发模式下显示详细调试信息
|
|
||||||
if (Prefs.DevMode)
|
if (Prefs.DevMode)
|
||||||
{
|
{
|
||||||
sb.AppendLine($"[Debug] {GetPocketSpaceDebugInfo()}");
|
sb.AppendLine($"[Debug] {GetPocketSpaceDebugInfo()}");
|
||||||
@@ -313,7 +336,7 @@ namespace WulaFallenEmpire
|
|||||||
{
|
{
|
||||||
if (!allowDirectAccess)
|
if (!allowDirectAccess)
|
||||||
{
|
{
|
||||||
return false; // 需要特殊权限
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Spawned)
|
if (!Spawned)
|
||||||
@@ -323,7 +346,7 @@ namespace WulaFallenEmpire
|
|||||||
|
|
||||||
if (transportDisabled)
|
if (transportDisabled)
|
||||||
{
|
{
|
||||||
return false; // 飞行中禁用传送功能
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -375,10 +398,18 @@ namespace WulaFallenEmpire
|
|||||||
int transferredCount = 0;
|
int transferredCount = 0;
|
||||||
foreach (Pawn pawn in pawnsToTransfer)
|
foreach (Pawn pawn in pawnsToTransfer)
|
||||||
{
|
{
|
||||||
if (TransferPawnToPocketSpace(pawn))
|
if (pawn.Spawned)
|
||||||
|
{
|
||||||
|
pawn.DeSpawn();
|
||||||
|
}
|
||||||
|
if (pocketSpaceContainer.innerContainer.TryAdd(pawn))
|
||||||
{
|
{
|
||||||
transferredCount++;
|
transferredCount++;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log.Warning($"[WULA-WARNING] Failed to add pawn {pawn.LabelShort} to pocketSpaceContainer.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (transferredCount > 0)
|
if (transferredCount > 0)
|
||||||
@@ -472,29 +503,13 @@ namespace WulaFallenEmpire
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
// 在地图中心找一个合适的位置
|
// 在地图中心找一个合适的位置
|
||||||
IntVec3 exitPos = pocketMap.Center;
|
IntVec3 exitPos = CellFinder.RandomClosewalkCellNear(pocketMap.Center, pocketMap, 5, (IntVec3 c) => c.IsValid && c.Standable(pocketMap) && !c.Roofed(pocketMap));
|
||||||
|
|
||||||
// 寻找可建造的位置
|
|
||||||
if (!exitPos.Standable(pocketMap) || exitPos.GetThingList(pocketMap).Any(t => t.def.category == ThingCategory.Building))
|
|
||||||
{
|
|
||||||
exitPos = CellFinder.RandomClosewalkCellNear(pocketMap.Center, pocketMap, 5,
|
|
||||||
p => p.Standable(pocketMap) && !p.GetThingList(pocketMap).Any(t => t.def.category == ThingCategory.Building));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (exitPos.IsValid)
|
if (exitPos.IsValid)
|
||||||
{
|
{
|
||||||
// 创建退出点建筑
|
exit = (Building_PocketMapExit)ThingMaker.MakeThing(exitDef);
|
||||||
Thing exitBuilding = ThingMaker.MakeThing(exitDef);
|
GenPlace.TryPlaceThing(exit, exitPos, pocketMap, ThingPlaceMode.Direct);
|
||||||
if (exitBuilding is Building_PocketMapExit exitPortal)
|
Log.Message($"[WULA] Created exit point at {exitPos} in pocket map.");
|
||||||
{
|
|
||||||
exitPortal.targetMap = this.Map;
|
|
||||||
exitPortal.targetPos = this.Position;
|
|
||||||
exitPortal.parentShuttle = this;
|
|
||||||
exit = exitPortal; // 设置 exit 引用,模仿原版 MapPortal
|
|
||||||
}
|
|
||||||
|
|
||||||
GenPlace.TryPlaceThing(exitBuilding, exitPos, pocketMap, ThingPlaceMode.Direct);
|
|
||||||
Log.Message($"[WULA] Created exit point at {exitPos} in pocket map");
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -556,93 +571,34 @@ namespace WulaFallenEmpire
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// 获取穿梭机的 CompTransporter
|
// 转移所有殖民者到 pocketSpaceContainer
|
||||||
CompTransporter transporter = this.GetComp<CompTransporter>();
|
List<Pawn> pawnsToTransfer = pocketMap.mapPawns.AllPawnsSpawned.ToList();
|
||||||
if (transporter == null)
|
Log.Message($"[WULA-DEBUG] Found {pawnsToTransfer.Count} pawns to transfer from pocket map.");
|
||||||
{
|
|
||||||
Log.Error("[WULA-ERROR] CompTransporter not found on shuttle! Cannot transfer items.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Log.Message($"[WULA-DEBUG] Found CompTransporter with {transporter.innerContainer.Count} existing items");
|
|
||||||
|
|
||||||
// 转移所有殖民者
|
|
||||||
List<Pawn> pawnsToTransfer = pocketMap.mapPawns.AllPawnsSpawned
|
|
||||||
.Where(p => p.IsColonist).ToList();
|
|
||||||
|
|
||||||
Log.Message($"[WULA-DEBUG] Found {pawnsToTransfer.Count} colonists to transfer");
|
|
||||||
|
|
||||||
foreach (Pawn pawn in pawnsToTransfer)
|
foreach (Pawn pawn in pawnsToTransfer)
|
||||||
{
|
{
|
||||||
if (pawn.Spawned)
|
if (pawn.Spawned)
|
||||||
{
|
{
|
||||||
Log.Message($"[WULA-DEBUG] Transferring pawn: {pawn.LabelShort}");
|
|
||||||
pawn.DeSpawn();
|
pawn.DeSpawn();
|
||||||
|
|
||||||
// 直接放入穿梭机的容器,如果失败就放到地面
|
|
||||||
if (!transporter.innerContainer.TryAdd(pawn))
|
|
||||||
{
|
|
||||||
Log.Warning($"[WULA-WARNING] Container full, placing pawn {pawn.LabelShort} near shuttle");
|
|
||||||
// 如果容器满了,放到穿梭机附近
|
|
||||||
IntVec3 spawnPos = CellFinder.RandomClosewalkCellNear(this.Position, this.Map, 5,
|
|
||||||
p => p.Standable(this.Map) && !p.GetThingList(this.Map).Any(t => t is Pawn));
|
|
||||||
|
|
||||||
if (spawnPos.IsValid)
|
|
||||||
{
|
|
||||||
GenPlace.TryPlaceThing(pawn, spawnPos, this.Map, ThingPlaceMode.Near);
|
|
||||||
Log.Message($"[WULA-DEBUG] Placed pawn {pawn.LabelShort} at {spawnPos}");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Log.Error($"[WULA-ERROR] Could not find valid position for pawn {pawn.LabelShort}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Log.Message($"[WULA-DEBUG] Successfully added pawn {pawn.LabelShort} to container");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
pocketSpaceContainer.innerContainer.TryAdd(pawn);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 转移所有物品到穿梭机的容器
|
// 转移所有物品到 pocketSpaceContainer
|
||||||
List<Thing> itemsToTransfer = pocketMap.listerThings.AllThings
|
List<Thing> itemsToTransfer = pocketMap.listerThings.AllThings.Where(t => t.def.category == ThingCategory.Item && t.def.EverHaulable).ToList();
|
||||||
.Where(t => t.def.category == ThingCategory.Item && t.def.EverHaulable).ToList();
|
Log.Message($"[WULA-DEBUG] Found {itemsToTransfer.Count} items to transfer from pocket map.");
|
||||||
|
|
||||||
Log.Message($"[WULA-DEBUG] Found {itemsToTransfer.Count} items to transfer");
|
|
||||||
|
|
||||||
foreach (Thing item in itemsToTransfer)
|
foreach (Thing item in itemsToTransfer)
|
||||||
{
|
{
|
||||||
if (item.Spawned)
|
if (item.Spawned)
|
||||||
{
|
{
|
||||||
Log.Message($"[WULA-DEBUG] Transferring item: {item.LabelShort} (stack: {item.stackCount})");
|
|
||||||
item.DeSpawn();
|
item.DeSpawn();
|
||||||
|
|
||||||
// 直接使用穿梭机的主容器
|
|
||||||
if (!transporter.innerContainer.TryAdd(item))
|
|
||||||
{
|
|
||||||
Log.Warning($"[WULA-WARNING] Container full, dropping item {item.LabelShort} near shuttle");
|
|
||||||
// 如果容器满了,丢到穿梭机附近(玩家可以手动重新装载)
|
|
||||||
IntVec3 dropPos = CellFinder.RandomClosewalkCellNear(this.Position, this.Map, 3);
|
|
||||||
if (dropPos.IsValid)
|
|
||||||
{
|
|
||||||
GenPlace.TryPlaceThing(item, dropPos, this.Map, ThingPlaceMode.Near);
|
|
||||||
Messages.Message($"容器已满:{item.LabelShort} 被放置在穿梭机附近", this, MessageTypeDefOf.CautionInput);
|
|
||||||
Log.Message($"[WULA-DEBUG] Dropped item {item.LabelShort} at {dropPos}");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Log.Error($"[WULA-ERROR] Could not find valid drop position for item {item.LabelShort}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Log.Message($"[WULA-DEBUG] Successfully added item {item.LabelShort} to container");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
pocketSpaceContainer.innerContainer.TryAdd(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.Message($"[WULA-DEBUG] Transfer complete. Container now has {transporter.innerContainer.Count} total items");
|
Log.Message($"[WULA] Transferred all pawns and items from pocket map to pocketSpaceContainer.");
|
||||||
Log.Message($"[WULA-SUCCESS] Transferred {pawnsToTransfer.Count} pawns and {itemsToTransfer.Count} items from pocket space");
|
|
||||||
|
// 调用新的同步方法,将 pocketSpaceContainer 中的所有物品和 Pawn 转移到主地图的 CompTransporter
|
||||||
|
TransferPocketContainerToMainTransporter();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -652,100 +608,38 @@ namespace WulaFallenEmpire
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 手动同步口袋空间中的所有物品到穿梭机主容器
|
/// 将pocketSpaceContainer中的所有物品和Pawn转移到主地图的CompTransporter
|
||||||
/// 用于解决物品消失问题
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void SyncPocketItemsToMainContainer()
|
public void TransferPocketContainerToMainTransporter()
|
||||||
{
|
{
|
||||||
Log.Message("[WULA-DEBUG] SyncPocketItemsToMainContainer started");
|
Log.Message("[WULA-DEBUG] TransferPocketContainerToMainTransporter started.");
|
||||||
|
|
||||||
if (pocketMap == null || !pocketMapGenerated)
|
|
||||||
{
|
|
||||||
Log.Warning("[WULA-DEBUG] SyncPocketItemsToMainContainer: No pocket map to sync");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CompTransporter transporter = this.GetComp<CompTransporter>();
|
CompTransporter transporter = this.GetComp<CompTransporter>();
|
||||||
if (transporter == null)
|
if (transporter == null)
|
||||||
{
|
{
|
||||||
Log.Error("[WULA-ERROR] No CompTransporter found on shuttle, cannot sync items");
|
Log.Error("[WULA-ERROR] CompTransporter not found on shuttle! Cannot transfer items from pocketSpaceContainer.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.Message($"[WULA-DEBUG] Starting sync. Current container has {transporter.innerContainer.Count} items");
|
List<Thing> thingsToTransfer = pocketSpaceContainer.innerContainer.ToList();
|
||||||
|
int transferredCount = 0;
|
||||||
|
|
||||||
try
|
foreach (Thing t in thingsToTransfer)
|
||||||
{
|
{
|
||||||
List<Thing> itemsInPocket = pocketMap.listerThings.AllThings
|
if (pocketSpaceContainer.innerContainer.Remove(t))
|
||||||
.Where(t => t.def.category == ThingCategory.Item && t.def.EverHaulable && t.Spawned).ToList();
|
|
||||||
|
|
||||||
Log.Message($"[WULA-DEBUG] Found {itemsInPocket.Count} items in pocket space to check");
|
|
||||||
|
|
||||||
int syncedCount = 0;
|
|
||||||
int droppedCount = 0;
|
|
||||||
int skippedCount = 0;
|
|
||||||
|
|
||||||
foreach (Thing item in itemsInPocket)
|
|
||||||
{
|
{
|
||||||
// 检查物品是否已经在主容器中
|
if (transporter.innerContainer.TryAdd(t))
|
||||||
if (!transporter.innerContainer.Contains(item))
|
|
||||||
{
|
{
|
||||||
Log.Message($"[WULA-DEBUG] Syncing item: {item.LabelShort} (not in main container)");
|
transferredCount++;
|
||||||
|
|
||||||
// 从口袋地图中移除
|
|
||||||
IntVec3 originalPos = item.Position;
|
|
||||||
item.DeSpawn();
|
|
||||||
|
|
||||||
// 尝试添加到主容器
|
|
||||||
if (transporter.innerContainer.TryAdd(item))
|
|
||||||
{
|
|
||||||
syncedCount++;
|
|
||||||
Log.Message($"[WULA-DEBUG] Successfully synced item: {item.LabelShort}");
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Log.Warning($"[WULA-WARNING] Container full, dropping item: {item.LabelShort}");
|
Log.Warning($"[WULA-WARNING] Failed to add {t.LabelShort} to main transporter container. Dropping on ground.");
|
||||||
// 如果主容器满了,放到穿梭机附近(玩家可以手动装载)
|
GenPlace.TryPlaceThing(t, this.Position, this.Map, ThingPlaceMode.Near);
|
||||||
IntVec3 dropPos = CellFinder.RandomClosewalkCellNear(this.Position, this.Map, 3);
|
|
||||||
if (dropPos.IsValid)
|
|
||||||
{
|
|
||||||
GenPlace.TryPlaceThing(item, dropPos, this.Map, ThingPlaceMode.Near);
|
|
||||||
droppedCount++;
|
|
||||||
Log.Message($"[WULA-DEBUG] Dropped item {item.LabelShort} at {dropPos}");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// 如果找不到合适位置,重新放回口袋空间
|
|
||||||
GenPlace.TryPlaceThing(item, originalPos, pocketMap, ThingPlaceMode.Near);
|
|
||||||
Log.Warning($"[WULA-WARNING] Could not find drop position, returned item {item.LabelShort} to pocket");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
Log.Message($"[WULA] Transferred {transferredCount} items/pawns from pocketSpaceContainer to main transporter.");
|
||||||
{
|
|
||||||
skippedCount++;
|
|
||||||
Log.Message($"[WULA-DEBUG] Item {item.LabelShort} already in main container, skipping");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
string message = $"[WULA-SUCCESS] 同步完成: {syncedCount} 个物品已同步";
|
|
||||||
if (droppedCount > 0)
|
|
||||||
{
|
|
||||||
message += $", {droppedCount} 个物品因容器已满被放置在附近";
|
|
||||||
}
|
|
||||||
if (skippedCount > 0)
|
|
||||||
{
|
|
||||||
message += $", {skippedCount} 个物品已在容器中";
|
|
||||||
}
|
|
||||||
|
|
||||||
Log.Message(message);
|
|
||||||
Log.Message($"[WULA-DEBUG] Final container state: {transporter.innerContainer.Count} items");
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Log.Error($"[WULA-ERROR] Error syncing pocket items to main container: {ex}");
|
|
||||||
Log.Error($"[WULA-ERROR] Stack trace: {ex.StackTrace}");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -806,42 +700,39 @@ namespace WulaFallenEmpire
|
|||||||
#region MapPortal兼容接口(使Dialog_EnterPortal能正常工作)
|
#region MapPortal兼容接口(使Dialog_EnterPortal能正常工作)
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 检查是否可以进入(模仿原版MapPortal.IsEnterable)
|
/// 判断是否可以进入(模仿原版MapPortal.IsEnterable)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual bool IsEnterable(out string reason)
|
public virtual bool IsEnterable(out string reason)
|
||||||
{
|
{
|
||||||
if (!allowDirectAccess)
|
reason = "";
|
||||||
{
|
|
||||||
reason = "WULA.PocketSpace.AccessDenied".Translate();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Spawned)
|
if (!Spawned)
|
||||||
{
|
{
|
||||||
reason = "WULA.PocketSpace.NotSpawned".Translate();
|
reason = "WULA.PocketSpace.NotSpawned".Translate();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (transportDisabled)
|
if (transportDisabled)
|
||||||
{
|
{
|
||||||
reason = "WULA.PocketSpace.TransportDisabled".Translate();
|
reason = "WULA.PocketSpace.TransportDisabled".Translate();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (!this.CanEnterPocketSpace())
|
||||||
reason = "";
|
{
|
||||||
|
reason = "WULA.PocketSpace.CannotEnterReason".Translate();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取目标地图(模仿原版MapPortal.GetOtherMap)
|
/// 获取另一个地图(模仿原版MapPortal.GetOtherMap)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual Map GetOtherMap()
|
public virtual Map GetOtherMap()
|
||||||
{
|
{
|
||||||
if (pocketMap == null)
|
if (PocketMap == null)
|
||||||
{
|
{
|
||||||
CreatePocketMap();
|
CreatePocketMap();
|
||||||
}
|
}
|
||||||
return pocketMap;
|
return PocketMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -849,93 +740,62 @@ namespace WulaFallenEmpire
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual IntVec3 GetDestinationLocation()
|
public virtual IntVec3 GetDestinationLocation()
|
||||||
{
|
{
|
||||||
if (exit != null)
|
return exit?.Position ?? IntVec3.Invalid;
|
||||||
{
|
|
||||||
return exit.Position;
|
|
||||||
}
|
|
||||||
return pocketMap?.Center ?? IntVec3.Invalid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 处理进入事件(模仿原版MapPortal.OnEntered)
|
/// 进入时回调(模仿原版MapPortal.OnEntered)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual void OnEntered(Pawn pawn)
|
public virtual void OnEntered(Pawn pawn)
|
||||||
{
|
{
|
||||||
// 通知物品被添加(用于统计和管理)
|
// 将Pawn添加到口袋空间容器
|
||||||
Notify_ThingAdded(pawn);
|
if (pawn.Spawned)
|
||||||
|
|
||||||
// 播放传送音效(如果存在)
|
|
||||||
if (Find.CurrentMap == this.Map)
|
|
||||||
{
|
{
|
||||||
// 可以在这里添加音效播放
|
pawn.DeSpawn();
|
||||||
// def.portal?.traverseSound?.PlayOneShot(this);
|
}
|
||||||
|
pocketSpaceContainer.innerContainer.TryAdd(pawn);
|
||||||
|
|
||||||
|
if (!beenEntered)
|
||||||
|
{
|
||||||
|
beenEntered = true;
|
||||||
|
// 这里可以添加一些首次进入的信件/事件
|
||||||
|
}
|
||||||
|
if (Find.CurrentMap == base.Map)
|
||||||
|
{
|
||||||
|
// def.portal.traverseSound?.PlayOneShot(this); // 暂时移除,避免NRE
|
||||||
|
}
|
||||||
|
else if (Find.CurrentMap == exit.Map)
|
||||||
|
{
|
||||||
|
// def.portal.traverseSound?.PlayOneShot(exit); // 暂时移除,避免NRE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 打开殖民者选择对话框(模仿原版Dialog_EnterPortal的功能)
|
/// 打开殖民者选择对话框(模仿原版Dialog_EnterPortal)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void OpenPawnSelectionDialog()
|
private void OpenPawnSelectionDialog()
|
||||||
{
|
{
|
||||||
// 获取所有可用的殖民者
|
List<Pawn> pawns = CaravanFormingUtility.AllSendablePawns(this.Map, true, true, true, true, true, 0).ToList();
|
||||||
List<Pawn> availablePawns = Map.mapPawns.AllPawnsSpawned
|
List<Thing> items = CaravanFormingUtility.AllReachableColonyItems(this.Map, true, true).ToList();
|
||||||
.Where(p => p.IsColonist && !p.Downed && p.CanReach(this, PathEndMode.Touch, Danger.Deadly))
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
if (availablePawns.Count == 0)
|
// 创建并显示对话框
|
||||||
{
|
Dialog_EnterPortal window = new Dialog_EnterPortal(new global::WulaFallenEmpire.MapPortalAdapter(this)); // 使用适配器
|
||||||
Messages.Message("WULA.PocketSpace.NoPawnsAvailable".Translate(), this, MessageTypeDefOf.RejectInput);
|
Find.WindowStack.Add(window);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建选项列表
|
|
||||||
List<FloatMenuOption> options = new List<FloatMenuOption>();
|
|
||||||
|
|
||||||
// 添加单个殖民者选项
|
|
||||||
foreach (Pawn pawn in availablePawns)
|
|
||||||
{
|
|
||||||
FloatMenuOption option = new FloatMenuOption(
|
|
||||||
$"{pawn.LabelShort}",
|
|
||||||
delegate
|
|
||||||
{
|
|
||||||
EnterPocketSpace(new List<Pawn> { pawn });
|
|
||||||
}
|
|
||||||
);
|
|
||||||
options.Add(option);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 添加“全部殖民者”选项
|
|
||||||
if (availablePawns.Count > 1)
|
|
||||||
{
|
|
||||||
FloatMenuOption allOption = new FloatMenuOption(
|
|
||||||
"WULA.PocketSpace.AllColonists".Translate(availablePawns.Count),
|
|
||||||
delegate
|
|
||||||
{
|
|
||||||
EnterPocketSpace(availablePawns);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
options.Add(allOption);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 显示浮动菜单
|
|
||||||
FloatMenu floatMenu = new FloatMenu(options);
|
|
||||||
Find.WindowStack.Add(floatMenu);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region 原版MapPortal的物品传送方法
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 通知有物品被添加(模仿原版 MapPortal.Notify_ThingAdded)
|
/// 通知物品被添加到此持有者(从IThingHolder继承,但现在由PocketSpaceThingHolder处理)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Notify_ThingAdded(Thing t)
|
public void Notify_ThingAdded(Thing t)
|
||||||
{
|
{
|
||||||
SubtractFromToLoadList(t, t.stackCount);
|
// 这个方法现在由 PocketSpaceThingHolder 内部处理,这里只是为了满足IThingHolder接口
|
||||||
|
// 或者,如果Building_ArmedShuttleWithPocket仍然需要实现IThingHolder,则可以将其转发
|
||||||
|
// Log.Message($"[WULA] Building_ArmedShuttleWithPocket.Notify_ThingAdded called for {t.LabelCap}");
|
||||||
|
// pocketSpaceContainer.innerContainer.Notify_ThingAdded(t); // 转发给内部容器
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 添加到加载列表(模仿原版 MapPortal.AddToTheToLoadList)
|
/// 添加到待加载列表(模仿原版MapPortal.AddToTheToLoadList)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void AddToTheToLoadList(TransferableOneWay t, int count)
|
public void AddToTheToLoadList(TransferableOneWay t, int count)
|
||||||
{
|
{
|
||||||
@@ -972,7 +832,7 @@ namespace WulaFallenEmpire
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 从加载列表中减去(模仿原版 MapPortal.SubtractFromToLoadList)
|
/// 从待加载列表移除(模仿原版MapPortal.SubtractFromToLoadList)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int SubtractFromToLoadList(Thing t, int count)
|
public int SubtractFromToLoadList(Thing t, int count)
|
||||||
{
|
{
|
||||||
@@ -1000,51 +860,39 @@ namespace WulaFallenEmpire
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 取消加载(模仿原版 MapPortal.CancelLoad)
|
/// 取消加载(模仿原版MapPortal.CancelLoad)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void CancelLoad()
|
public void CancelLoad()
|
||||||
{
|
{
|
||||||
// 简化版本,只清理列表
|
Lord lord = base.Map.lordManager.lords.FirstOrDefault((Lord l) => l.LordJob is LordJob_LoadAndEnterPortal lordJob_LoadAndEnterPortal && lordJob_LoadAndEnterPortal.portal is global::WulaFallenEmpire.MapPortalAdapter adapter && adapter.shuttle == this);
|
||||||
if (leftToLoad != null)
|
if (lord != null)
|
||||||
{
|
{
|
||||||
leftToLoad.Clear();
|
base.Map.lordManager.RemoveLord(lord);
|
||||||
}
|
}
|
||||||
|
leftToLoad.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region 穿梭机状态变化处理
|
#region 生命周期方法
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 更新口袋空间中退出点的目标位置(处理穿梭机位置变化)
|
/// 更新退出点目标
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void UpdateExitPointTarget()
|
public void UpdateExitPointTarget()
|
||||||
{
|
{
|
||||||
if (pocketMap == null || exit == null) return;
|
if (exit == null) return;
|
||||||
|
if (base.Map == null)
|
||||||
|
{
|
||||||
|
Log.Warning("[WULA] UpdateExitPointTarget: Shuttle map is null, cannot update exit point target.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// 如果退出点是我们的Building_PocketMapExit类型,更新其目标位置
|
exit.targetMap = base.Map;
|
||||||
if (exit is Building_PocketMapExit pocketExit)
|
exit.targetPos = base.Position;
|
||||||
{
|
Log.Message($"[WULA] Updated exit point target to map {base.Map.uniqueID} at position {base.Position}");
|
||||||
// 更新目标地图和位置
|
|
||||||
if (this.Spawned)
|
|
||||||
{
|
|
||||||
// 穿梭机在地图上,更新目标位置
|
|
||||||
if (pocketExit.targetMap != this.Map || pocketExit.targetPos != this.Position)
|
|
||||||
{
|
|
||||||
pocketExit.targetMap = this.Map;
|
|
||||||
pocketExit.targetPos = this.Position;
|
|
||||||
pocketExit.parentShuttle = this;
|
|
||||||
Log.Message($"[WULA] Updated pocket map exit target to shuttle location: {this.Map?.uniqueID} at {this.Position}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// 穿梭机不在地图上(可能在飞行中),记录警告但保持原有目标
|
|
||||||
Log.Warning($"[WULA] Shuttle not spawned, pocket map exit target may be outdated. Current target: {pocketExit.targetMap?.uniqueID} at {pocketExit.targetPos}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -1066,7 +914,7 @@ namespace WulaFallenEmpire
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 定期检查并同步口袋空间中的物品(每5分钟检查一次)
|
// 定期检查并同步口袋空间中的物品(每5分钟检查一次)
|
||||||
if (this.IsHashIntervalTick(18000) && pocketMapGenerated && pocketMap != null) // 18000 ticks = 5 minutes
|
if (this.IsHashIntervalTick(18000) && pocketMapGenerated && pocketMap != null)
|
||||||
{
|
{
|
||||||
// 自动同步口袋空间中的物品到主容器
|
// 自动同步口袋空间中的物品到主容器
|
||||||
try
|
try
|
||||||
@@ -1074,7 +922,7 @@ namespace WulaFallenEmpire
|
|||||||
int itemsInPocket = pocketMap.listerThings.AllThings.Count(t => t.def.category == ThingCategory.Item && t.def.EverHaulable && t.Spawned);
|
int itemsInPocket = pocketMap.listerThings.AllThings.Count(t => t.def.category == ThingCategory.Item && t.def.EverHaulable && t.Spawned);
|
||||||
if (itemsInPocket > 0)
|
if (itemsInPocket > 0)
|
||||||
{
|
{
|
||||||
SyncPocketItemsToMainContainer();
|
TransferPocketContainerToMainTransporter();
|
||||||
if (Prefs.DevMode)
|
if (Prefs.DevMode)
|
||||||
{
|
{
|
||||||
Log.Message($"[WULA] Auto-synced pocket items. Current status: {GetPocketSpaceDebugInfo()}");
|
Log.Message($"[WULA] Auto-synced pocket items. Current status: {GetPocketSpaceDebugInfo()}");
|
||||||
@@ -1093,7 +941,7 @@ namespace WulaFallenEmpire
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public override void SpawnSetup(Map map, bool respawningAfterLoad)
|
public override void SpawnSetup(Map map, bool respawningAfterLoad)
|
||||||
{
|
{
|
||||||
Log.Message($"[WULA-DEBUG] SpawnSetup called: map={map?.uniqueID}, respawning={respawningAfterLoad}");
|
Log.Message($"[WULA-DEBUG] Building_ArmedShuttleWithPocket.SpawnSetup START. Instance ID: {this.ThingID}, Map param: {map?.GetUniqueLoadID() ?? "null"}, Respawning: {respawningAfterLoad}");
|
||||||
|
|
||||||
// 保存旧位置信息
|
// 保存旧位置信息
|
||||||
Map oldMap = this.Map;
|
Map oldMap = this.Map;
|
||||||
@@ -1124,79 +972,145 @@ namespace WulaFallenEmpire
|
|||||||
// 如果有口袋空间,确保退出点正确连接到新地图
|
// 如果有口袋空间,确保退出点正确连接到新地图
|
||||||
if (pocketMapGenerated && pocketMap != null && exit != null)
|
if (pocketMapGenerated && pocketMap != null && exit != null)
|
||||||
{
|
{
|
||||||
Log.Message($"[WULA-DEBUG] Reconnecting pocket space exit to new map: {map?.uniqueID} at {this.Position}");
|
Log.Message($"[WULA-DEBUG] Reconnecting pocket space exit to new map: {map?.GetUniqueLoadID() ?? "null"} at {this.Position}");
|
||||||
// 退出点会在 UpdateExitPointTarget 中自动更新
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 从 ThingDef 中读取 portal 配置
|
// 从 ThingDef 中读取 portal 配置
|
||||||
if (def.HasModExtension<PocketMapProperties>())
|
if (def.HasModExtension<PocketMapProperties>())
|
||||||
{
|
{
|
||||||
var portalProps = def.GetModExtension<PocketMapProperties>();
|
if (this.Map == null)
|
||||||
Log.Message($"[WULA-DEBUG] Loading portal properties from ThingDef");
|
|
||||||
|
|
||||||
if (portalProps.pocketMapGenerator != null)
|
|
||||||
{
|
{
|
||||||
mapGenerator = portalProps.pocketMapGenerator;
|
Log.Error($"[WULA-ERROR] Building_ArmedShuttleWithPocket {this.ThingID} Map is NULL after SpawnSetup!");
|
||||||
Log.Message($"[WULA-DEBUG] Set mapGenerator: {mapGenerator.defName}");
|
|
||||||
}
|
}
|
||||||
if (portalProps.exitDef != null)
|
PocketMapProperties props = def.GetModExtension<PocketMapProperties>();
|
||||||
{
|
pocketMapSize = props.pocketMapSize;
|
||||||
exitDef = portalProps.exitDef;
|
mapGenerator = props.mapGenerator;
|
||||||
Log.Message($"[WULA-DEBUG] Set exitDef: {exitDef.defName}");
|
exitDef = props.exitDef;
|
||||||
|
allowDirectAccess = props.allowDirectAccess;
|
||||||
}
|
}
|
||||||
if (portalProps.pocketMapSize != IntVec2.Zero)
|
|
||||||
{
|
|
||||||
pocketMapSize = portalProps.pocketMapSize;
|
|
||||||
Log.Message($"[WULA-DEBUG] Set pocketMapSize: {pocketMapSize}");
|
|
||||||
}
|
}
|
||||||
allowDirectAccess = portalProps.allowDirectAccess;
|
|
||||||
Log.Message($"[WULA-DEBUG] Set allowDirectAccess: {allowDirectAccess}");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 初始化地图生成器和退出点定义(如果 XML 中没有配置)
|
public class PocketMapProperties : DefModExtension
|
||||||
if (mapGenerator == null)
|
|
||||||
{
|
{
|
||||||
mapGenerator = DefDatabase<MapGeneratorDef>.GetNamed("AncientStockpile", false)
|
public IntVec2 pocketMapSize = new IntVec2(80, 80);
|
||||||
?? DefDatabase<MapGeneratorDef>.GetNamed("Base_Player", false)
|
public MapGeneratorDef mapGenerator;
|
||||||
?? MapGeneratorDefOf.Base_Player;
|
public ThingDef exitDef;
|
||||||
Log.Message($"[WULA-DEBUG] Using fallback mapGenerator: {mapGenerator.defName}");
|
public bool allowDirectAccess = true;
|
||||||
}
|
|
||||||
|
|
||||||
if (exitDef == null)
|
|
||||||
{
|
|
||||||
exitDef = DefDatabase<ThingDef>.GetNamed("WULA_PocketMapExit", false)
|
|
||||||
?? ThingDefOf.Door;
|
|
||||||
Log.Message($"[WULA-DEBUG] Using fallback exitDef: {exitDef.defName}");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果位置发生了变化,记录日志
|
|
||||||
if (oldMap != null && (oldMap != map || oldPos != this.Position))
|
|
||||||
{
|
|
||||||
Log.Message($"[WULA-DEBUG] Shuttle moved from {oldMap?.uniqueID}:{oldPos} to {map?.uniqueID}:{this.Position}, updating pocket map exit target");
|
|
||||||
}
|
|
||||||
|
|
||||||
Log.Message($"[WULA-DEBUG] SpawnSetup completed successfully");
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 口袋空间属性配置类
|
/// 适配器类,使Building_ArmedShuttleWithPocket能够作为MapPortal被Dialog_EnterPortal使用
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class PocketMapProperties : DefModExtension
|
public class MapPortalAdapter : MapPortal
|
||||||
{
|
{
|
||||||
/// <summary>口袋地图生成器</summary>
|
public Building_ArmedShuttleWithPocket shuttle;
|
||||||
public MapGeneratorDef pocketMapGenerator;
|
|
||||||
|
|
||||||
/// <summary>退出点定义</summary>
|
public MapPortalAdapter() { } // Scribe需要无参数构造函数
|
||||||
public ThingDef exitDef;
|
|
||||||
|
|
||||||
/// <summary>口袋地图大小</summary>
|
public MapPortalAdapter(Building_ArmedShuttleWithPocket shuttle)
|
||||||
public IntVec2 pocketMapSize = new IntVec2(13, 13);
|
{
|
||||||
|
this.shuttle = shuttle;
|
||||||
/// <summary>允许直接访问</summary>
|
|
||||||
public bool allowDirectAccess = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public new Map PocketMap => shuttle?.PocketMap;
|
||||||
|
|
||||||
|
public new bool PocketMapExists => shuttle?.PocketMap != null; // 修正
|
||||||
|
|
||||||
|
public new bool AutoDraftOnEnter => false; // 修正
|
||||||
|
|
||||||
|
protected new Texture2D EnterTex => ContentFinder<Texture2D>.Get("UI/Commands/LoadTransporter"); // 修正
|
||||||
|
|
||||||
|
public new string EnterString => shuttle?.EnterString;
|
||||||
|
|
||||||
|
public new string CancelEnterString => shuttle?.CancelEnterString;
|
||||||
|
|
||||||
|
public new string EnteringString => shuttle?.EnteringString;
|
||||||
|
|
||||||
|
public new bool LoadInProgress => shuttle?.LoadInProgress ?? false;
|
||||||
|
|
||||||
|
public new bool AnyPawnCanLoadAnythingNow => shuttle?.AnyPawnCanLoadAnythingNow ?? false;
|
||||||
|
|
||||||
|
public override void ExposeData()
|
||||||
|
{
|
||||||
|
base.ExposeData();
|
||||||
|
Scribe_References.Look(ref shuttle, "shuttle");
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void SpawnSetup(Map map, bool respawningAfterLoad)
|
||||||
|
{
|
||||||
|
// 适配器不应该被Spawn,此方法留空或报错
|
||||||
|
Log.Error("MapPortalAdapter should not be spawned directly.");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Tick()
|
||||||
|
{
|
||||||
|
// 适配器不应该Tick,此方法留空
|
||||||
|
}
|
||||||
|
|
||||||
|
public new ThingOwner GetDirectlyHeldThings()
|
||||||
|
{
|
||||||
|
return shuttle?.GetDirectlyHeldThings();
|
||||||
|
}
|
||||||
|
|
||||||
|
public new void GetChildHolders(List<IThingHolder> outChildren)
|
||||||
|
{
|
||||||
|
shuttle?.GetChildHolders(outChildren);
|
||||||
|
}
|
||||||
|
|
||||||
|
public new void Notify_ThingAdded(Thing t)
|
||||||
|
{
|
||||||
|
shuttle?.Notify_ThingAdded(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
public new void AddToTheToLoadList(TransferableOneWay t, int count)
|
||||||
|
{
|
||||||
|
shuttle?.AddToTheToLoadList(t, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
public new int SubtractFromToLoadList(Thing t, int count)
|
||||||
|
{
|
||||||
|
return shuttle?.SubtractFromToLoadList(t, count) ?? 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public new void CancelLoad()
|
||||||
|
{
|
||||||
|
shuttle?.CancelLoad();
|
||||||
|
}
|
||||||
|
|
||||||
|
public new bool IsEnterable(out string reason)
|
||||||
|
{
|
||||||
|
if (shuttle == null)
|
||||||
|
{
|
||||||
|
reason = "WULA.PocketSpace.AdapterError".Translate();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return shuttle.IsEnterable(out reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
public new Map GetOtherMap()
|
||||||
|
{
|
||||||
|
return shuttle?.GetOtherMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
public new IntVec3 GetDestinationLocation()
|
||||||
|
{
|
||||||
|
return shuttle?.GetDestinationLocation() ?? IntVec3.Invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public new void OnEntered(Pawn pawn)
|
||||||
|
{
|
||||||
|
shuttle?.OnEntered(pawn);
|
||||||
|
}
|
||||||
|
|
||||||
|
public new IEnumerable<Gizmo> GetGizmos()
|
||||||
|
{
|
||||||
|
// 适配器不直接提供Gizmo,Gizmo应该由shuttle提供
|
||||||
|
return base.GetGizmos(); // 或者返回空的IEnumerable
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion // MapPortal兼容接口
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,366 +0,0 @@
|
|||||||
using RimWorld;
|
|
||||||
using Verse;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using UnityEngine;
|
|
||||||
using System.Reflection;
|
|
||||||
|
|
||||||
namespace WulaFallenEmpire
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 口袋空间传送门组件 - 只作为入口功能,附加在穿梭机上处理进入内部空间的逻辑
|
|
||||||
/// </summary>
|
|
||||||
public class CompPocketMapPortal : ThingComp
|
|
||||||
{
|
|
||||||
/// <summary>组件属性</summary>
|
|
||||||
public CompProperties_PocketMapPortal Props => (CompProperties_PocketMapPortal)props;
|
|
||||||
|
|
||||||
/// <summary>父建筑(必须是穿梭机)</summary>
|
|
||||||
public Building_ArmedShuttleWithPocket ParentShuttle => parent as Building_ArmedShuttleWithPocket;
|
|
||||||
|
|
||||||
/// <summary>MapPortal适配器,用于使用原版Dialog_EnterPortal</summary>
|
|
||||||
private ShuttlePortalAdapter portalAdapter;
|
|
||||||
|
|
||||||
public override void PostSpawnSetup(bool respawningAfterLoad)
|
|
||||||
{
|
|
||||||
base.PostSpawnSetup(respawningAfterLoad);
|
|
||||||
|
|
||||||
Log.Message($"[WULA-DEBUG] CompPocketMapPortal.PostSpawnSetup called. Parent: {parent?.def?.defName ?? "null"}");
|
|
||||||
|
|
||||||
// 检查父对象是否是穿梭机
|
|
||||||
if (ParentShuttle == null)
|
|
||||||
{
|
|
||||||
Log.Error($"[WULA] CompPocketMapPortal attached to non-shuttle building: {parent?.def?.defName}");
|
|
||||||
return; // Early exit if parent is not a shuttle
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建MapPortal适配器,并设置其地图和位置信息
|
|
||||||
portalAdapter = new ShuttlePortalAdapter(ParentShuttle);
|
|
||||||
// 确保 portalAdapter 的 shuttle 引用被正确设置
|
|
||||||
if (portalAdapter != null)
|
|
||||||
{
|
|
||||||
portalAdapter.shuttle = ParentShuttle;
|
|
||||||
Log.Message($"[WULA-DEBUG] portalAdapter.shuttle set in PostSpawnSetup: {portalAdapter.shuttle?.def.defName ?? "null"}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 检查穿梭机是否可以进入(仅作为入口功能)
|
|
||||||
/// </summary>
|
|
||||||
public bool IsEnterable(out string reason)
|
|
||||||
{
|
|
||||||
if (ParentShuttle == null)
|
|
||||||
{
|
|
||||||
reason = "WULA.PocketSpace.NotSpawned".Translate();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ParentShuttle.AllowDirectAccess)
|
|
||||||
{
|
|
||||||
reason = "WULA.PocketSpace.AccessDenied".Translate();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ParentShuttle.Spawned)
|
|
||||||
{
|
|
||||||
reason = "WULA.PocketSpace.NotSpawned".Translate();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查穿梭机的传送状态
|
|
||||||
var transportDisabledField = typeof(Building_ArmedShuttleWithPocket).GetField("transportDisabled",
|
|
||||||
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
|
|
||||||
|
|
||||||
if (transportDisabledField != null)
|
|
||||||
{
|
|
||||||
bool transportDisabled = (bool)transportDisabledField.GetValue(ParentShuttle);
|
|
||||||
if (transportDisabled)
|
|
||||||
{
|
|
||||||
reason = "WULA.PocketSpace.TransportDisabled".Translate();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查口袋地图是否存在
|
|
||||||
if (ParentShuttle.PocketMap == null)
|
|
||||||
{
|
|
||||||
reason = "WULA.PocketSpace.NoTargetMap".Translate();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
reason = "";
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取组件额外的Gizmo按钮(根据口袋空间初始化状态显示不同按钮)
|
|
||||||
/// 重写CompGetGizmosExtra方法,这样RimWorld会自动调用并显示按钮
|
|
||||||
/// </summary>
|
|
||||||
public override IEnumerable<Gizmo> CompGetGizmosExtra()
|
|
||||||
{
|
|
||||||
if (ParentShuttle == null) yield break;
|
|
||||||
|
|
||||||
// 检查口袋空间是否已初始化
|
|
||||||
bool pocketMapExists = ParentShuttle.PocketMap != null;
|
|
||||||
|
|
||||||
if (!pocketMapExists)
|
|
||||||
{
|
|
||||||
// 口袋空间未创建,显示初始化按钮
|
|
||||||
Command_Action initializeCommand = new Command_Action();
|
|
||||||
initializeCommand.action = delegate
|
|
||||||
{
|
|
||||||
// 创建口袋空间
|
|
||||||
InitializePocketSpace();
|
|
||||||
};
|
|
||||||
initializeCommand.icon = ContentFinder<Texture2D>.Get("UI/Commands/LoadTransporter");
|
|
||||||
initializeCommand.defaultLabel = "WULA.PocketSpace.Initialize".Translate();
|
|
||||||
initializeCommand.defaultDesc = "WULA.PocketSpace.InitializeDesc".Translate();
|
|
||||||
|
|
||||||
// 检查是否可以初始化
|
|
||||||
if (!ParentShuttle.Spawned)
|
|
||||||
{
|
|
||||||
initializeCommand.Disabled = true;
|
|
||||||
initializeCommand.disabledReason = "WULA.PocketSpace.NotSpawned".Translate();
|
|
||||||
}
|
|
||||||
|
|
||||||
yield return initializeCommand;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// 穿梭机已创建,显示装载按钮(使用原版Dialog_EnterPortal)
|
|
||||||
Command_Action enterCommand = new Command_Action();
|
|
||||||
enterCommand.action = delegate
|
|
||||||
{
|
|
||||||
// 使用和Building_PocketMapExit一模一样的Dialog_EnterPortal方法
|
|
||||||
if (portalAdapter == null || portalAdapter.shuttle != ParentShuttle)
|
|
||||||
{
|
|
||||||
// 重新创建并设置适配器,确保其指向正确的穿梭机
|
|
||||||
portalAdapter = new ShuttlePortalAdapter(ParentShuttle);
|
|
||||||
// 再次尝试设置 MapPortal 基类的地图和位置信息
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var mapField = typeof(Thing).GetField("mapIndexOrState",
|
|
||||||
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
|
|
||||||
var positionField = typeof(Thing).GetField("positionInt",
|
|
||||||
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
|
|
||||||
|
|
||||||
if (mapField != null && positionField != null && ParentShuttle.Spawned)
|
|
||||||
{
|
|
||||||
mapField.SetValue(portalAdapter, (sbyte)ParentShuttle.Map.Index); // 显式转换为 sbyte
|
|
||||||
positionField.SetValue(portalAdapter, ParentShuttle.Position);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (System.Exception ex)
|
|
||||||
{
|
|
||||||
Log.Error($"[WULA] Error setting MapPortal base fields during Gizmo click: {ex.Message}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (portalAdapter != null)
|
|
||||||
{
|
|
||||||
Log.Message($"[WULA-DEBUG] Opening Dialog_EnterPortal with portalAdapter. Type: {portalAdapter.GetType().Name}. Shuttle: {portalAdapter.shuttle?.def.defName ?? "null"}");
|
|
||||||
var dialog = new Dialog_EnterPortal(portalAdapter);
|
|
||||||
Find.WindowStack.Add(dialog);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Messages.Message("WULA.PocketSpace.AdapterError".Translate(), ParentShuttle, MessageTypeDefOf.RejectInput);
|
|
||||||
Log.Error("[WULA] Portal adapter is null after recreation attempt.");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
enterCommand.icon = ContentFinder<Texture2D>.Get(Props.buttonIconPath);
|
|
||||||
enterCommand.defaultLabel = Props.enterButtonTextKey.Translate() + "...";
|
|
||||||
enterCommand.defaultDesc = Props.enterButtonDescKey.Translate();
|
|
||||||
|
|
||||||
// 检查是否可以进入
|
|
||||||
string reason;
|
|
||||||
enterCommand.Disabled = !IsEnterable(out reason);
|
|
||||||
enterCommand.disabledReason = reason;
|
|
||||||
yield return enterCommand;
|
|
||||||
|
|
||||||
// 查看口袋地图按钮
|
|
||||||
yield return new Command_Action
|
|
||||||
{
|
|
||||||
defaultLabel = "WULA.PocketSpace.SwitchTo".Translate(),
|
|
||||||
defaultDesc = "WULA.PocketSpace.SwitchToDesc".Translate(),
|
|
||||||
icon = ContentFinder<Texture2D>.Get("UI/Commands/ViewCave"),
|
|
||||||
action = delegate
|
|
||||||
{
|
|
||||||
Current.Game.CurrentMap = ParentShuttle.PocketMap;
|
|
||||||
Find.CameraDriver.JumpToCurrentMapLoc(ParentShuttle.PocketMap.Center);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 初始化口袋空间
|
|
||||||
/// </summary>
|
|
||||||
private void InitializePocketSpace()
|
|
||||||
{
|
|
||||||
if (ParentShuttle == null || !ParentShuttle.Spawned)
|
|
||||||
{
|
|
||||||
Messages.Message("WULA.PocketSpace.CannotInitialize".Translate(), ParentShuttle, MessageTypeDefOf.RejectInput);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ParentShuttle.PocketMap != null)
|
|
||||||
{
|
|
||||||
Messages.Message("WULA.PocketSpace.AlreadyInitialized".Translate(), ParentShuttle, MessageTypeDefOf.RejectInput);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Log.Message("[WULA] Starting pocket space initialization via component");
|
|
||||||
|
|
||||||
// 使用穿梭机的SwitchToPocketSpace方法,它会自动创建口袋空间
|
|
||||||
ParentShuttle.SwitchToPocketSpace();
|
|
||||||
|
|
||||||
if (ParentShuttle.PocketMap != null)
|
|
||||||
{
|
|
||||||
Messages.Message("WULA.PocketSpace.InitializeSuccess".Translate(), ParentShuttle, MessageTypeDefOf.PositiveEvent);
|
|
||||||
Log.Message("[WULA] Pocket space initialization completed successfully");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Messages.Message("WULA.PocketSpace.InitializeFailed".Translate(), ParentShuttle, MessageTypeDefOf.RejectInput);
|
|
||||||
Log.Error("[WULA] Pocket space initialization failed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (System.Exception ex)
|
|
||||||
{
|
|
||||||
Log.Error($"[WULA] Error during pocket space initialization: {ex}");
|
|
||||||
Messages.Message("WULA.PocketSpace.InitializeFailed".Translate(), ParentShuttle, MessageTypeDefOf.RejectInput);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 口袋空间传送门组件属性
|
|
||||||
/// </summary>
|
|
||||||
public class CompProperties_PocketMapPortal : CompProperties
|
|
||||||
{
|
|
||||||
/// <summary>进入按钮文本键</summary>
|
|
||||||
public string enterButtonTextKey = "WULA.PocketSpace.Enter";
|
|
||||||
|
|
||||||
/// <summary>进入按钮描述键</summary>
|
|
||||||
public string enterButtonDescKey = "WULA.PocketSpace.EnterDesc";
|
|
||||||
|
|
||||||
/// <summary>按钮图标路径</summary>
|
|
||||||
public string buttonIconPath = "UI/Commands/LoadTransporter";
|
|
||||||
|
|
||||||
public CompProperties_PocketMapPortal()
|
|
||||||
{
|
|
||||||
this.compClass = typeof(CompPocketMapPortal);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// MapPortal适配器类,将Building_ArmedShuttleWithPocket适配为MapPortal接口
|
|
||||||
/// 完全模仿Building_PocketMapExit的实现方式
|
|
||||||
/// </summary>
|
|
||||||
public class ShuttlePortalAdapter : MapPortal
|
|
||||||
{
|
|
||||||
/// <summary>关联的穿梭机</summary>
|
|
||||||
public Building_ArmedShuttleWithPocket shuttle;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 默认构造函数(RimWorld组件系统要求)
|
|
||||||
/// </summary>
|
|
||||||
public ShuttlePortalAdapter()
|
|
||||||
{
|
|
||||||
// 在这里不初始化 shuttle,因为它将在 PostSpawnSetup 中设置
|
|
||||||
}
|
|
||||||
|
|
||||||
public ShuttlePortalAdapter(Building_ArmedShuttleWithPocket shuttle)
|
|
||||||
{
|
|
||||||
this.shuttle = shuttle;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 重写获取其他地图,返回口袋空间(模仿Building_PocketMapExit.GetOtherMap)
|
|
||||||
/// </summary>
|
|
||||||
public override Map GetOtherMap()
|
|
||||||
{
|
|
||||||
if (shuttle?.PocketMap == null)
|
|
||||||
{
|
|
||||||
// 如口袋空间还没创建,先创建它
|
|
||||||
shuttle?.SwitchToPocketSpace();
|
|
||||||
}
|
|
||||||
return shuttle?.PocketMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 重写获取目标位置,返回口袋空间中心(模仿Building_PocketMapExit.GetDestinationLocation)
|
|
||||||
/// </summary>
|
|
||||||
public override IntVec3 GetDestinationLocation()
|
|
||||||
{
|
|
||||||
return shuttle?.PocketMap?.Center ?? IntVec3.Invalid;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 重写是否可进入,检查穿梭机状态(模仿Building_PocketMapExit.IsEnterable)
|
|
||||||
/// </summary>
|
|
||||||
public override bool IsEnterable(out string reason)
|
|
||||||
{
|
|
||||||
if (shuttle == null || !shuttle.Spawned)
|
|
||||||
{
|
|
||||||
reason = "WULA.PocketSpace.NotSpawned".Translate();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!shuttle.AllowDirectAccess)
|
|
||||||
{
|
|
||||||
reason = "WULA.PocketSpace.AccessDenied".Translate();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查穿梭机的传送状态
|
|
||||||
var transportDisabledField = typeof(Building_ArmedShuttleWithPocket).GetField("transportDisabled",
|
|
||||||
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
|
|
||||||
|
|
||||||
if (transportDisabledField != null)
|
|
||||||
{
|
|
||||||
bool transportDisabled = (bool)transportDisabledField.GetValue(shuttle);
|
|
||||||
if (transportDisabled)
|
|
||||||
{
|
|
||||||
reason = "WULA.PocketSpace.TransportDisabled".Translate();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
reason = "";
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 重写进入事件,处理进入口袋空间(模仿Building_PocketMapExit.OnEntered)
|
|
||||||
/// </summary>
|
|
||||||
public override void OnEntered(Pawn pawn)
|
|
||||||
{
|
|
||||||
// 通知穿梭机有物品被添加(用于统计和管理)
|
|
||||||
shuttle?.Notify_ThingAdded(pawn);
|
|
||||||
|
|
||||||
// 播放传送音效(如果存在)
|
|
||||||
if (Find.CurrentMap == shuttle?.Map)
|
|
||||||
{
|
|
||||||
// 可以在这里添加音效播放
|
|
||||||
// def.portal?.traverseSound?.PlayOneShot(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// 重写进入按钮文本
|
|
||||||
/// </summary>
|
|
||||||
public override string EnterString => "WULA.PocketSpace.Enter".Translate();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 重写进入按钮图标,使用装载按钮的贴图
|
|
||||||
/// </summary>
|
|
||||||
protected override Texture2D EnterTex => ContentFinder<Texture2D>.Get("UI/Commands/LoadTransporter");
|
|
||||||
|
|
||||||
// 移除了 new 关键字的 Map, Position, def 属性,因为它们在 MapPortal 基类中可能不是 virtual 的
|
|
||||||
// 并且我们依赖 PostSpawnSetup 中的反射来设置 MapPortal 基类的私有字段
|
|
||||||
// 这确保了 Dialog_EnterPortal 能够直接访问到正确的地图和位置信息。
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Verse;
|
||||||
|
|
||||||
|
namespace WulaFallenEmpire
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 用于武装穿梭机口袋空间的IThingHolder实现,与CompTransporter的容器分离
|
||||||
|
/// </summary>
|
||||||
|
public class PocketSpaceThingHolder : IThingHolder, IExposable
|
||||||
|
{
|
||||||
|
/// <summary>持有的物品容器</summary>
|
||||||
|
public ThingOwner<Thing> innerContainer;
|
||||||
|
|
||||||
|
/// <summary>该容器的拥有者(通常是Building_ArmedShuttleWithPocket)</summary>
|
||||||
|
private IThingHolder owner;
|
||||||
|
|
||||||
|
/// <summary>实现IThingHolder.ParentHolder属性</summary>
|
||||||
|
public IThingHolder ParentHolder => owner;
|
||||||
|
|
||||||
|
public PocketSpaceThingHolder()
|
||||||
|
{
|
||||||
|
innerContainer = new ThingOwner<Thing>(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PocketSpaceThingHolder(IThingHolder owner) : this()
|
||||||
|
{
|
||||||
|
this.owner = owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取直接持有的物品
|
||||||
|
/// </summary>
|
||||||
|
public ThingOwner GetDirectlyHeldThings()
|
||||||
|
{
|
||||||
|
return innerContainer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取子持有者
|
||||||
|
/// </summary>
|
||||||
|
public void GetChildHolders(List<IThingHolder> outChildren)
|
||||||
|
{
|
||||||
|
// 目前没有子持有者,留空
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 通知物品被添加
|
||||||
|
/// </summary>
|
||||||
|
public void Notify_ThingAdded(Thing t)
|
||||||
|
{
|
||||||
|
// 这里可以添加逻辑来处理物品被添加到口袋空间的情况
|
||||||
|
Log.Message($"[WULA] Item {t.LabelCap} added to pocket space container.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 通知物品被移除
|
||||||
|
/// </summary>
|
||||||
|
public void Notify_ThingRemoved(Thing t)
|
||||||
|
{
|
||||||
|
// 这里可以添加逻辑来处理物品被从口袋空间移除的情况
|
||||||
|
Log.Message($"[WULA] Item {t.LabelCap} removed from pocket space container.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ExposeData()
|
||||||
|
{
|
||||||
|
Scribe_Deep.Look(ref innerContainer, "innerContainer", this);
|
||||||
|
// owner 通常在构造函数中设置,不需要序列化
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -96,7 +96,6 @@
|
|||||||
<Compile Include="EventSystem\EventUIConfigDef.cs" />
|
<Compile Include="EventSystem\EventUIConfigDef.cs" />
|
||||||
<Compile Include="EventSystem\Letter_EventChoice.cs" />
|
<Compile Include="EventSystem\Letter_EventChoice.cs" />
|
||||||
<Compile Include="EventSystem\QuestNode_Root_EventLetter.cs" />
|
<Compile Include="EventSystem\QuestNode_Root_EventLetter.cs" />
|
||||||
<Compile Include="HarmonyPatches\DialogEnterPortal_MapPatch.cs" />
|
|
||||||
<Compile Include="HarmonyPatches\Caravan_NeedsTracker_TrySatisfyPawnNeeds_Patch.cs" />
|
<Compile Include="HarmonyPatches\Caravan_NeedsTracker_TrySatisfyPawnNeeds_Patch.cs" />
|
||||||
<Compile Include="HarmonyPatches\DamageInfo_Constructor_Patch.cs" />
|
<Compile Include="HarmonyPatches\DamageInfo_Constructor_Patch.cs" />
|
||||||
<Compile Include="HarmonyPatches\FloatMenuOptionProvider_Ingest_Patch.cs" />
|
<Compile Include="HarmonyPatches\FloatMenuOptionProvider_Ingest_Patch.cs" />
|
||||||
@@ -172,8 +171,8 @@
|
|||||||
<Compile Include="WULA_Shuttle\Building_ArmedShuttle.cs" />
|
<Compile Include="WULA_Shuttle\Building_ArmedShuttle.cs" />
|
||||||
<Compile Include="WULA_Shuttle\Building_ArmedShuttleWithPocket.cs" />
|
<Compile Include="WULA_Shuttle\Building_ArmedShuttleWithPocket.cs" />
|
||||||
<Compile Include="WULA_Shuttle\Building_PocketMapExit.cs" />
|
<Compile Include="WULA_Shuttle\Building_PocketMapExit.cs" />
|
||||||
<Compile Include="WULA_Shuttle\CompPocketMapPortal.cs" />
|
|
||||||
<Compile Include="WULA_Shuttle\GenStep_WulaPocketSpaceSmall.cs" />
|
<Compile Include="WULA_Shuttle\GenStep_WulaPocketSpaceSmall.cs" />
|
||||||
|
<Compile Include="WULA_Shuttle\PocketSpaceThingHolder.cs" />
|
||||||
<Compile Include="HarmonyPatches\Patch_DropCellFinder_SkyfallerCanLandAt.cs" />
|
<Compile Include="HarmonyPatches\Patch_DropCellFinder_SkyfallerCanLandAt.cs" />
|
||||||
<Compile Include="MechWeapon\FloatMenuProvider_Mech.cs" />
|
<Compile Include="MechWeapon\FloatMenuProvider_Mech.cs" />
|
||||||
<Compile Include="MechWeapon\Patch_MissingWeapon.cs" />
|
<Compile Include="MechWeapon\Patch_MissingWeapon.cs" />
|
||||||
|
|||||||
Reference in New Issue
Block a user