mirror of
https://github.com/HoonTB/Project-AS.git
synced 2025-12-26 20:01:21 +09:00
262 lines
8.1 KiB
C#
262 lines
8.1 KiB
C#
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using Cysharp.Threading.Tasks;
|
|
using UnityEngine;
|
|
|
|
/// <summary>Command 배열을 ScriptAction 배열로 컴파일</summary>
|
|
public class Compiler
|
|
{
|
|
private readonly Dictionary<string, int> _labelMap;
|
|
|
|
private Compiler(Dictionary<string, int> labelMap)
|
|
{
|
|
_labelMap = labelMap;
|
|
}
|
|
|
|
/// <summary>컴파일 시점에만 사용되는 선택지 데이터</summary>
|
|
private class ChoiceData
|
|
{
|
|
public string RawText;
|
|
public string TargetLabel;
|
|
public int TargetIndex;
|
|
}
|
|
|
|
public static ScriptAction[] Compile(List<Command> commands, Dictionary<string, int> labelMap)
|
|
{
|
|
var compiler = new Compiler(labelMap);
|
|
return commands.Select(compiler.CompileCommand).ToArray();
|
|
}
|
|
|
|
private ScriptAction CompileCommand(Command cmd)
|
|
{
|
|
return cmd.Type switch
|
|
{
|
|
"label" => CompileLabel(cmd),
|
|
"msg" => CompileMsg(cmd),
|
|
"spk" => CompileSpk(cmd),
|
|
"char" => CompileChar(cmd),
|
|
"remove" => CompileRemove(cmd),
|
|
"action" => CompileAction(cmd),
|
|
"expr" => CompileExpr(cmd),
|
|
"goto" => CompileGoto(cmd),
|
|
"choices" => CompileChoices(cmd),
|
|
"var" => CompileVar(cmd),
|
|
"add" => CompileAdd(cmd),
|
|
"bg" => CompileBg(cmd),
|
|
"script" => CompileScript(cmd),
|
|
_ => CompileUnknown(cmd)
|
|
};
|
|
}
|
|
|
|
// ===== 헬퍼 메서드 =====
|
|
|
|
private static ScriptAction SyncAction(string type, string debugInfo, System.Action<ScriptContext> execute)
|
|
{
|
|
return new ScriptAction
|
|
{
|
|
DebugType = type,
|
|
DebugInfo = debugInfo,
|
|
Execute = ctx =>
|
|
{
|
|
execute(ctx);
|
|
return UniTask.FromResult(ScriptResult.Continue);
|
|
}
|
|
};
|
|
}
|
|
|
|
// ===== 개별 컴파일러 =====
|
|
|
|
private ScriptAction CompileLabel(Command cmd)
|
|
{
|
|
return new ScriptAction
|
|
{
|
|
DebugType = "label",
|
|
DebugInfo = cmd.GetParam("content"),
|
|
Execute = _ => UniTask.FromResult(ScriptResult.Continue)
|
|
};
|
|
}
|
|
|
|
private ScriptAction CompileMsg(Command cmd)
|
|
{
|
|
var rawContent = cmd.GetParam("content");
|
|
return new ScriptAction
|
|
{
|
|
DebugType = "msg",
|
|
DebugInfo = rawContent.Length > 20 ? rawContent[..20] + "..." : rawContent,
|
|
Execute = ctx => ExecuteMsg(ctx, rawContent)
|
|
};
|
|
}
|
|
|
|
private static UniTask<ScriptResult> ExecuteMsg(ScriptContext ctx, string rawContent)
|
|
{
|
|
string content = ctx.VariableStore.ReplaceVariables(rawContent);
|
|
ctx.DialogueStore.Dialogue.Value = content;
|
|
|
|
return UniTask.FromResult(
|
|
ctx.PeekNextType?.Invoke() == "choices"
|
|
? ScriptResult.Continue
|
|
: ScriptResult.Wait);
|
|
}
|
|
|
|
private ScriptAction CompileSpk(Command cmd)
|
|
{
|
|
var rawName = cmd.GetParam("name");
|
|
return SyncAction("spk", rawName, ctx =>
|
|
ctx.DialogueStore.Speaker.Value = ctx.VariableStore.ReplaceVariables(rawName));
|
|
}
|
|
|
|
private ScriptAction CompileChar(Command cmd)
|
|
{
|
|
var img = cmd.GetParam("img");
|
|
var direction = ParseDirectionType(cmd.GetParam("enter"));
|
|
return SyncAction("char", img, ctx =>
|
|
{
|
|
var sprite = ctx.LoadCharacterSprite(img);
|
|
if (sprite != null)
|
|
ctx.CharacterStore.Add(img, sprite, direction);
|
|
});
|
|
}
|
|
|
|
private ScriptAction CompileRemove(Command cmd)
|
|
{
|
|
var target = cmd.GetParam("target");
|
|
var direction = ParseDirectionType(cmd.GetParam("exit"));
|
|
return SyncAction("remove", target, ctx =>
|
|
ctx.CharacterStore.Remove(target, direction));
|
|
}
|
|
|
|
private ScriptAction CompileAction(Command cmd)
|
|
{
|
|
var target = cmd.GetParam("target");
|
|
var animationType = ParseAnimationType(cmd.GetParam("anim"));
|
|
return SyncAction("action", $"{target}:{animationType}", ctx =>
|
|
ctx.CharacterStore.PlayAction(target, animationType));
|
|
}
|
|
|
|
private ScriptAction CompileExpr(Command cmd)
|
|
{
|
|
var target = cmd.GetParam("target");
|
|
var expr = cmd.GetParam("expr").ToLower();
|
|
return SyncAction("expr", $"{target}:{expr}", ctx =>
|
|
{
|
|
var sprite = ctx.LoadCharacterSprite(expr);
|
|
if (sprite != null)
|
|
ctx.CharacterStore.ChangeExpression(target, sprite);
|
|
});
|
|
}
|
|
|
|
private ScriptAction CompileGoto(Command cmd)
|
|
{
|
|
var targetLabel = cmd.GetParam("content");
|
|
var targetIndex = _labelMap[targetLabel];
|
|
return new ScriptAction
|
|
{
|
|
DebugType = "goto",
|
|
DebugInfo = targetLabel,
|
|
Execute = _ => UniTask.FromResult(ScriptResult.JumpTo(targetIndex))
|
|
};
|
|
}
|
|
|
|
private ScriptAction CompileChoices(Command cmd)
|
|
{
|
|
var choices = cmd.Choices.Select(c => new ChoiceData
|
|
{
|
|
RawText = c["content"],
|
|
TargetLabel = c["goto"],
|
|
TargetIndex = _labelMap[c["goto"]]
|
|
}).ToList();
|
|
|
|
return new ScriptAction
|
|
{
|
|
DebugType = "choices",
|
|
DebugInfo = $"{choices.Count} options",
|
|
Execute = ctx => ExecuteChoices(ctx, choices)
|
|
};
|
|
}
|
|
|
|
private static UniTask<ScriptResult> ExecuteChoices(ScriptContext ctx, List<ChoiceData> choices)
|
|
{
|
|
var options = choices.Select(c => new ChoiceOption
|
|
{
|
|
Text = ctx.VariableStore.ReplaceVariables(c.RawText),
|
|
TargetLabel = c.TargetLabel,
|
|
TargetIndex = c.TargetIndex
|
|
}).ToList();
|
|
|
|
ctx.ChoiceStore.Show(options);
|
|
return UniTask.FromResult(ScriptResult.Wait);
|
|
}
|
|
|
|
private ScriptAction CompileVar(Command cmd)
|
|
{
|
|
var pairs = cmd.Params.ToDictionary(p => p.Key, p => p.Value.ToString());
|
|
return SyncAction("var", string.Join(",", pairs.Keys), ctx =>
|
|
{
|
|
foreach (var kvp in pairs)
|
|
ctx.VariableStore.SetVariable(kvp.Key, kvp.Value);
|
|
});
|
|
}
|
|
|
|
private ScriptAction CompileAdd(Command cmd)
|
|
{
|
|
var pairs = cmd.Params.ToDictionary(p => p.Key, p => p.Value.ToString());
|
|
return SyncAction("add", string.Join(",", pairs.Keys), ctx =>
|
|
{
|
|
foreach (var kvp in pairs)
|
|
ctx.VariableStore.AddVariable(kvp.Key, kvp.Value);
|
|
});
|
|
}
|
|
|
|
private ScriptAction CompileScript(Command cmd)
|
|
{
|
|
var scriptPath = cmd.GetParam("file");
|
|
return new ScriptAction
|
|
{
|
|
DebugType = "script",
|
|
DebugInfo = scriptPath,
|
|
Execute = ctx =>
|
|
{
|
|
ctx.OnScriptChange?.Invoke(scriptPath);
|
|
return UniTask.FromResult(ScriptResult.End);
|
|
}
|
|
};
|
|
}
|
|
|
|
private ScriptAction CompileBg(Command cmd)
|
|
{
|
|
var file = cmd.GetParam("file");
|
|
return SyncAction("bg", file, ctx =>
|
|
Debug.Log($"Background: {file}")); // TODO: 배경 변경 로직
|
|
}
|
|
|
|
private ScriptAction CompileUnknown(Command cmd)
|
|
{
|
|
return SyncAction(cmd.Type, "unknown", ctx =>
|
|
Debug.LogWarning($"Unknown command: {cmd.Type}"));
|
|
}
|
|
|
|
// ===== Enum 파서 (컴파일 타임 변환) =====
|
|
private static AnimationType ParseAnimationType(string str) => str.ToLower() switch
|
|
{
|
|
"jump" => AnimationType.Jump,
|
|
"shake" => AnimationType.Shake,
|
|
"run" => AnimationType.Run,
|
|
"nod" => AnimationType.Nod,
|
|
"punch" => AnimationType.Punch,
|
|
_ => AnimationType.Nod
|
|
};
|
|
|
|
private static DirectionType ParseDirectionType(string str) => str.ToLower() switch
|
|
{
|
|
"left" => DirectionType.Left,
|
|
"right" => DirectionType.Right,
|
|
"center" => DirectionType.Center,
|
|
"bottomleft" => DirectionType.BottomLeft,
|
|
"bottomright" => DirectionType.BottomRight,
|
|
"top" => DirectionType.Top,
|
|
"runleft" => DirectionType.RunLeft,
|
|
"runright" => DirectionType.RunRight,
|
|
_ => DirectionType.Center
|
|
};
|
|
}
|