using System.Collections.Generic; using System.Text; using UnityEngine; using UnityEngine.Networking; using YIUIFramework; using cfg; namespace ET.Client { [FriendOf(typeof(ClientSenderComponent))] [FriendOf(typeof(HeroComponent))] [FriendOf(typeof(BagComponent))] public static class GMHeroBagHelper { public static ClientSenderComponent GetSender(Scene clientScene) { return clientScene?.GetComponent(); } public static bool CheckSender(Scene clientScene) { ClientSenderComponent sender = GetSender(clientScene); if (sender == null || sender.netClientActorId.Fiber == 0) { Debug.LogError("[GM] 当前未登录或网络通道未建立,请先登录。"); return false; } return true; } public static Dictionary BuildHeroConfigDropdown() { Tables tables = new(); Dictionary options = new(); foreach (HeroRow row in tables.TbHero.GetAll()) { string title = $"{row.Id} - {row.Name}"; options[title] = row.Id.ToString(); } return options; } } [GM(EGMType.Common, 1, "Hero-召唤", "RPC: C2G_SummonHero")] public class GM_HeroSummon : IGMCommand { public List GetParams() { Dictionary options = GMHeroBagHelper.BuildHeroConfigDropdown(); string defaultConfigId = "10001"; foreach (KeyValuePair pair in options) { defaultConfigId = pair.Value; break; } return new() { new GMParamInfo(EGMParamType.Int, "英雄配置ID(下拉来自TbHero)", defaultConfigId) { OptionDic = options }, }; } public async ETTask Run(Scene clientScene, ParamVo paramVo) { if (!GMHeroBagHelper.CheckSender(clientScene)) { return false; } int configId = paramVo.Get(0); C2G_SummonHero request = C2G_SummonHero.Create(); request.configId = configId; R2C_SummonHero response = await GMHeroBagHelper.GetSender(clientScene).Call(request, false) as R2C_SummonHero; Debug.Log($"[GM] Hero-召唤: error={response?.Error} msg={response?.Message} heroId={response?.hero?.heroId}"); return false; } } [GM(EGMType.Common, 1, "Hero-加经验", "RPC: C2G_HeroAddExp")] public class GM_HeroAddExpRpc : IGMCommand { public List GetParams() { return new() { new GMParamInfo(EGMParamType.Long, "heroId", "0"), new GMParamInfo(EGMParamType.Int, "itemId", "1"), new GMParamInfo(EGMParamType.Int, "count", "1"), }; } public async ETTask Run(Scene clientScene, ParamVo paramVo) { if (!GMHeroBagHelper.CheckSender(clientScene)) { return false; } C2G_HeroAddExp request = C2G_HeroAddExp.Create(); request.heroId = paramVo.Get(0); request.itemId = paramVo.Get(1); request.count = paramVo.Get(2); R2C_HeroAddExp response = await GMHeroBagHelper.GetSender(clientScene).Call(request, false) as R2C_HeroAddExp; Debug.Log($"[GM] Hero-加经验: error={response?.Error} msg={response?.Message} lv={response?.hero?.level} exp={response?.hero?.exp}"); return false; } } [GM(EGMType.Common, 1, "Hero-升技能", "RPC: C2G_HeroSkillUp")] public class GM_HeroSkillUpRpc : IGMCommand { public List GetParams() { return new() { new GMParamInfo(EGMParamType.Long, "heroId", "0"), new GMParamInfo(EGMParamType.Int, "skillIndex", "0"), }; } public async ETTask Run(Scene clientScene, ParamVo paramVo) { if (!GMHeroBagHelper.CheckSender(clientScene)) { return false; } C2G_HeroSkillUp request = C2G_HeroSkillUp.Create(); request.heroId = paramVo.Get(0); request.skillIndex = paramVo.Get(1); R2C_HeroSkillUp response = await GMHeroBagHelper.GetSender(clientScene).Call(request, false) as R2C_HeroSkillUp; Debug.Log($"[GM] Hero-升技能: error={response?.Error} msg={response?.Message}"); return false; } } [GM(EGMType.Common, 1, "Bag-使用道具", "RPC: C2G_UseItem")] public class GM_BagUseItemRpc : IGMCommand { public List GetParams() { return new() { new GMParamInfo(EGMParamType.Long, "itemIndex", "0"), new GMParamInfo(EGMParamType.Int, "count", "1"), }; } public async ETTask Run(Scene clientScene, ParamVo paramVo) { if (!GMHeroBagHelper.CheckSender(clientScene)) { return false; } C2G_UseItem request = C2G_UseItem.Create(); request.itemIndex = paramVo.Get(0); request.count = paramVo.Get(1); R2C_UseItem response = await GMHeroBagHelper.GetSender(clientScene).Call(request, false) as R2C_UseItem; Debug.Log($"[GM] Bag-使用道具: error={response?.Error} msg={response?.Message}"); return false; } } [GM(EGMType.Common, 1, "Hero-穿装备", "RPC: C2G_HeroWearEquip")] public class GM_HeroWearEquipRpc : IGMCommand { public List GetParams() { return new() { new GMParamInfo(EGMParamType.Long, "heroId", "0"), new GMParamInfo(EGMParamType.Long, "itemIndex", "0"), new GMParamInfo(EGMParamType.Int, "slotIndex", "1"), }; } public async ETTask Run(Scene clientScene, ParamVo paramVo) { if (!GMHeroBagHelper.CheckSender(clientScene)) { return false; } C2G_HeroWearEquip request = C2G_HeroWearEquip.Create(); request.heroId = paramVo.Get(0); request.itemIndex = paramVo.Get(1); request.slotIndex = paramVo.Get(2); R2C_HeroWearEquip response = await GMHeroBagHelper.GetSender(clientScene).Call(request, false) as R2C_HeroWearEquip; Debug.Log($"[GM] Hero-穿装备: error={response?.Error} msg={response?.Message}"); return false; } } [GM(EGMType.Common, 1, "Hero-卸装备", "RPC: C2G_TakeOffEquip")] public class GM_HeroTakeOffEquipRpc : IGMCommand { public List GetParams() { return new() { new GMParamInfo(EGMParamType.Long, "heroId", "0"), new GMParamInfo(EGMParamType.Int, "slotIndex", "1"), }; } public async ETTask Run(Scene clientScene, ParamVo paramVo) { if (!GMHeroBagHelper.CheckSender(clientScene)) { return false; } C2G_TakeOffEquip request = C2G_TakeOffEquip.Create(); request.heroId = paramVo.Get(0); request.slotIndex = paramVo.Get(1); R2C_TakeOffEquip response = await GMHeroBagHelper.GetSender(clientScene).Call(request, false) as R2C_TakeOffEquip; Debug.Log($"[GM] Hero-卸装备: error={response?.Error} msg={response?.Message}"); return false; } } [GM(EGMType.Common, 1, "缓存-显示Hero列表", "打印客户端Hero缓存")] [FriendOf(typeof(HeroComponent))] public class GM_ShowHeroCache : IGMCommand { public List GetParams() { return new(); } public async ETTask Run(Scene clientScene, ParamVo paramVo) { HeroComponent heroComp = clientScene.GetComponent(); if (heroComp == null || heroComp.HeroMap.Count == 0) { Debug.LogWarning("[GM] Hero缓存为空"); return false; } StringBuilder sb = new(); sb.Append($"[GM] Hero缓存 count={heroComp.HeroMap.Count}"); foreach (var pair in heroComp.HeroMap) { HeroInfo hero = pair.Value; sb.Append($" | id={hero.heroId},cfg={hero.configId},lv={hero.level},star={hero.star}"); } Debug.Log(sb.ToString()); await ETTask.CompletedTask; return false; } } [GM(EGMType.Common, 1, "缓存-显示Bag列表", "打印客户端Bag缓存")] [FriendOf(typeof(BagComponent))] public class GM_ShowBagCache : IGMCommand { public List GetParams() { return new(); } public async ETTask Run(Scene clientScene, ParamVo paramVo) { BagComponent bagComp = clientScene.GetComponent(); if (bagComp == null || bagComp.ItemMap.Count == 0) { Debug.LogWarning("[GM] Bag缓存为空"); return false; } StringBuilder sb = new(); sb.Append($"[GM] Bag缓存 count={bagComp.ItemMap.Count}"); foreach (var pair in bagComp.ItemMap) { ItemInfo item = pair.Value; sb.Append($" | idx={item.itemIndex},itemId={item.itemId},count={item.count},heroId={item.heroId}"); } Debug.Log(sb.ToString()); await ETTask.CompletedTask; return false; } } [GM(EGMType.Common, 1, "ServerGM-执行文本", "走HttpGMHandler执行服务端GM命令")] public class GM_ServerCommandHttp : IGMCommand { public List GetParams() { return new() { new GMParamInfo(EGMParamType.String, "url", "http://127.0.0.1:10002/gm"), new GMParamInfo(EGMParamType.String, "password(可空)", ""), new GMParamInfo(EGMParamType.String, "command", "ShowHeroes"), }; } public async ETTask Run(Scene clientScene, ParamVo paramVo) { string url = paramVo.Get(0); string password = paramVo.Get(1); string command = paramVo.Get(2); if (string.IsNullOrWhiteSpace(url) || string.IsNullOrWhiteSpace(command)) { Debug.LogError("[GM] url / command 不能为空"); return false; } byte[] bytes = Encoding.UTF8.GetBytes(command); using UnityWebRequest req = new(url, UnityWebRequest.kHttpVerbPOST); req.uploadHandler = new UploadHandlerRaw(bytes); req.downloadHandler = new DownloadHandlerBuffer(); req.SetRequestHeader("Content-Type", "text/plain; charset=utf-8"); if (!string.IsNullOrWhiteSpace(password)) { req.SetRequestHeader("X-GM-Password", password); } await req.SendWebRequest(); bool ok = req.result == UnityWebRequest.Result.Success; string text = req.downloadHandler?.text ?? string.Empty; Debug.Log($"[GM] ServerGM result={(ok ? "OK" : "FAIL")} code={req.responseCode} body={text}"); return false; } } }