using Milimoe.FunGame.Core.Entity; using Milimoe.FunGame.Core.Library.Constant; using Milimoe.FunGame.Core.Model; using Milimoe.FunGame.Testing.Tests; using Oshima.FunGame.OshimaModules.Characters; using Oshima.FunGame.OshimaServers.Service; namespace Milimoe.FunGame.Testing.Solutions { /// /// 客户端逻辑层 /// /// public class RogueLike(RogueLikeDispatcher dispatcher) { public RogueLikeDispatcher Dispatcher { get; set; } = dispatcher; public Dictionary> Commands { get; set; } = []; public Dictionary CommandAlias { get; set; } = []; public User User { get; set; } = General.UnknownUserInstance; public bool Running { get; set; } = false; public bool InGame { get; set; } = false; public Lock Lock { get; } = new(); /// /// 为空表示没有正在进行的询问 /// private Guid _currentRequestGuid = Guid.Empty; /// /// 询问结果,和上面的字段配合使用 /// private TaskCompletionSource _requestTcs = new(); public async Task StartGame() { Running = true; Dispatcher.StartServer(); DataRequestArgs response = await DataRequest(new("login") { Data = { { "uid", 1 } } }); if (response.Data.TryGetValue("user", out object? value) && value is User user) { User = user; } else { return; } // 初始化菜单指令 Commands["quit"] = async (args) => { Running = false; WriteLine("游戏结束!"); }; AddCommandAlias("quit", "退出", "exit", "!q"); Commands["test"] = async (args) => { WriteLine("打木桩测试"); Character enemy = new CustomCharacter(0, "木桩") { Level = User.Inventory.MainCharacter.Level, CharacterState = CharacterState.NotActionable }; enemy.Recovery(); List strings = (await FunGameActionQueue.NewAndStartGame([User.Inventory.MainCharacter, enemy], showAllRound: true)).Result; foreach (string str in strings) { WriteLine(str); } }; Commands["help"] = Help; Commands["start"] = async (args) => { if (InGame) { return; } InGame = true; await Start(); InGame = false; }; AddCommandAlias("help", "菜单", "h", "帮助"); AddCommandAlias("start", "开局"); await Help([]); while (Running) { if (InGame) { await Task.Delay(1000); continue; } string input = await GetTextResultsAsync([]); string[] strings = input.Split(" ", StringSplitOptions.RemoveEmptyEntries); if (strings.Length == 0) { continue; } string command = strings[0]; string[] args = [.. strings.Skip(1)]; if (Commands.TryGetValue(command.ToLower(), out Func? func) && func != null) { await func.Invoke(args); } else if (CommandAlias.TryGetValue(command.ToLower(), out string? actualCommand) && actualCommand != null) { if (Commands.TryGetValue(actualCommand, out Func? func2) && func2 != null) { await func2.Invoke(args); } } else { WriteLine("未知指令"); } } } public Action WriteLineHandler { get => field ?? Console.WriteLine; set => field = value; } public delegate Task ReadInput(Dictionary args, List results); public delegate Task ReadInputInquiryResponse(InquiryOptions options); public event ReadInput? ReadInputStringHandler; public event ReadInput? ReadInputNumberHandler; public event ReadInputInquiryResponse? ReadInputInquiryResponseHandler; public async Task> GetChoiceResultsAsync(InquiryOptions options, Dictionary args) { int index = 0; Dictionary indexToChoice = []; foreach (string choice in options.Choices.Keys) { index++; indexToChoice[index] = choice; WriteLine($"{index}. {choice}:{options.Choices[choice]}"); } WriteLine($"--- {options.Topic} ---"); List results = []; if (ReadInputStringHandler != null) { await ReadInputStringHandler.Invoke(args, results); } return [.. indexToChoice.Where(kv => results.Contains(kv.Key.ToString())).Select(kv => kv.Value)]; } public async Task> GetNumberResultsAsync(Dictionary args) { List results = []; if (ReadInputNumberHandler != null) { await ReadInputNumberHandler.Invoke(args, results); } return results; } public async Task GetTextResultsAsync(Dictionary args) { List results = []; if (ReadInputStringHandler != null) { await ReadInputStringHandler.Invoke(args, results); } return results.FirstOrDefault() ?? ""; } public async Task DataRequest(DataRequestArgs args) { _requestTcs.TrySetCanceled(); _currentRequestGuid = Guid.NewGuid(); _requestTcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); await Dispatcher.DataRequest(_currentRequestGuid, args); return await _requestTcs.Task; } public async Task DataRequestComplete(Guid guid, DataRequestArgs response) { if (guid == _currentRequestGuid) { _currentRequestGuid = Guid.Empty; _requestTcs.TrySetResult(response); } } public async Task GetInquiryResponse(InquiryOptions options) { if (ReadInputInquiryResponseHandler is null) return new(options); return await ReadInputInquiryResponseHandler.Invoke(options); } public void WriteLine(string message = "") { WriteLineHandler(message); } public void AddDialog(string speaker, string message) { WriteLine(BuildSpeakerDialog(speaker, message)); } public static string BuildSpeakerDialog(string speaker, string message) { return $"【{speaker}】{message}"; } private void AddCommandAlias(string command, params string[] aliases) { foreach (string alias in aliases) { CommandAlias[alias] = command; } } public string GetCommandAliases(string command) { string[] alias = [.. CommandAlias.Where(kv => kv.Value == command).Select(kv => kv.Key)]; return alias.Length > 0 ? $"(替代:{string.Join(",", alias)})" : ""; } private async Task Help(string[] args) { WriteLine($"可用指令:{string.Join(",", Commands.Keys.Select(c => $"{c}{GetCommandAliases(c)}"))}"); } private async Task Start() { await Dispatcher.CreateGameLoop(User.Username); } } }