Skip to content

Commit

Permalink
Better dialogue handling
Browse files Browse the repository at this point in the history
  • Loading branch information
MegaPiggy committed Sep 22, 2024
1 parent 6d38fd5 commit b755675
Show file tree
Hide file tree
Showing 2 changed files with 132 additions and 35 deletions.
56 changes: 36 additions & 20 deletions Winch/Patches/API/DialogueRunnerPatcher.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using HarmonyLib;
using UnityEngine.Rendering.Universal;
using Winch.Core;
using Winch.Core.API;
using Winch.Util;
Expand All @@ -9,38 +10,53 @@ namespace Winch.Patches.API;
[HarmonyPatch(typeof(DredgeDialogueRunner))]
internal static class DialogueRunnerPatcher
{
public static void Placeholder()
{

}

[HarmonyPostfix]
[HarmonyPriority(Priority.First)]
[HarmonyPatch(nameof(DredgeDialogueRunner.Awake))]
public static void Awake_Postfix(DredgeDialogueRunner __instance)
{
#pragma warning disable IDE0200
__instance.AddCommandHandler<string>("LogDebug", message => __instance.LogDebug(message));
__instance.AddCommandHandler<string>("LogInfo", message => __instance.LogInfo(message));
__instance.AddCommandHandler<string>("LogWarn", message => __instance.LogWarn(message));
__instance.AddCommandHandler<string>("LogError", message => __instance.LogError(message));
#pragma warning restore IDE0200
__instance.AddCommandHandler("Placeholder", Placeholder);
new DialogueLogger(__instance);
DredgeEvent.TriggerDialogueRunnerLoaded(__instance);
}

private static void LogDebug(this DredgeDialogueRunner dialogueRunner, string message)
private class DialogueLogger
{
WinchCore.Log.Debug(message, dialogueRunner.CurrentNodeName);
}
private readonly DredgeDialogueRunner dialogueRunner;

private static void LogInfo(this DredgeDialogueRunner dialogueRunner, string message)
{
WinchCore.Log.Info(message, dialogueRunner.CurrentNodeName);
}
public DialogueLogger(DredgeDialogueRunner dialogueRunner)
{
this.dialogueRunner = dialogueRunner;
dialogueRunner.AddCommandHandler<string>("LogDebug", LogDebug);
dialogueRunner.AddCommandHandler<string>("LogInfo", LogInfo);
dialogueRunner.AddCommandHandler<string>("LogWarn", LogWarn);
dialogueRunner.AddCommandHandler<string>("LogError", LogError);
}

private static void LogWarn(this DredgeDialogueRunner dialogueRunner, string message)
{
WinchCore.Log.Warn(message, dialogueRunner.CurrentNodeName);
}
private void LogDebug(string message)
{
WinchCore.Log.Debug(message, dialogueRunner.CurrentNodeName);
}

private static void LogError(this DredgeDialogueRunner dialogueRunner, string message)
{
WinchCore.Log.Error(message, dialogueRunner.CurrentNodeName);
private void LogInfo(string message)
{
WinchCore.Log.Info(message, dialogueRunner.CurrentNodeName);
}

private void LogWarn(string message)
{
WinchCore.Log.Warn(message, dialogueRunner.CurrentNodeName);
}

private void LogError(string message)
{
WinchCore.Log.Error(message, dialogueRunner.CurrentNodeName);
}
}

[HarmonyPrefix]
Expand Down
111 changes: 96 additions & 15 deletions Winch/Util/DialogueUtil.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
using System.Text;
using Winch.Config;
using CommandTerminal;
using Sirenix.Utilities;
using Google.Protobuf;

namespace Winch.Util;

Expand Down Expand Up @@ -48,10 +50,23 @@ public static class DialogueUtil
/// </summary>
internal static Dictionary<string, Program> programs = new();

/// <summary>
/// Fix yarn files to use spaces instead of tabs
/// </summary>
private static void FixDialogueFiles(string[] yarnFiles)
{
foreach (var yarnFile in yarnFiles)
{
File.WriteAllText(yarnFile, File.ReadAllText(yarnFile).Replace("\t", " "));
}
}

internal static void LoadDialogueFiles(string dialogueFolderPath)
{
string[] yarnFiles = Directory.GetFiles(dialogueFolderPath).Where(f => f.EndsWith(".yarn")).ToArray();

FixDialogueFiles(yarnFiles);

CompilationResult compilationResult = CompileProgram(yarnFiles);
programCompilationResults.Add(dialogueFolderPath, compilationResult);
var program = compilationResult.Program;
Expand Down Expand Up @@ -154,20 +169,45 @@ public static void AddInstructions(params DredgeInstruction[] instructions)
DialogueUtil.instructions.AddRange(instructions);
}

/// <summary>
/// Register line metadata to insert later
/// </summary>
/// <param name="line">The line to add the metadata to.</param>
/// <param name="metadata">The metadata that will be added to the line.</param>
public static void AddLineMetadata(string line, params string[] metadata)
{
DialogueUtil.metadata.Add(line, metadata);
}

/// <summary>
/// Manually set the line metadata
/// </summary>
/// <param name="line">The line to add the metadata to.</param>
/// <param name="metadata">The metadata that will be added to the line.</param>
internal static void SetLineMetadata(string line, params string[] metadata)
{
var _lineMetadata = Traverse.Create(GameManager.Instance.DialogueRunner.yarnProject.lineMetadata).Field("_lineMetadata").GetValue<SerializedDictionary<string, string>>();
var metadataValue = string.Join(" ", metadata);
if (!string.IsNullOrWhiteSpace(metadataValue))
_lineMetadata[line] = metadataValue;
else
_lineMetadata.Remove(line);
}

internal static void InsertInstruction(DredgeInstruction dredgeInstruction)
{
Yarn.Instruction instruction = new Instruction();
instruction.Opcode = dredgeInstruction.OpCode;

foreach (var operand in dredgeInstruction.Operands)
{
if (operand is string)
if (operand is string stringOperand)
{
instruction.Operands.Add(new Operand((string)operand));
instruction.Operands.Add(new Operand(stringOperand));
}
else if (operand is bool)
else if (operand is bool boolOperand)
{
instruction.Operands.Add(new Operand((bool)operand));
instruction.Operands.Add(new Operand(boolOperand));
}
else if (operand is float || operand is int)
{
Expand All @@ -177,19 +217,30 @@ internal static void InsertInstruction(DredgeInstruction dredgeInstruction)

DredgeDialogueRunner runner = GameManager.Instance.DialogueRunner;
Program program = Traverse.Create(runner.Dialogue).Field("program").GetValue<Program>();
Node node = program.Nodes[dredgeInstruction.NodeID];
if (program.Nodes.TryGetValue(dredgeInstruction.NodeID, out Node node))
{
int index = dredgeInstruction.Index;

node.Instructions.Insert(dredgeInstruction.Index, instruction);
if (index != -1)
node.Instructions.Insert(index, instruction);
else
{
index = node.Instructions.Count;
node.Instructions.Add(instruction);
}

foreach (var label in node.Labels)
{
if (label.Value >= dredgeInstruction.Index)
foreach (var label in node.Labels)
{
node.Labels[label.Key] += 1;
if (label.Value >= index)
{
node.Labels[label.Key] += 1;
}
}
}

if (!string.IsNullOrWhiteSpace(dredgeInstruction.Label)) node.Labels[dredgeInstruction.Label] = dredgeInstruction.Index;
if (!string.IsNullOrWhiteSpace(dredgeInstruction.Label)) node.Labels[dredgeInstruction.Label] = index;
}
else
WinchCore.Log.Error($"Failed to insert instruction into missing node \"{dredgeInstruction.NodeID}\"");
}

private static Dictionary<string, string> GetLinesForLocale(string localeId)
Expand Down Expand Up @@ -274,6 +325,8 @@ internal static void Inject()
Program oldProgram = Traverse.Create(runner.Dialogue).Field("program").GetValue<Program>();
var _lineMetadata = Traverse.Create(runner.yarnProject.lineMetadata).Field("_lineMetadata").GetValue<SerializedDictionary<string, string>>();

newProgram.Name = oldProgram.Name;

if (exportYarnProgram)
{
WriteYarnProgramToText("YarnProgramVanilla", oldProgram, _lineMetadata);
Expand All @@ -291,7 +344,10 @@ internal static void Inject()
{
newProgram.Nodes[nodeName.Key] = nodeName.Value.Clone();
}
newProgram.InitialValues.Add(modProgram.InitialValues);
foreach (var initialValue in modProgram.InitialValues)
{
newProgram.InitialValues[initialValue.Key] = initialValue.Value.Clone();
}
}

runner.Dialogue.SetProgram(newProgram);
Expand All @@ -300,9 +356,9 @@ internal static void Inject()
{
var metadataValue = string.Join(" ", metadataEntry.Value);
if (!string.IsNullOrWhiteSpace(metadataValue))
_lineMetadata.Add(metadataEntry.Key, metadataValue);
_lineMetadata.SafeAdd(metadataEntry.Key, metadataValue);
}

foreach (var instruction in instructions)
{
InsertInstruction(instruction);
Expand Down Expand Up @@ -367,6 +423,31 @@ public DredgeInstruction(string nodeID, int index, string label, Yarn.Instructio
}
}

internal class DredgeOption(Line line, string destination, bool enabled)
{
public Line Line { get; set; } = line;
public string Destination { get; set; } = destination;
public bool Enabled { get; set; } = enabled;

public DredgeOption(Line line, string destination) : this(line, destination, true)
{

}

public DredgeOption(string lineID, string destination, bool enabled) : this(new Line { ID = lineID, Substitutions = new string[0] }, destination, enabled)
{

}

public DredgeOption(string lineID, string destination) : this(lineID, destination, true)
{

}

public static implicit operator ValueTuple<Line, string, bool>(DredgeOption option)
=> (option.Line, option.Destination, option.Enabled);
}

internal static string GetProgramFileLocation(string fileName) => Path.Combine(WinchCore.WinchInstallLocation, $"{fileName}.txt");

internal static void WriteYarnProgramToText(string fileName, Program program, SerializedDictionary<string, string> lineMetadata)
Expand Down

0 comments on commit b755675

Please sign in to comment.