feat(upserver): 保存M2客户端KV迁移至本人统计写检查点

保存独立KV用户服务、固定会话存档与原业务接线,以及C3d资料缓存和C3e本人统计写。
保留原PF/AGG路线、业务公式和时序;榜单读取、好友资料、公告、匹配及首场景闸仍待完成。

验证:ServiceHost两条件各33组646断言;Unity CLI Loop编译0错误269警告。
包含相关方案、评审裁决、测试及状态文档。未操作服务器、正式账号或打包。
This commit is contained in:
Liubing\LB
2026-09-30 19:19:05 +08:00
parent 1c0cdf7a99
commit 6813da149a
511 changed files with 151858 additions and 2376 deletions

View File

@@ -0,0 +1,829 @@
using asap.core;
using cfg;
using game;
using GameCore;
using Newtonsoft.Json.Linq;
using PlayFab;
using PlayFab.MultiplayerModels;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using TMPro;
using UniRx;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.UI;
public class EventFishingDuelPanel : BasePanel
{
Tables tables;
Button btn_close;
GameObject btn_close_image;
Animation anim;
GameObject MiddlePanel;
TMP_Text text_time;
Image icon_rank;
TMP_Text text_rank;
Button btn_questionmark1;
Button btn_questionmark;
GameObject bg_bar;
Image bar;
TMP_Text text_progress;
Button btn_reward;
List<RewardItemNew> rewardItemNews;
TMP_Text win_text_num;
TMP_Text loss_text_num;
TMP_Text middle_text_time;
Button icon_ticket;
Button btn_confirm;
GameObject loading;
GameObject p_text;
TMP_Text text_num;
//GameObject effect_beilv_loop;
Button btn_beilv;
//Image btn_beilv_image;
Button btn_beilv_max;
//private Image btn_beilv_max_image;
TMP_Text text_beilv;
TMP_Text text_beilv_max;
TMP_Text text_beilv_show;
GameObject matchingPanel;
DuelMatchPlayer myself;
DuelMatchPlayer enemy;
GameObject fx_ui_matchingPanel_match_glow_01;
TMP_Text match_text_time;
Button but_stop;
Coroutine matchIng;
FishingDuelManager FDM;
Sound audio_matchingloop;
AudioClip audio_ui_fishingduel_matchingloop;
IUIService uiService;
Timer timer;
FishingEventData fishingEventData;
Button btn_advert;
DuelRandomMapPanel randomMapPanel;
GameObject fishConfrimPanel;
TicketTips ticket_tips;
IDisposable disRequestSvrTime;
float MatchPlayerProb;
private void Awake()
{
fishingEventData = GContext.container.Resolve<FishingEventData>();
uiService = GContext.container.Resolve<IUIService>();
tables = GContext.container.Resolve<Tables>();
btn_close = transform.Find("bottom/btn_close").GetComponent<Button>();
btn_close_image = transform.Find("bottom/btn_close/Image").gameObject;
GContext.container.Unregister<FishingDuelManager>();
FDM = new FishingDuelManager();
GContext.container.RegisterInstance(FDM);
btn_advert = transform.Find("root/MiddlePanel/bottom/btn_advert").GetComponent<Button>();
//====================倍率调整
btn_beilv = transform.Find("root/MiddlePanel/bottom/beilv").GetComponent<Button>();
btn_beilv_max = transform.Find("root/MiddlePanel/bottom/beilv_max").GetComponent<Button>();
text_beilv = transform.Find("root/MiddlePanel/bottom/beilv/text_beilv").GetComponent<TMP_Text>();
text_beilv_max = transform.Find("root/MiddlePanel/bottom/beilv_max/text_beilv").GetComponent<TMP_Text>();
//====================
ticket_tips = transform.Find("root/MiddlePanel/bottom/ticket_tips").GetComponent<TicketTips>();
//UI_EventPartnerFishbowlPanel_27
anim = transform.Find("root/matchingPanel").GetComponent<Animation>();
btn_questionmark1 = transform.Find("root/MiddlePanel/top/title/btn_questionmark").GetComponent<Button>();
//===================匹配界面
MiddlePanel = transform.Find("root/MiddlePanel").gameObject;
text_time = transform.Find("root/MiddlePanel/top/text_time").GetComponent<TMP_Text>();
icon_rank = transform.Find("root/MiddlePanel/rank/icon_rank").GetComponent<Image>();
text_rank = transform.Find("root/MiddlePanel/rank/text_rank").GetComponent<TMP_Text>();
btn_questionmark = transform.Find("root/MiddlePanel/rank/text_rank/btn_questionmark").GetComponent<Button>();
bg_bar = transform.Find("root/MiddlePanel/rank/bg_bar").gameObject;
bar = transform.Find("root/MiddlePanel/rank/bg_bar/bar").GetComponent<Image>();
text_progress = transform.Find("root/MiddlePanel/rank/bg_bar/text_progress").GetComponent<TMP_Text>();
btn_reward = transform.Find("root/MiddlePanel/rank/btn_reward").GetComponent<Button>();
rewardItemNews = new List<RewardItemNew>();
Transform layout_reward = transform.Find("root/MiddlePanel/reward/layout_reward");
int layout_reward_count = layout_reward.childCount;
for (int i = 0; i < layout_reward_count; i++)
{
rewardItemNews.Add(layout_reward.GetChild(i).GetComponent<RewardItemNew>());
}
icon_ticket = transform.Find("root/MiddlePanel/bottom/icon_ticket").GetComponent<Button>();
win_text_num = transform.Find("root/MiddlePanel/reward/info/win/text_num").GetComponent<TMP_Text>();
loss_text_num = transform.Find("root/MiddlePanel/reward/info/loss/text_num").GetComponent<TMP_Text>();
btn_confirm = transform.Find("root/MiddlePanel/bottom/btn_confirm/btn_green").GetComponent<Button>();
loading = transform.Find("root/MiddlePanel/bottom/btn_confirm/btn_green/Ani_Container/loading").gameObject;
p_text = transform.Find("root/MiddlePanel/bottom/btn_confirm/btn_green/Ani_Container/p_text").gameObject;
middle_text_time = transform.Find("root/MiddlePanel/top/text_time").GetComponent<TMP_Text>();
text_num = transform.Find("root/MiddlePanel/bottom/icon_ticket/text_num").GetComponent<TMP_Text>();
//================================
//=====================匹配中
matchingPanel = transform.Find("root/matchingPanel").gameObject;
myself = transform.Find("root/matchingPanel/myself").GetComponent<DuelMatchPlayer>();
enemy = transform.Find("root/matchingPanel/enermy").GetComponent<DuelMatchPlayer>();
match_text_time = transform.Find("root/matchingPanel/text_time").GetComponent<TMP_Text>();
but_stop = transform.Find("root/matchingPanel/btn_stop/btn_green").GetComponent<Button>();
fx_ui_matchingPanel_match_glow_01 = transform.Find("root/matchingPanel/enermy/fx_ui_matchingPanel_match_glow_01").gameObject;
//=================================
randomMapPanel = transform.Find("root/matchingPanel/RandomMap").GetComponent<DuelRandomMapPanel>();
fishConfrimPanel = transform.Find("root/FishConfirmPanel").gameObject;
fishConfrimPanel.SetActive(false);
LoadAudio();
GContext.container.Resolve<GuideDataCenter>().InspectTriggerGuide("EventFishingDuelPanel");
CheckResource();
MatchPlayerProb = FDM.eventSoloConfig.MatchPlayerProb;
}
ILoadResourceService loadResourceService;
IDisposable loadResourceIdis;
string resourceKey;
public async void CheckResource()
{
PlayerFishData playerFishData = GContext.container.Resolve<PlayerFishData>();
List<int> rodIDs = tables.TbRodData.DataList.FindAll(_ => !playerFishData.NotRod(_.ID)).Select(_ => _.ID).ToList();
List<string> resourceName = new List<string>();
RodSkinData rodSkinData;
foreach (var rodID in rodIDs)
{
int skindID = playerFishData.GetRodSkin(rodID);
rodSkinData = tables.TbRodSkinData.GetOrDefault(skindID);
resourceName.Add(rodSkinData.Fbx);
}
loadResourceService = GContext.container.Resolve<ILoadResourceService>();
resourceKey = "RodList" + rodIDs.Count;
SetLoading(true);
bool isReady = await loadResourceService.CheckResourceLoadQueue(resourceKey, resourceName);
if (!isReady)
{
loadResourceIdis = GContext.OnEvent<LoadEventResourceEvent>().Where(_ => _.key == resourceKey).Subscribe(LoadEventResourceEvent);
}
else
{
LoadEventResource(true);
}
}
void LoadEventResourceEvent(LoadEventResourceEvent loadEvent)
{
Debug.Log($"LoadEventResourceEvent {loadEvent.key} {loadEvent.isSucceeded} ");
DisposeEvent();
LoadEventResource(loadEvent.isSucceeded);
}
void DisposeEvent()
{
loadResourceIdis?.Dispose();
loadResourceIdis = null;
}
void LoadEventResource(bool succeeded)
{
if (this == null)
{
return;
}
if (succeeded)
{
try
{
SetLoading(false);
}
catch (System.Exception e)
{
Debug.LogError($"Load Event Resource Exception! == {gameObject.name} \n {e}");
}
}
else
{
Debug.LogError($"Load Event Resource Failed! == {gameObject.name}");
}
}
async void LoadAudio()
{
audio_ui_fishingduel_matchingloop = await Addressables.LoadAssetAsync<AudioClip>("audio_ui_fishingduel_matchingloop").Task;
}
protected override void Start()
{
base.Start();
GContext.Publish(new HideHomePanelEvent());
//disposable = GContext.OnEvent<RewardPanelClose>().Subscribe(OnRewardPanelClose);
ShowPanel(false);
btn_close.onClick.AddListener(OnClickClose);
InitMiddlePanel();
but_stop.onClick.AddListener(OnClickStop);
IUserService userService = GContext.container.Resolve<IUserService>();
var url = userService.AvatarUrl;
uiService.SetHeadImage(myself.icon_head, url);
myself.text_name.text = userService.DisplayName;
myself.icon_rank.sprite = icon_rank.sprite;
myself.text_score.text = ConvertTools.GetNumberString2(FDM.duelData.progress);
btn_beilv.onClick.AddListener(OnclickMagnification);
btn_beilv_max.onClick.AddListener(OnclickMagnification);
SetShowMagnification();
btn_reward.onClick.AddListener(() => _ = UIManager.Instance.ShowUI(UITypes.EventFishingDuelRewardPopupPanel));
btn_advert.onClick.AddListener(() => _ = UIManager.Instance.ShowUI(UITypes.EventFishingduelShopPopupPanel));
Item itemdata = tables.TbItem.GetOrDefault(2051);
string nameL = LocalizationMgr.GetText(itemdata.Name_l10n_key);
ticket_tips.SetText(LocalizationMgr.GetFormatTextValue("UI_EventPartnerFishbowlPanel_27", nameL));
}
void OnclickMagnification()
{
FDM.SetMagnification();
SetShowMagnification();
}
void SetShowMagnification()
{
bool IsMax = FDM.IsMaxMagnification();
btn_beilv.gameObject.SetActive(!IsMax);
btn_beilv_max.gameObject.SetActive(IsMax);
text_beilv.text = text_beilv_max.text = $"x{FDM.magnification}";
SetReward();
}
//void OnRewardPanelClose(RewardPanelClose rewardPanelClose)
//{
// SetEnergy();
//}
void SetEnergy()
{
//获取配置表
int MatchCost = FDM.magnification;
int Energy = FDM.duelData.tickets;
if (MatchCost > Energy)
{
//ConvertTools.GetNumberString
text_num.text = $"<color=red>{Energy}/{MatchCost}</color>";
}
else
{
text_num.text = $"{Energy}/{MatchCost}";
}
}
void SetReward()
{
var rewardItemData = FDM.GetReward();
if (rewardItemData != null)
{
int dataCount = rewardItemData.Count;
int rewardCount = rewardItemNews.Count;
for (int i = 0; i < rewardCount; i++)
{
if (i < dataCount)
{
rewardItemData[i].count *= FDM.magnification;
rewardItemNews[i].SetData(rewardItemData[i]);
}
else
{
rewardItemNews[i].gameObject.SetActive(false);
}
}
}
win_text_num.text = $"+{FDM.eventSolomain.WinTrophy * FDM.magnification}";
loss_text_num.text = $"-{FDM.eventSolomain.LoseTrophy * FDM.magnification}";
SetEnergy();
}
void InitMiddlePanel()
{
DoConsumeBait();
icon_ticket.onClick.AddListener(OnClickIcon);
btn_confirm.onClick.AddListener(OnClickMaching);
btn_questionmark.onClick.AddListener(() => _ = UIManager.Instance.ShowUI(UITypes.EventFishingDuelRankPopupPanel));
btn_questionmark1.onClick.AddListener(() => _ = UIManager.Instance.ShowUI(UITypes.EventFishingDuelInfoPopupPanel));
uiService.SetImageSprite(icon_rank, FDM.eventSolomain.RankIcon);
text_rank.text = LocalizationMgr.GetText(FDM.eventSolomain.RankText_l10n_key);
text_progress.text = $"{FDM.duelData.progress}";
win_text_num.text = $"+{FDM.eventSolomain.WinTrophy * FDM.magnification}";
loss_text_num.text = $"-{FDM.eventSolomain.LoseTrophy * FDM.magnification}";
}
private void DoConsumeBait()
{
Debug.Log("NetworkReachability");
if (Application.internetReachability == NetworkReachability.NotReachable)
{
Debug.Log("NetworkReachability.NotReachable");
NoInternet();
}
}
private async void NoInternet()
{
GameObject go = await UIManager.Instance.ShowUI(UITypes.NoticeConfirmPopupPanel);
var NoticeConfirmPopupPanel = go.GetComponent<NoticeConfirmPopupPanel>();
string info = LocalizationMgr.GetText("UI_FishingReconnectPanel_101003");
string label = LocalizationMgr.GetText("UI_FishingRewardPanel_101022");
string title = LocalizationMgr.GetText("UI_FishingReconnectPanel_101002");
NoticeConfirmPopupPanel.Init(1, title, info,
onClickLeft: DoConsumeBait,
onClose: DoConsumeBait,
btn_left_text: label);
}
void OnClickMaching()
{
if (FDM.duelData.tickets < FDM.magnification)
{
ToastPanel.Show(LocalizationMgr.GetText("UI_ToastPanel_86"));
//var pos = btn_confirm.transform.position;
//pos.y += 50;
//ticket_tips.SetPos(pos);
//ticket_tips.gameObject.SetActive(!ticket_tips.gameObject.activeSelf);
//门票不足
FDM.SetMaxMagnification();
SetShowMagnification();
return;
}
if (loading.activeSelf)
{
ToastPanel.Show(LocalizationMgr.GetText("UI_ToastPanel_114"));
return;
}
disRequestSvrTime?.Dispose();
disRequestSvrTime = GContext.OnEvent<RequestSvrTimeEvent>().Subscribe(RequestSvrTimeEvent);
ShowPanel(true);
matchIng = StartCoroutine(StartMaching());
}
void SetLoading(bool value)
{
//loading.SetActive(value);
loading.SetActive(value);
p_text.SetActive(!value);
}
void RequestSvrTimeEvent(RequestSvrTimeEvent requestSvrTimeEvent)
{
if (!requestSvrTimeEvent.Status)
{
OnClickStop();
}
}
void OnClickIcon()
{
var pos = icon_ticket.transform.position;
pos.y += 40;
ticket_tips.SetPos(pos);
ticket_tips.gameObject.SetActive(!ticket_tips.gameObject.activeSelf);
}
void OnClickStop()
{
FDM.StopRT();
CancelMatchmaking();
disRequestSvrTime?.Dispose();
disRequestSvrTime = null;
ticketId = false;
if (matchIng != null)
{
StopCoroutine(matchIng);
matchIng = null;
}
randomMapPanel.Stop();
ShowPanel(false);
}
void ShowPanel(bool isMatch)
{
if (isMatch)
{
StopTimer();
}
else
{
SetTimer();
}
btn_close.enabled = !isMatch;
btn_close_image.SetActive(!isMatch);
MiddlePanel.SetActive(!isMatch);
matchingPanel.SetActive(isMatch);
StopLoopAudio();
}
void PlayLoopAudio()
{
StopLoopAudio();
audio_matchingloop = GContext.container.Resolve<ISoundService>().GetNewUISound(audio_ui_fishingduel_matchingloop);
audio_matchingloop.audioSource.Play();
audio_matchingloop.audioSource.loop = true;
}
void StopLoopAudio()
{
if (audio_matchingloop)
{
audio_matchingloop.audioSource.Stop();
audio_matchingloop.ReturnPool();
audio_matchingloop = null;
}
}
IEnumerator StartMaching()
{
but_stop.gameObject.SetActive(false);
//anim.Play("eventfishingduelpanel_maprandom");
Dictionary<int, Robot> robots = tables.TbRobot.DataMap;
List<int> RobotAccountList = FDM.eventSolomain.RobotAccountList;
int robotId = RobotAccountList[UnityEngine.Random.Range(0, RobotAccountList.Count)];
EventSoloRobot eventSoloRobot = tables.TbEventSoloRobot.GetOrDefault(robotId);
List<int> robotList = eventSoloRobot.RobotList;
robotId = robotList[UnityEngine.Random.Range(0, robotList.Count)];
Robot robot = robots[robotId];
SetRobot(robot, eventSoloRobot.Trophy);
//等待匹配
randomMapPanel.StartMap();
PlayLoopAudio();
yield return new WaitForSeconds(1);
currentTicketId = null;
ticketId = false;
yield return FDM.StartMaching().AsIEnumerator();
int MaxMatchTime = FDM.eventSoloConfig.MaxMatchTime;
float matchPlayerProb = UnityEngine.Random.value;
if (matchPlayerProb >= MatchPlayerProb || MaxMatchTime < 2 || FDM.rts == null)
{
but_stop.gameObject.SetActive(true);
ticketId = true;
yield return Awaiters.Seconds(UnityEngine.Random.Range(0, MaxMatchTime));
if (ticketId)
{
FDM.MachingEnd(null);
}
ticketId = false;
}
else
{
CreateMatchmakingTicket();
}
//anim.Play("eventfishingduelpanel_loop");
float time = 0.1f;
while (FDM.MachingState < 2)
{
robotId = RobotAccountList[UnityEngine.Random.Range(0, RobotAccountList.Count)];
eventSoloRobot = tables.TbEventSoloRobot.GetOrDefault(robotId);
robotList = eventSoloRobot.RobotList;
robotId = robotList[UnityEngine.Random.Range(0, robotList.Count)];
robot = robots[robotId];
SetRobot(robot, eventSoloRobot.Trophy);
yield return new WaitForSeconds(time);
}
but_stop.gameObject.SetActive(false);
disRequestSvrTime?.Dispose();
disRequestSvrTime = null;
FDM.OnJoin();
var matchDelayTime = FDM.eventSoloConfig.MatchDelayTime;
float machTimeM = UnityEngine.Random.Range(matchDelayTime[0], matchDelayTime[1]);
//最后两秒等的越来越长
while (machTimeM > 0f)
{
robotId = RobotAccountList[UnityEngine.Random.Range(0, RobotAccountList.Count)];
eventSoloRobot = tables.TbEventSoloRobot.GetOrDefault(robotId);
robotList = eventSoloRobot.RobotList;
robotId = robotList[UnityEngine.Random.Range(0, robotList.Count)];
robot = robots[robotId];
SetRobot(robot, eventSoloRobot.Trophy);
machTimeM -= time;
yield return new WaitForSeconds(time);
}
randomMapPanel.SetClose();
while (!randomMapPanel.IsStop)
{
robotId = RobotAccountList[UnityEngine.Random.Range(0, RobotAccountList.Count)];
eventSoloRobot = tables.TbEventSoloRobot.GetOrDefault(robotId);
robotList = eventSoloRobot.RobotList;
robotId = robotList[UnityEngine.Random.Range(0, robotList.Count)];
robot = robots[robotId];
SetRobot(robot, eventSoloRobot.Trophy);
yield return new WaitForSeconds(time);
}
fx_ui_matchingPanel_match_glow_01.SetActive(true);
uiService.SetHeadImage(enemy.icon_head, FDM.EnemyModel.PlayerAvatar);
enemy.text_name.text = FDM.EnemyModel.PlayerName;
var eventSolomain = FDM.GetEventSolomain(FDM.EnemyModel.RankScore);
uiService.SetImageSprite(enemy.icon_rank, eventSolomain.RankIcon);
enemy.text_score.text = ConvertTools.GetNumberString2(FDM.EnemyModel.RankScore);
StopLoopAudio();
yield return new WaitForSeconds(2);
anim.Play("eventfishingduelpanel_matchingpanel_end");
yield return new WaitForSeconds(0.5f);
//PlayLoopAudio();
//yield return new WaitForSeconds(2);
//StopLoopAudio();
ShowFishConfrimPanel();
}
void SetRobot(Robot robot, int trophy)
{
int robotTier = FDM.eventSolomain.MatchTierList[UnityEngine.Random.Range(0, FDM.eventSolomain.MatchTierList.Count)];
var eventSolomain = tables.TbEventSolomain.DataMap[robotTier];
uiService.SetHeadImage(enemy.icon_head, robot.Avatar);
enemy.text_name.text = LocalizationMgr.GetText(robot.Name_l10n_key);
uiService.SetImageSprite(enemy.icon_rank, eventSolomain.RankIcon);
enemy.text_score.text = ConvertTools.GetNumberString2(trophy);
}
public void OnClickClose()
{
GContext.container.Unregister<FishingDuelManager>();
GContext.Publish(new RestartShowHomeUIEvent());
UIManager.Instance.DestroyUI(UITypes.EventFishingDuelPanel);
disRequestSvrTime?.Dispose();
disRequestSvrTime = null;
}
void SetTimer()
{
StopTimer();
DateTime endDateTime = fishingEventData.GetEventEndTime(fishingEventData.duelData.eventID)
.AddSeconds(-tables.TbEventSoloConfig.SettlementTime);
TimeSpan now = endDateTime - ZZTimeHelper.UtcNow().UtcNowOffset();
text_time.text = LocalizationMgr.GetFormatTextValue("UI_COMMON_reset",
ConvertTools.ConvertTime2(now.Days, now.Hours, now.Minutes, now.Seconds));
double seconds = now.TotalSeconds;
if (seconds < 1)
{
Refresh();
}
else
{
timer = this.AttachTimer((float)seconds, Refresh,
(elapsed) =>
{
now = endDateTime - ZZTimeHelper.UtcNow().UtcNowOffset();
text_time.text = LocalizationMgr.GetFormatTextValue("UI_COMMON_reset",
ConvertTools.ConvertTime2(now.Days, now.Hours, now.Minutes, now.Seconds));
}, useRealTime: true);
}
}
void StopTimer()
{
timer?.Cancel();
timer = null;
}
void Refresh()
{
timer?.Cancel();
timer = null;
OnClickClose();
UIManager.Instance.DestroyUI(UITypes.EventFishingDuelRankPopupPanel);
UIManager.Instance.DestroyUI(UITypes.EventFishingDuelRewardPopupPanel);
UIManager.Instance.DestroyUI(UITypes.EventFishingduelShopPopupPanel);
UIManager.Instance.DestroyUI(UITypes.EventFishingDuelInfoPopupPanel);
}
public void ShowFishConfrimPanel()
{
matchingPanel.gameObject.SetActive(false);
fishConfrimPanel.SetActive(true);
}
#region Matchmaking
public string currentTicketId;
public bool ticketId;
string GetDetails()
{
IUserService userService = GContext.container.Resolve<IUserService>();
MatchDetails matchDetails = new MatchDetails();
matchDetails.ID = userService.UserId;
matchDetails.Name = userService.DisplayName;
matchDetails.Avatar = userService.AvatarUrl;
matchDetails.RandScore = FDM.duelData.progress;
matchDetails.Mag = FDM.magnification;
return Newtonsoft.Json.JsonConvert.SerializeObject(matchDetails);
}
void CreateMatchmakingTicket()
{
if (GContext.container.Resolve<IUserService>() is not PlayFabUserService)
{
Debug.LogWarning("KV matchmaking service is not connected.");
FDM.MachingEnd(null);
return;
}
int MaxMatchTime = FDM.eventSoloConfig.MaxMatchTime;
//可匹配段位列表,杯数,选择倍率,地图列表,随机种子seed,鱼卡等级
List<int> matchTierList = FDM.eventSolomain.MatchTierList;
List<int> mapIDs = FDM.mapIDs;
List<string> matchTierListStr = new List<string>();
for (int i = 0; i < matchTierList.Count; i++)
{
matchTierListStr.Add(matchTierList[i].ToString());
}
List<string> mapIDsStr = new List<string>();
for (int i = 0; i < mapIDs.Count; i++)
{
mapIDsStr.Add(mapIDs[i].ToString());
}
IUserService userService = GContext.container.Resolve<IUserService>();
List<string> Group = FDM.GetGroups();
string details = GetDetails();
var request = new CreateMatchmakingTicketRequest
{
Creator = new MatchmakingPlayer
{
Entity = new EntityKey
{
Id = ((PlayFabUserService)userService).entityKey.Id,
Type = ((PlayFabUserService)userService).entityKey.Type
},
Attributes = new MatchmakingPlayerAttributes
{
DataObject = new
{
Tier = matchTierListStr.ToArray(),
Map = mapIDsStr.ToArray(),
Group = Group.ToArray(),
Details = details,
}
}
},
GiveUpAfterSeconds = MaxMatchTime,
QueueName = FishingDuelManager.QueueName // 需要根据实际的匹配队列名称修改
};
PlayFabMultiplayerAPI.CreateMatchmakingTicket(request,
(result) =>
{
currentTicketId = result.TicketId;
Debug.Log("匹配请求已创建,等待匹配...");
Debug.Log("匹配Ticket ID: " + result.TicketId);
//// 开始轮询匹配状态
StartCoroutine(CheckMatchmakingStatus());
//显示取消按钮
but_stop.gameObject.SetActive(true);
},
(error) =>
{
Debug.LogError("创建匹配请求失败: " + error.GenerateErrorReport());
FDM.MachingEnd(null);
});
}
IEnumerator CheckMatchmakingStatus()
{
while (!string.IsNullOrEmpty(currentTicketId))
{
yield return new WaitForSeconds(3f);
if (string.IsNullOrEmpty(currentTicketId))
yield break;
var request = new GetMatchmakingTicketRequest
{
TicketId = currentTicketId,
QueueName = FishingDuelManager.QueueName, // 需要根据实际的匹配队列名称修改
EscapeObject = false
};
PlayFabMultiplayerAPI.GetMatchmakingTicket(request,
(result) =>
{
string statusInfo = "匹配状态: " + result.Status;
if (result.MatchId != null)
{
statusInfo += ", Match ID: " + result.MatchId;
}
Debug.Log(statusInfo.ToString());
if (result.Status == "Matched")
{
but_stop.gameObject.SetActive(false);
Debug.Log("匹配成功,获取服务器信息: ");
GetMatchDetails(result.MatchId);
}
else if (result.Status == "Canceled")
{
Debug.Log("匹配已取消: Canceled " + result.CancellationReasonString);
//if (result.CancellationReasonString != "Requested")
//{
MachingEnd();
//}
}
},
(error) =>
{
Debug.LogError("检查匹配状态失败: " + error.GenerateErrorReport());
MachingEnd();
});
}
}
void GetMatchDetails(string matchId)
{
if (GContext.container.Resolve<IUserService>() is not PlayFabUserService)
{
Debug.LogWarning("KV matchmaking service is not connected.");
FDM.MachingEnd(null);
return;
}
var request = new PlayFab.MultiplayerModels.GetMatchRequest
{
MatchId = matchId,
QueueName = FishingDuelManager.QueueName, // 需要根据实际的匹配队列名称修改
EscapeObject = false,
ReturnMemberAttributes = true
};
PlayFabMultiplayerAPI.GetMatch(request,
(result) =>
{
Debug.Log("匹配成功: " + result.MatchId);
if (string.IsNullOrEmpty(currentTicketId))
{
return;
}
// 添加玩家信息
if (result.Members != null && result.Members.Count > 0)
{
//AddMatchmakingLog("玩家数量: " + result.Members.Count);
IUserService userService = GContext.container.Resolve<IUserService>();
MatchDetails matchDetails = null;
int[] mapArray = null;
try
{
for (int i = 0; i < result.Members.Count; i++)
{
MatchmakingPlayerWithTeamAssignment member = result.Members[i];
if (member.Entity.Id != ((PlayFabUserService)userService).entityKey.Id)
{
JObject dataObject = JObject.FromObject(result.Members[i].Attributes.DataObject);
string[] tierArray = dataObject["Tier"].ToObject<string[]>();
mapArray = dataObject["Map"].ToObject<int[]>();
string matchDetailsStr = dataObject["Details"].ToString();
matchDetails = Newtonsoft.Json.JsonConvert.DeserializeObject<MatchDetails>(matchDetailsStr);
break;
}
}
}
catch
{
matchDetails = null;
mapArray = null;
}
currentTicketId = null;
FDM.MachingEnd(result.MatchId, matchDetails, mapArray);
StartCoroutine(CheckReady());
}
},
(error) =>
{
Debug.LogError("获取匹配详情失败: " + error.GenerateErrorReport());
MachingEnd();
});
}
IEnumerator CheckReady()
{
yield return new WaitForSeconds(5f);
if (FDM.MachingState < 2)
{
Debug.LogError("匹配Ready超时 ");
//返回 还是给个机器人? OnClickStop();
FDM.MachingState = 0;
FDM.MachingEnd(null);
}
}
void MachingEnd()
{
if (!string.IsNullOrEmpty(currentTicketId))
{
currentTicketId = null;
FDM.MachingEnd(null);
}
}
void CancelMatchmaking()
{
if (string.IsNullOrEmpty(currentTicketId))
return;
but_stop.gameObject.SetActive(false);
var request = new CancelMatchmakingTicketRequest
{
TicketId = currentTicketId,
QueueName = FishingDuelManager.QueueName // 需要根据实际的匹配队列名称修改
};
currentTicketId = null;
PlayFabMultiplayerAPI.CancelMatchmakingTicket(request,
(result) =>
{
Debug.Log("匹配已取消: ");
},
(error) =>
{
Debug.LogError("取消匹配失败: " + error.GenerateErrorReport());
});
}
#endregion Matchmaking
}