Skip to content

Commit

Permalink
Add ChaFile.GetSourceFilePath extension (gets path to the character c…
Browse files Browse the repository at this point in the history
…ard)
  • Loading branch information
ManlyMarco committed Nov 23, 2022
1 parent 2e3c883 commit 689ee7e
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 0 deletions.
2 changes: 2 additions & 0 deletions doc/KKAPI.Chara.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ Static Methods
| --- | --- | --- |
| `void` | BindToFunctionController(this `BaseEditableGuiEntry<TValue>` guiEntry, `GetValueForInterface<TController, TValue>` getValue, `SetValueToController<TController, TValue>` setValue) | Synchronize this maker control to the state of your custom `KKAPI.Chara.CharaCustomFunctionController`. When the control's value changes the change is sent to the controller, and when the character is reloaded the change is automatically pulled from the controller into the control. |
| `ChaControl` | GetChaControl(this `ChaFile` chaFile) | Get ChaControl that is using this ChaFile if any exist. |
| `String` | GetFancyCharacterName(this `ChaFile` chaFile, `Boolean` describeIfEmpty = True) | Get cleaned up full name of this character, including its translation if available. |
| `String` | GetSourceFilePath(this `ChaFile` chaFile) | Gets full path to the file where this ChaFile was loaded from. Usually this means the character card, but can also point to a studio scene or a game save file if the character was contained inside them. If the ChaFile was loaded from memory or copied, this will most likely return null. |


## `CharaCustomFunctionController`
Expand Down
23 changes: 23 additions & 0 deletions src/Shared.AIalike/Chara/CharacterApi.Hooks.AI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System;
using System.Collections;
using System.Diagnostics;
using System.IO;
using System.Linq;

namespace KKAPI.Chara
Expand All @@ -26,6 +27,28 @@ public static void InitHooks()

var target3 = typeof(ChaFile).GetMethods().Single(info => info.Name == nameof(ChaFile.CopyAll));
i.Patch(target3, null, new HarmonyMethod(typeof(Hooks), nameof(ChaFile_CopyChaFileHook)));

i.Patch(original: AccessTools.FirstMethod(typeof(ChaFile), info => info.Name == nameof(ChaFile.LoadFile) && info.GetParameters().FirstOrDefault()?.ParameterType == typeof(BinaryReader)),
prefix: new HarmonyMethod(typeof(Hooks), nameof(Hooks.ChaFileLoadHook)) { wrapTryCatch = true }); //todo ai hs2
}

private static void ChaFileLoadHook(ChaFile __instance, BinaryReader br)
{
// Keep track of what filenames cards get loaded from
// Doesn't handle studio scenes and files loaded from memory but it doesn't matter here
if (br.BaseStream is FileStream fs)
{
// .Name should already be the full path, but it usually has a bunch of ../ in it, GetFullPath will clean it up
var fullPath = Path.GetFullPath(fs.Name);
CharacterExtensions.ChaFileFullPathLookup[__instance] = fullPath;
#if DEBUG
KoikatuAPI.Logger.LogDebug($"FullName for {__instance} is {fullPath}");
#endif
}
#if DEBUG
else
KoikatuAPI.Logger.LogWarning($"Failed to get FullName for {__instance}, BaseStream is {br.BaseStream} in {new System.Diagnostics.StackTrace()}");
#endif
}

public static void ChaControl_InitializePostHook(ChaControl __instance)
Expand Down
14 changes: 14 additions & 0 deletions src/Shared.Core/Chara/CharacterExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using KKAPI.Maker;
using KKAPI.Maker.UI;
Expand Down Expand Up @@ -155,5 +156,18 @@ void OnCleanup(object sender, EventArgs args)
}

#endregion

internal static readonly Dictionary<ChaFile, string> ChaFileFullPathLookup = new Dictionary<ChaFile, string>(); //todo add extension

/// <summary>
/// Gets full path to the file where this ChaFile was loaded from. Usually this means the character card,
/// but can also point to a studio scene or a game save file if the character was contained inside them.
/// If the ChaFile was loaded from memory or copied, this will most likely return null. Might not work in maker in some games (todo).
/// </summary>
public static string GetSourceFilePath(this ChaFile chaFile)
{
ChaFileFullPathLookup.TryGetValue(chaFile, out var fullPath);
return fullPath;
}
}
}
22 changes: 22 additions & 0 deletions src/Shared.KKalike/Chara/CharacterApi.Hooks.KK.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
Expand Down Expand Up @@ -46,6 +47,27 @@ public static void InitHooks()
if (lambdaMethod != null)
i.Patch(lambdaMethod, null, null, transpiler);
}
#endif
i.Patch(original: AccessTools.FirstMethod(typeof(ChaFile), info => info.Name == nameof(ChaFile.LoadFile) && info.GetParameters().FirstOrDefault()?.ParameterType == typeof(BinaryReader)),
prefix: new HarmonyMethod(typeof(Hooks), nameof(Hooks.ChaFileLoadHook)) { wrapTryCatch = true });
}

private static void ChaFileLoadHook(ChaFile __instance, BinaryReader br)
{
// Keep track of what filenames cards get loaded from
// Doesn't handle studio scenes and files loaded from memory but it doesn't matter here
if (br.BaseStream is FileStream fs)
{
// .Name should already be the full path, but it usually has a bunch of ../ in it, GetFullPath will clean it up
var fullPath = Path.GetFullPath(fs.Name);
CharacterExtensions.ChaFileFullPathLookup[__instance] = fullPath;
#if DEBUG
KoikatuAPI.Logger.LogDebug($"FullName for {__instance} is {fullPath}");
#endif
}
#if DEBUG
else
KoikatuAPI.Logger.LogWarning($"Failed to get FullName for {__instance}, BaseStream is {br.BaseStream} in {new System.Diagnostics.StackTrace()}");
#endif
}

Expand Down

0 comments on commit 689ee7e

Please sign in to comment.