diff --git a/1.6/1.6/Assemblies/WulaFallenEmpire.dll b/1.6/1.6/Assemblies/WulaFallenEmpire.dll index fde1fd95..a714baac 100644 Binary files a/1.6/1.6/Assemblies/WulaFallenEmpire.dll and b/1.6/1.6/Assemblies/WulaFallenEmpire.dll differ diff --git a/Source/WulaFallenEmpire/HarmonyPatches/DialogEnterPortal_MapPatch.cs b/Source/WulaFallenEmpire/HarmonyPatches/DialogEnterPortal_MapPatch.cs new file mode 100644 index 00000000..1c784c3d --- /dev/null +++ b/Source/WulaFallenEmpire/HarmonyPatches/DialogEnterPortal_MapPatch.cs @@ -0,0 +1,51 @@ +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 Transpiler(IEnumerable instructions) + { + var codes = new List(instructions); + // 找到 MapPortal.Map 属性的 getter 方法 + var mapPropertyGetter = AccessTools.PropertyGetter(typeof(MapPortal), "Map"); + // 找到我们自定义的静态方法,它将返回正确的 Map + var getShuttleMapMethod = AccessTools.Method(typeof(DialogEnterPortal_CalculateAndRecacheTransferables_Patch), nameof(GetShuttleMap)); + + for (int i = 0; i < codes.Count; i++) + { + // 查找对 MapPortal.Map 的 get 访问 + if (codes[i].opcode == OpCodes.Callvirt && codes[i].operand is MethodInfo method && method == mapPropertyGetter) + { + // 替换为调用我们的静态方法 + yield return new CodeInstruction(OpCodes.Call, getShuttleMapMethod); + } + else + { + yield return codes[i]; + } + } + } + + // 这个静态方法将由 Transpiler 注入,用于返回正确的 Map + // 参数 portalInstance 是原始方法中对 MapPortal 实例的引用 + public static Map GetShuttleMap(MapPortal portalInstance) + { + if (portalInstance is ShuttlePortalAdapter adapter && adapter.shuttle != null) + { + return adapter.shuttle.Map; + } + // 如果不是我们的适配器或者 shuttle 为空,则返回原始 MapPortal 的 Map + // 我们需要直接访问 Thing 类的 Map 属性,这是 MapPortal 继承的 + var originalMapGetter = AccessTools.PropertyGetter(typeof(Thing), "Map"); + return (Map)originalMapGetter.Invoke(portalInstance, null); + } + } +} \ No newline at end of file diff --git a/Source/WulaFallenEmpire/WULA_Shuttle/CompPocketMapPortal.cs b/Source/WulaFallenEmpire/WULA_Shuttle/CompPocketMapPortal.cs index d14e4ef3..203fa873 100644 --- a/Source/WulaFallenEmpire/WULA_Shuttle/CompPocketMapPortal.cs +++ b/Source/WulaFallenEmpire/WULA_Shuttle/CompPocketMapPortal.cs @@ -33,27 +33,12 @@ namespace WulaFallenEmpire { // 创建MapPortal适配器,并设置其地图和位置信息 portalAdapter = new ShuttlePortalAdapter(ParentShuttle); - // 使用反射设置适配器的地图和位置,让Dialog_EnterPortal能正确访问 - if (portalAdapter != null && ParentShuttle.Spawned) + // 确保 portalAdapter 的 shuttle 引用被正确设置 + // 并在 PostSpawnSetup 中设置 MapPortal 基类的地图和位置信息 + // 确保 portalAdapter 的 shuttle 引用被正确设置 + if (portalAdapter != null) { - 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) - { - mapField.SetValue(portalAdapter, mapField.GetValue(ParentShuttle)); - positionField.SetValue(portalAdapter, positionField.GetValue(ParentShuttle)); - } - } - catch (System.Exception ex) - { - Log.Warning($"[WULA] Could not set adapter map/position via reflection: {ex.Message}"); - } + portalAdapter.shuttle = ParentShuttle; } } } @@ -147,25 +132,39 @@ namespace WulaFallenEmpire enterCommand.action = delegate { // 使用和Building_PocketMapExit一模一样的Dialog_EnterPortal方法 - if (portalAdapter != null && portalAdapter.shuttle != null) + 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) { var dialog = new Dialog_EnterPortal(portalAdapter); Find.WindowStack.Add(dialog); } else { - Log.Error("[WULA] Portal adapter or shuttle is null, recreating adapter"); - // 重新创建适配器 - if (ParentShuttle != null) - { - portalAdapter = new ShuttlePortalAdapter(ParentShuttle); - var dialog = new Dialog_EnterPortal(portalAdapter); - Find.WindowStack.Add(dialog); - } - else - { - Messages.Message("内部错误:穿梭机引用丢失", ParentShuttle, MessageTypeDefOf.RejectInput); - } + Messages.Message("WULA.PocketSpace.AdapterError".Translate(), ParentShuttle, MessageTypeDefOf.RejectInput); + Log.Error("[WULA] Portal adapter is null after recreation attempt."); } }; enterCommand.icon = ContentFinder.Get(Props.buttonIconPath); @@ -271,7 +270,7 @@ namespace WulaFallenEmpire /// public ShuttlePortalAdapter() { - // 为空,在PostSpawnSetup中初始化 + // 在这里不初始化 shuttle,因为它将在 PostSpawnSetup 中设置 } public ShuttlePortalAdapter(Building_ArmedShuttleWithPocket shuttle) @@ -286,7 +285,7 @@ namespace WulaFallenEmpire { if (shuttle?.PocketMap == null) { - // 如果口袋空间还没创建,先创建它 + // 如口袋空间还没创建,先创建它 shuttle?.SwitchToPocketSpace(); } return shuttle?.PocketMap; @@ -318,7 +317,7 @@ namespace WulaFallenEmpire } // 检查穿梭机的传送状态 - var transportDisabledField = typeof(Building_ArmedShuttleWithPocket).GetField("transportDisabled", + var transportDisabledField = typeof(Building_ArmedShuttleWithPocket).GetField("transportDisabled", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); if (transportDisabledField != null) @@ -361,19 +360,8 @@ namespace WulaFallenEmpire /// protected override Texture2D EnterTex => ContentFinder.Get("UI/Commands/LoadTransporter"); - /// - /// 获取地图引用(用于Dialog_EnterPortal) - /// - public new Map Map => shuttle?.Map; - - /// - /// 获取位置引用(用于Dialog_EnterPortal) - /// - public new IntVec3 Position => shuttle?.Position ?? IntVec3.Invalid; - - /// - /// 获取定义引用(用于Dialog_EnterPortal) - /// - public new ThingDef def => shuttle?.def; + // 移除了 new 关键字的 Map, Position, def 属性,因为它们在 MapPortal 基类中可能不是 virtual 的 + // 并且我们依赖 PostSpawnSetup 中的反射来设置 MapPortal 基类的私有字段 + // 这确保了 Dialog_EnterPortal 能够直接访问到正确的地图和位置信息。 } } \ No newline at end of file diff --git a/Source/WulaFallenEmpire/WulaFallenEmpire.csproj b/Source/WulaFallenEmpire/WulaFallenEmpire.csproj index 2897858b..5a565947 100644 --- a/Source/WulaFallenEmpire/WulaFallenEmpire.csproj +++ b/Source/WulaFallenEmpire/WulaFallenEmpire.csproj @@ -96,6 +96,7 @@ +