Add log entry functionality to AIImages. Introduce event description handling in PawnAppearanceData and update prompt generation logic to include event context. Enhance Window_AIImage to display log entries and allow image generation from log events, improving user interaction and character representation.
All checks were successful
SonarQube Analysis / Build and analyze (push) Successful in 1m45s
All checks were successful
SonarQube Analysis / Build and analyze (push) Successful in 1m45s
This commit is contained in:
241
Source/AIImages/Patches/PawnLogPatch.cs
Normal file
241
Source/AIImages/Patches/PawnLogPatch.cs
Normal file
@@ -0,0 +1,241 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using HarmonyLib;
|
||||
using RimWorld;
|
||||
using UnityEngine;
|
||||
using Verse;
|
||||
|
||||
namespace AIImages.Patches
|
||||
{
|
||||
/// <summary>
|
||||
/// Патч для получения записей лога пешки через ITab_Pawn_Log
|
||||
/// </summary>
|
||||
[HarmonyPatch(typeof(ITab_Pawn_Log), "FillTab")]
|
||||
public static class ITab_Pawn_Log_Patch
|
||||
{
|
||||
private static Pawn lastPawn = null;
|
||||
private static List<LogEntry> cachedEntries = new List<LogEntry>();
|
||||
|
||||
[HarmonyPrefix]
|
||||
public static void Prefix(ITab_Pawn_Log __instance)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Получаем пешку через рефлексию
|
||||
var selPawnProp = AccessTools.Property(typeof(ITab), "SelPawn");
|
||||
if (selPawnProp != null)
|
||||
{
|
||||
var pawn = selPawnProp.GetValue(__instance) as Pawn;
|
||||
if (pawn != null)
|
||||
{
|
||||
// Пробуем получить записи напрямую через Pawn.logs
|
||||
var logsProperty = AccessTools.Property(typeof(Pawn), "logs");
|
||||
if (logsProperty != null)
|
||||
{
|
||||
var logs = logsProperty.GetValue(pawn);
|
||||
if (logs != null)
|
||||
{
|
||||
// Пробуем AllEntries
|
||||
var allEntriesProperty = AccessTools.Property(
|
||||
logs.GetType(),
|
||||
"AllEntries"
|
||||
);
|
||||
if (allEntriesProperty != null)
|
||||
{
|
||||
var entries = allEntriesProperty.GetValue(logs);
|
||||
if (entries is IEnumerable<LogEntry> entriesList)
|
||||
{
|
||||
cachedEntries = entriesList.ToList();
|
||||
lastPawn = pawn;
|
||||
UnityEngine.Debug.Log(
|
||||
$"[AI Images] Cached {cachedEntries.Count} log entries for {pawn.Name}"
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
UnityEngine.Debug.LogWarning(
|
||||
$"[AI Images] ITab_Pawn_Log patch error: {ex.Message}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public static List<LogEntry> GetCachedEntries(Pawn pawn)
|
||||
{
|
||||
if (pawn == lastPawn && cachedEntries != null && cachedEntries.Any())
|
||||
{
|
||||
return cachedEntries;
|
||||
}
|
||||
|
||||
// Если кэш не подходит, пытаемся получить напрямую
|
||||
if (pawn != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var logsProperty = AccessTools.Property(typeof(Pawn), "logs");
|
||||
if (logsProperty != null)
|
||||
{
|
||||
var logs = logsProperty.GetValue(pawn);
|
||||
if (logs != null)
|
||||
{
|
||||
var allEntriesProperty = AccessTools.Property(
|
||||
logs.GetType(),
|
||||
"AllEntries"
|
||||
);
|
||||
if (allEntriesProperty != null)
|
||||
{
|
||||
var entries = allEntriesProperty.GetValue(logs);
|
||||
if (entries is IEnumerable<LogEntry> entriesList)
|
||||
{
|
||||
var list = entriesList.ToList();
|
||||
if (list.Any())
|
||||
{
|
||||
cachedEntries = list;
|
||||
lastPawn = pawn;
|
||||
return list;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
UnityEngine.Debug.LogWarning(
|
||||
$"[AI Images] Error getting entries directly: {ex.Message}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return new List<LogEntry>();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Патч для получения записей лога пешки
|
||||
/// Упрощённая версия - только для получения данных
|
||||
/// </summary>
|
||||
public static class PawnLogPatch
|
||||
{
|
||||
/// <summary>
|
||||
/// Получает все записи лога пешки
|
||||
/// </summary>
|
||||
public static IEnumerable<LogEntry> GetAllLogEntries(Pawn pawn)
|
||||
{
|
||||
// Сначала пробуем получить из кэша ITab_Pawn_Log
|
||||
var cachedEntries = ITab_Pawn_Log_Patch.GetCachedEntries(pawn);
|
||||
if (cachedEntries != null && cachedEntries.Any())
|
||||
{
|
||||
return cachedEntries;
|
||||
}
|
||||
|
||||
// Затем пробуем другие способы
|
||||
return GetAllLogEntriesInternal(pawn);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Внутренний метод получения записей лога
|
||||
/// </summary>
|
||||
private static IEnumerable<LogEntry> GetAllLogEntriesInternal(Pawn pawn)
|
||||
{
|
||||
if (pawn == null)
|
||||
return Enumerable.Empty<LogEntry>();
|
||||
|
||||
try
|
||||
{
|
||||
// Способ 1: Через property через reflection
|
||||
var logsProperty = AccessTools.Property(typeof(Pawn), "logs");
|
||||
if (logsProperty != null)
|
||||
{
|
||||
var logs = logsProperty.GetValue(pawn);
|
||||
if (logs != null)
|
||||
{
|
||||
var allEntriesProperty = AccessTools.Property(logs.GetType(), "AllEntries");
|
||||
if (allEntriesProperty != null)
|
||||
{
|
||||
var entries = allEntriesProperty.GetValue(logs);
|
||||
if (entries is IEnumerable<LogEntry> entriesList)
|
||||
{
|
||||
return entriesList;
|
||||
}
|
||||
}
|
||||
|
||||
// Пробуем метод GetEntries
|
||||
var getEntriesMethod = AccessTools.Method(logs.GetType(), "GetEntries");
|
||||
if (getEntriesMethod != null)
|
||||
{
|
||||
var entries = getEntriesMethod.Invoke(logs, null);
|
||||
if (entries is IEnumerable<LogEntry> entriesList)
|
||||
{
|
||||
return entriesList;
|
||||
}
|
||||
}
|
||||
|
||||
// Пробуем поле entries
|
||||
var entriesField = AccessTools.Field(logs.GetType(), "entries");
|
||||
if (entriesField != null)
|
||||
{
|
||||
var entries = entriesField.GetValue(logs);
|
||||
if (entries is IEnumerable<LogEntry> entriesList)
|
||||
{
|
||||
return entriesList;
|
||||
}
|
||||
if (entries is System.Collections.IList entriesCollection)
|
||||
{
|
||||
return entriesCollection.Cast<LogEntry>();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Способ 3: Через story.logs
|
||||
if (pawn.story != null)
|
||||
{
|
||||
var logsField = AccessTools.Field(pawn.story.GetType(), "logs");
|
||||
if (logsField != null)
|
||||
{
|
||||
var logs = logsField.GetValue(pawn.story);
|
||||
if (logs != null)
|
||||
{
|
||||
var allEntriesProperty = AccessTools.Property(
|
||||
logs.GetType(),
|
||||
"AllEntries"
|
||||
);
|
||||
if (allEntriesProperty != null)
|
||||
{
|
||||
var entries = allEntriesProperty.GetValue(logs);
|
||||
if (entries is IEnumerable<LogEntry> entriesList)
|
||||
{
|
||||
return entriesList;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
// Логируем ошибку для отладки
|
||||
UnityEngine.Debug.LogWarning(
|
||||
$"[AI Images] Error getting log entries for {pawn?.Name}: {ex.Message}"
|
||||
);
|
||||
}
|
||||
|
||||
// Если все способы не сработали, логируем информацию
|
||||
UnityEngine.Debug.Log(
|
||||
$"[AI Images] Could not get log entries for {pawn?.Name}. "
|
||||
+ $"logs property exists: {AccessTools.Property(typeof(Pawn), "logs") != null}, "
|
||||
+ $"story property exists: {AccessTools.Property(typeof(Pawn), "story") != null}"
|
||||
);
|
||||
|
||||
return Enumerable.Empty<LogEntry>();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user