1411 lines
53 KiB
C#
1411 lines
53 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using asap.core;
|
|
using Castle.Core.Internal;
|
|
using cfg;
|
|
using GameCore;
|
|
using UnityEngine;
|
|
using UnityEngine.Assertions;
|
|
using Random = UnityEngine.Random;
|
|
using game;
|
|
using Newtonsoft.Json;
|
|
using ScrollViewItemInfo = EventPartnerScrollViewItem.ScrollViewItemInfo;
|
|
using UniRx;
|
|
|
|
public class EventPartnerData
|
|
{
|
|
private bool _lock = false, _whole = false;
|
|
private MetaData _data;
|
|
private readonly Tables _tables = GContext.container.Resolve<Tables>();
|
|
private readonly IUserService _userService = GContext.container.Resolve<IUserService>();
|
|
private readonly IRTService _rtService = GContext.container.Resolve<IRTService>();
|
|
private readonly FriendService _friendService = GContext.container.Resolve<FriendService>();
|
|
private readonly ICustomServerMgr _customServerMgr = GContext.container.Resolve<ICustomServerMgr>();
|
|
public List<Component> Components;
|
|
public int EventId => _data.EventId;
|
|
public int RedirectId => _data.RedirectId;
|
|
public PlayerPreferenceCache Cache;
|
|
public bool IsWhole => _whole;
|
|
|
|
/// <summary>
|
|
/// In degrees.
|
|
/// </summary>
|
|
public float LastWheelRotation => _data.WheelRotation;
|
|
private CompositeDisposable _disposables = null;
|
|
public DateTime? LastDetailRequestFromEntranceButton = null;
|
|
public int DetailRequestIntervalInSeconds = 15;
|
|
public bool IsLastTimeDetailRequestFromEntranceButtonValid = false;
|
|
|
|
public int TicketCount
|
|
{
|
|
get
|
|
{
|
|
if (_data == null)
|
|
{
|
|
Debug.Log($"[EventPartner] data is null!");
|
|
return 0;
|
|
}
|
|
return _data.TicketCount;
|
|
}
|
|
}
|
|
|
|
public DateTime EndTime
|
|
{
|
|
get
|
|
{
|
|
return DateTime.Parse((_tables.TbFishingEvent[_data.EventId].TimeDefinition as LimitedTime)?.EndTime);
|
|
}
|
|
}
|
|
|
|
public TimeSpan RemainingTime => EndTime - ZZTimeHelper.UtcNow();
|
|
|
|
public bool IsWithinEventTime
|
|
{
|
|
get
|
|
{
|
|
var et = DateTime.Parse((_tables.TbFishingEvent[_data.EventId].TimeDefinition as LimitedTime).EndTime);
|
|
var st = DateTime.Parse((_tables.TbFishingEvent[_data.EventId].TimeDefinition as LimitedTime).StartTime);
|
|
return ZZTimeHelper.UtcNow() >= st && ZZTimeHelper.UtcNow() < et;
|
|
}
|
|
}
|
|
|
|
public bool IsEventActivated
|
|
{
|
|
get
|
|
{
|
|
// if (DebugFlag)
|
|
// return true;
|
|
return _data is not null
|
|
&& _tables.TbFishingEvent.DataMap.ContainsKey(_data.EventId)
|
|
&& _tables.TbFishingEvent[_data.EventId].Type == 4
|
|
&& _tables.TbFishingEvent[_data.EventId].SubType == 3
|
|
&& (_tables.TbEventPartnerMain.DataMap.ContainsKey(_data.RedirectId) ||
|
|
_tables.TbEventPartnerMain2.DataMap.ContainsKey(_data.RedirectId))
|
|
&& IsWithinEventTime
|
|
&& DateTime.Parse((_tables.TbFishingEvent[_data.EventId].TimeDefinition as LimitedTime)?.StartTime) < ZZTimeHelper.UtcNow();
|
|
}
|
|
}
|
|
|
|
public bool IsBuildingCompleted => Components.All(component => component.IsFinished);
|
|
|
|
public bool IsBuildingRewardCollected
|
|
{
|
|
get => _data.IsBuildingRewardCollected;
|
|
set => _data.IsBuildingRewardCollected = value;
|
|
}
|
|
|
|
public bool DoNeedRedPoint
|
|
{
|
|
get
|
|
{
|
|
if (!_whole)
|
|
return false;
|
|
if (_data.IsFirstOpen)
|
|
{
|
|
_data.IsFirstOpen = false;
|
|
return true;
|
|
}
|
|
|
|
if (Components.Any(component => component.LastProgressReceived < component.GetProgressIdx(component.Score)))
|
|
return true;
|
|
// Debug.Log(_data.EventId);
|
|
if (IsBuildingCompleted)
|
|
return !IsBuildingRewardCollected;
|
|
if (TicketCount >= GContext.container.Resolve<FishingEventData>().GetRedDot(_data.EventId) && Components.Any(c => c.IsMatched && !c.IsFinished))
|
|
return true;
|
|
var chainPackData = GContext.container.Resolve<FishingEventData>().ChainPackWithProgressMigrationData;
|
|
if (chainPackData != null && chainPackData.DoNeedPackRedPoint)
|
|
return true;
|
|
return !IsFullyMatched && !RequestPartners.IsNullOrEmpty();
|
|
}
|
|
}
|
|
|
|
public string Icon => _tables.TbEventPartnerMain[_data.RedirectId].Icon;
|
|
public string MainPanelUrl => _tables.TbEventPartnerMain[_data.RedirectId].UIPanel;
|
|
public string InfoPanelUrl => _tables.TbEventPartnerMain[_data.RedirectId].InfoPanel;
|
|
public string AddressableLabel => _tables.TbEventPartnerMain[_data.RedirectId].Addressable;
|
|
public string AtlasUrl => _tables.TbEventPartnerMain[_data.RedirectId].Atlas;
|
|
public string BgmUrl => _tables.TbEventPartnerMain[_data.RedirectId].Bgm;
|
|
public string MatchBgmUrl => "audio_ui_partner_space_radar";
|
|
public int ActiveFriendCountThreshold => _tables.TbEventPartnerConfig.FriendRecommendParam1[0];
|
|
|
|
public int RecommendCount => _tables.TbEventPartnerConfig.FriendRecommendParam2[_friendService.FriendList.Count < ActiveFriendCountThreshold ? 0 : 1];
|
|
|
|
//<summary>
|
|
//Invited Partners
|
|
//</summary>
|
|
public List<string> InvitePartners { get; private set; }
|
|
|
|
//<summary>
|
|
//Received Invitations
|
|
//</summary>
|
|
public List<string> RequestPartners { get; private set; }
|
|
|
|
//<summary>
|
|
//Refused Invitations
|
|
//</summary>
|
|
public List<string> RefusePartners { get; private set; }
|
|
public bool IsFullyMatched => Components.All(c => c.IsMatched);
|
|
public int InvitationCount => _data.InvitationCount;
|
|
public bool DoRecommendBot => !IsFullyMatched && _data.InvitationCount >= _tables.TbEventPartnerConfig.RobotRecommendTriggerCount;
|
|
|
|
|
|
|
|
public async void LoadData(FishingEvent e)
|
|
{
|
|
try
|
|
{
|
|
await LoadDataAsync(e);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Debug.LogError(ex.Message);
|
|
}
|
|
}
|
|
|
|
public async System.Threading.Tasks.Task LoadDataAsync(FishingEvent e)
|
|
{
|
|
if (_lock)
|
|
{
|
|
Debug.Log($"[EventPartner] Data locked, abandon.");
|
|
return;
|
|
}
|
|
try
|
|
{
|
|
_lock = true;
|
|
_playerPreferenceKey = "EventPartnerRecommendCache" + _userService.UserId;
|
|
//Load Player Preferences
|
|
var cacheString = PlayerPrefs.GetString(_playerPreferenceKey, "");
|
|
if (cacheString == "")
|
|
{
|
|
Cache = new PlayerPreferenceCache();
|
|
Cache.Recommend = null;
|
|
Cache.DisplayScore = new Dictionary<int, (int, int)>();
|
|
Cache.ListInvitedBy = new List<ScrollViewItemInfo>();
|
|
Cache.ActionQ = new Dictionary<int, Queue<EventBuildBotAddScoreAction>>();
|
|
}
|
|
else
|
|
{
|
|
Debug.Log($"<color=#ffc700>[EventPartner]Cache: {cacheString}</color>");
|
|
try
|
|
{
|
|
Cache = JsonConvert.DeserializeObject<PlayerPreferenceCache>(cacheString);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
throw ex;
|
|
}
|
|
Debug.Log($"Cache Done");
|
|
}
|
|
var pfString = PlayFabMgr.Instance.GetLocalData(EventPartnerPlayfabData.Key);
|
|
EventPartnerPlayfabData pfData = EventPartnerPlayfabData.FromString(pfString);
|
|
Debug.Log($"<color=#2d7cee>[EventPartner] Try get response in load data:</color>");
|
|
var detailRequest = new EventBuildDetailRequest() { eventId = e.ID };
|
|
var response = await GContext.container.Resolve<ICustomServerMgr>()
|
|
.EventPartnerRequest<EventBuildDetailResp>(DetailUrl, detailRequest);
|
|
if (response == null)
|
|
{
|
|
response = new EventBuildDetailResp();
|
|
response.State = EEventBuildState.Failed;
|
|
response.Message = "Response is null";
|
|
Debug.Log($"<color=#2d7cee>[EventPartner] Response is Null.</color>");
|
|
}
|
|
else
|
|
{
|
|
Debug.Log($"<color=#2d7cee>[EventPartner] Response: {response}</color>");
|
|
Debug.Log($"<color=#2d7cee>[EventPartner] ResponseState: {response.State}</color>");
|
|
Debug.Log($"<color=#2d7cee>[EventPartner] ResponseMessage: {response.Message}</color>");
|
|
}
|
|
switch (response.State)
|
|
{
|
|
case EEventBuildState.Failed:
|
|
Debug.Log($"<color=red>[EventPartner] Load data error from server: {response.Message} </color>");
|
|
ResolveEventOnly(e);
|
|
break;
|
|
case EEventBuildState.NoActiveEvent:
|
|
Debug.Log($"<color=red>[EventPartner] Event partner not active in server: {response.Message}, but this is not supposed to happen any more.</color>");
|
|
ResolveEventOnly(e);
|
|
break;
|
|
case EEventBuildState.Success:
|
|
ResolveData(e, response, Cache, pfData);
|
|
SubscribeEvent();
|
|
break;
|
|
default:
|
|
Debug.Log($"<color=red>[EventPartner] Unexpected status: {response.State}./nMessage: {response.Message} </color>");
|
|
ResolveEventOnly(e);
|
|
break;
|
|
}
|
|
UITypes.EventPartnerPanel.SetType(MainPanelUrl);
|
|
UITypes.EventPartnerInfoPopupPanel.SetType(InfoPanelUrl);
|
|
|
|
var chainPackData = GContext.container.Resolve<FishingEventData>().ChainPackWithProgressMigrationData;
|
|
var packId = GContext.container.Resolve<Tables>().TbEventPartnerMain.GetOrDefault(e.RedirectID).PackId;
|
|
if (chainPackData.EventId != e.ID)
|
|
chainPackData.UpdateData(e.ID, packId);
|
|
|
|
Debug.Log($"<color=#2d7cee>[EventPartner]Load Data Event Thrown</color>");
|
|
GContext.Publish(new EventPartnerDataLoaded());
|
|
Unlock();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Unlock();
|
|
Debug.Log($"<color=red>[EventPartner]Load Data Error</color>");
|
|
throw ex;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Resolve data from server and local Player Preference.
|
|
/// </summary>
|
|
/// <param name="e">fishing event</param>
|
|
/// <param name="r">server response for detail</param>
|
|
/// <param name="p">Player Preference</param>
|
|
private void ResolveData(FishingEvent e, EventBuildDetailResp r, PlayerPreferenceCache p, EventPartnerPlayfabData d)
|
|
{
|
|
Debug.Log($"<color=#2d7cee>[EventPartner]Resolve data: </color>");
|
|
_data = new MetaData();
|
|
_data.EventId = e.ID;
|
|
_data.RedirectId = e.RedirectID;
|
|
_data.IsFirstOpen = p.IsFirstTimeOpen;
|
|
_data.IsBuildingRewardCollected = d.IsBuildingRewardCollected;
|
|
_data.TicketCount = d.TicketCount;
|
|
_data.InvitationCount = d.InvitationCount;
|
|
_data.Components = new ComponentData[4];
|
|
Components = new List<Component>();
|
|
r.Scores ??= new Dictionary<int, Dictionary<string, int>>();
|
|
InvitePartners = r.Info.InvitePartners;
|
|
RequestPartners = r.Info.RequestPartners;
|
|
RefusePartners = r.Info.RefusePartners;
|
|
if (e.ID != d.EventId)
|
|
{
|
|
_data.TicketCount = GContext.container.Resolve<FishingEventData>().GetInitWelcomeGift(e.ID);
|
|
ToPlayfabData().Save();
|
|
Debug.Log($"<color=#2d7cee>[EventPartner]New Player. Reward give.</color>");
|
|
}
|
|
InvitePartners ??= new List<string>();
|
|
RequestPartners ??= new List<string>();
|
|
RefusePartners ??= new List<string>();
|
|
// Debug.Log($"<color=#ffc700>[EventPartner] DataHash from Initiation: {GetHashCode()}</color>");
|
|
for (int idx = 0; idx < 4; idx++)
|
|
{
|
|
_data.Components[idx] = new ComponentData
|
|
{
|
|
ComponentIndex = idx,
|
|
ComponentId = _tables.TbEventPartnerMain[RedirectId].ComponentList[idx]
|
|
};
|
|
var componentData = _data.Components[idx];
|
|
if (r.Info.Partners is null || !r.Info.Partners.TryGetValue(idx, out var partner))
|
|
{
|
|
componentData.PartnerId = "";
|
|
continue;
|
|
}
|
|
|
|
// Get display info
|
|
if (partner.EndsWith(EventPartnerBot.RobotIdentifier))
|
|
{
|
|
componentData.PartnerId = partner;
|
|
EventPartnerBot.GetBotDisplayInfo(partner, out componentData.AvatarUrl, out componentData.DisplayName);
|
|
|
|
var botRes = d.Bots.TryGetValue(idx, out var bot);
|
|
if (botRes)
|
|
{
|
|
componentData.BotTargetScore = bot.TargetScore;
|
|
componentData.WakeStartTime = bot.WakeStartTime;
|
|
componentData.WakingSeconds = bot.WakingSeconds;
|
|
componentData.BotGrade = bot.Grade;
|
|
}
|
|
else
|
|
{
|
|
Debug.Log("<color=#2d7cee>[EventPartner]Bot not found. Schedule a new bot.</color>");
|
|
componentData.BotTargetScore = 0;
|
|
componentData.WakeStartTime = ZZTimeHelper.UtcNow();
|
|
componentData.WakingSeconds = Random.Range(
|
|
GContext.container.Resolve<Tables>().TbEventPartnerConfig.RobotDailyActiveTimeWindow[0],
|
|
GContext.container.Resolve<Tables>().TbEventPartnerConfig.RobotDailyActiveTimeWindow[1]);
|
|
componentData.BotGrade = FtMathUtils.GetRandomIdxFromWeightList(
|
|
GContext.container.Resolve<Tables>().TbEventPartnerRobot.DataList.Select(r => r.Weight));
|
|
}
|
|
// componentData.BotTargetScore = d.Bots[idx].TargetScore;
|
|
// componentData.WakeStartTime = d.Bots[idx].WakeStartTime;
|
|
// componentData.WakingSeconds = d.Bots[idx].WakingSeconds;
|
|
// componentData.BotGrade = d.Bots[idx].Grade;
|
|
}
|
|
else
|
|
{
|
|
componentData.PartnerId = partner;
|
|
var partnerInfo = _userService.GetPlayInfo(componentData.PartnerId);
|
|
componentData.AvatarUrl = partnerInfo.avatarUrl;
|
|
componentData.DisplayName = partnerInfo.name;
|
|
}
|
|
|
|
// Get actual score
|
|
if (partner.EndsWith(EventPartnerBot.RobotIdentifier))
|
|
{
|
|
var botRes = d.Bots.TryGetValue(idx, out var bot);
|
|
if (botRes)
|
|
{
|
|
componentData.ScoreSelfActual = bot.ScorePlayer;
|
|
componentData.ScorePartnerActual = bot.ScoreBot;
|
|
}
|
|
else
|
|
{
|
|
componentData.ScoreSelfActual = 0;
|
|
componentData.ScorePartnerActual = 0;
|
|
}
|
|
}
|
|
else if (r.Scores.TryGetValue(idx, out var scoreData))
|
|
{
|
|
if (!scoreData.TryGetValue(_userService.UserId, out componentData.ScoreSelfActual))
|
|
{
|
|
Debug.Log($"<color=#2d7cee>[EventPartner]Fail to get self score. Id:{componentData}.</color>");
|
|
componentData.ScoreSelfActual = 0;
|
|
}
|
|
|
|
if (!scoreData.TryGetValue(componentData.PartnerId, out componentData.ScorePartnerActual))
|
|
{
|
|
Debug.Log($"<color=#2d7cee>[EventPartner]Fail to get partner score. Id:{componentData}.</color>");
|
|
componentData.ScorePartnerActual = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
componentData.ScoreSelfActual = 0;
|
|
componentData.ScorePartnerActual = 0;
|
|
}
|
|
|
|
// Get display score.
|
|
if (p.DisplayScore.TryGetValue(idx, out var displayScore))
|
|
{
|
|
componentData.ScoreSelfDisplay =
|
|
displayScore.Item1 <= componentData.ScoreSelfActual ? displayScore.Item1 : componentData.ScoreSelfActual;
|
|
componentData.ScorePartnerDisplay = displayScore.Item2 <= componentData.ScorePartnerActual
|
|
? displayScore.Item2
|
|
: componentData.ScorePartnerActual;
|
|
}
|
|
else // Cache does not have this component index, create a new one from server data.
|
|
{
|
|
componentData.ScoreSelfDisplay = componentData.ScoreSelfActual;
|
|
componentData.ScorePartnerDisplay = componentData.ScorePartnerActual;
|
|
p.DisplayScore.Add(idx, (componentData.ScoreSelfDisplay, componentData.ScorePartnerDisplay));
|
|
}
|
|
|
|
if (d.LastProgressReceived.IsNullOrEmpty() || !d.LastProgressReceived.TryGetValue(idx, out var lastProgressReceived))
|
|
componentData.LastProgressReceived = 0;
|
|
else
|
|
componentData.LastProgressReceived = lastProgressReceived;
|
|
}
|
|
|
|
foreach (var c in _data.Components)
|
|
Components.Add(new Component(c));
|
|
Debug.Log($"<color=#2d7cee>[EventPartner]Resolve Data Event Thrown</color>");
|
|
GContext.Publish(new EventPartnerDataLoaded());
|
|
_whole = true;
|
|
}
|
|
|
|
private void ResolveEventOnly(FishingEvent e)
|
|
{
|
|
Debug.Log($"<color=#2d7cee>[EventPartner]Resolve event only: </color>");
|
|
_data = new MetaData();
|
|
_data.EventId = e.ID;
|
|
_data.RedirectId = e.RedirectID;
|
|
_data.Components = new ComponentData[4];
|
|
Components = new List<Component>();
|
|
InvitePartners ??= new List<string>();
|
|
RequestPartners ??= new List<string>();
|
|
RefusePartners ??= new List<string>();
|
|
for (int idx = 0; idx < 4; idx++)
|
|
{
|
|
_data.Components[idx] = new ComponentData
|
|
{
|
|
ComponentIndex = idx,
|
|
ComponentId = _tables.TbEventPartnerMain[RedirectId].ComponentList[idx]
|
|
};
|
|
}
|
|
|
|
foreach (var c in _data.Components)
|
|
Components.Add(new Component(c));
|
|
Debug.Log($"<color=#2d7cee>[EventPartner]Resolve Only Event Data Event Thrown</color>");
|
|
GContext.Publish(new EventPartnerDataLoaded());
|
|
}
|
|
|
|
public void ResolveAllDataButEvent(EventBuildDetailResp r, PlayerPreferenceCache p, EventPartnerPlayfabData d)
|
|
{
|
|
_data.IsFirstOpen = p.IsFirstTimeOpen;
|
|
_data.IsBuildingRewardCollected = d.IsBuildingRewardCollected;
|
|
_data.TicketCount = d.TicketCount;
|
|
_data.InvitationCount = d.InvitationCount;
|
|
r.Scores ??= new Dictionary<int, Dictionary<string, int>>();
|
|
InvitePartners = r.Info.InvitePartners;
|
|
RequestPartners = r.Info.RequestPartners;
|
|
RefusePartners = r.Info.RefusePartners;
|
|
InvitePartners ??= new List<string>();
|
|
RequestPartners ??= new List<string>();
|
|
RefusePartners ??= new List<string>();
|
|
if (_data.EventId != d.EventId)
|
|
{
|
|
_data.TicketCount = GContext.container.Resolve<FishingEventData>().GetInitWelcomeGift(_data.EventId);
|
|
ToPlayfabData().Save();
|
|
Debug.Log($"<color=#2d7cee>[EventPartner]New Player. Reward give.</color>");
|
|
}
|
|
for (int idx = 0; idx < 4; idx++)
|
|
{
|
|
var componentData = _data.Components[idx];
|
|
if (r.Info.Partners is null || !r.Info.Partners.TryGetValue(idx, out var partner))
|
|
{
|
|
componentData.PartnerId = "";
|
|
continue;
|
|
}
|
|
|
|
// Get display info
|
|
if (partner.EndsWith(EventPartnerBot.RobotIdentifier))
|
|
{
|
|
componentData.PartnerId = partner;
|
|
EventPartnerBot.GetBotDisplayInfo(partner, out componentData.AvatarUrl, out componentData.DisplayName);
|
|
var botRes = d.Bots.TryGetValue(idx, out var bot);
|
|
if (botRes)
|
|
{
|
|
componentData.BotTargetScore = bot.TargetScore;
|
|
componentData.WakeStartTime = bot.WakeStartTime;
|
|
componentData.WakingSeconds = bot.WakingSeconds;
|
|
componentData.BotGrade = bot.Grade;
|
|
}
|
|
else
|
|
{
|
|
Debug.Log("<color=#2d7cee>[EventPartner]Bot not found. Schedule a new bot.</color>");
|
|
componentData.BotTargetScore = 0;
|
|
componentData.WakeStartTime = ZZTimeHelper.UtcNow();
|
|
componentData.WakingSeconds = Random.Range(
|
|
GContext.container.Resolve<Tables>().TbEventPartnerConfig.RobotDailyActiveTimeWindow[0],
|
|
GContext.container.Resolve<Tables>().TbEventPartnerConfig.RobotDailyActiveTimeWindow[1]);
|
|
componentData.BotGrade = FtMathUtils.GetRandomIdxFromWeightList(
|
|
GContext.container.Resolve<Tables>().TbEventPartnerRobot.DataList.Select(r => r.Weight));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
componentData.PartnerId = partner;
|
|
var partnerInfo = _userService.GetPlayInfo(componentData.PartnerId);
|
|
componentData.AvatarUrl = partnerInfo.avatarUrl;
|
|
componentData.DisplayName = partnerInfo.name;
|
|
}
|
|
|
|
// Get actual score
|
|
if (partner.EndsWith(EventPartnerBot.RobotIdentifier))
|
|
{
|
|
EventPartnerBot.GetBotDisplayInfo(partner, out componentData.AvatarUrl, out componentData.DisplayName);
|
|
var botRes = d.Bots.TryGetValue(idx, out var bot);
|
|
if (botRes)
|
|
{
|
|
componentData.ScoreSelfActual = bot.ScorePlayer;
|
|
componentData.ScorePartnerActual = bot.ScoreBot;
|
|
}
|
|
else
|
|
{
|
|
componentData.ScoreSelfActual = 0;
|
|
componentData.ScorePartnerActual = 0;
|
|
}
|
|
}
|
|
else if (r.Scores.TryGetValue(idx, out var scoreData))
|
|
{
|
|
if (!scoreData.TryGetValue(_userService.UserId, out componentData.ScoreSelfActual))
|
|
{
|
|
Debug.Log($"<color=#2d7cee>[EventPartner]Fail to get self score. Id:{componentData}.</color>");
|
|
componentData.ScoreSelfActual = 0;
|
|
}
|
|
|
|
if (!scoreData.TryGetValue(componentData.PartnerId,
|
|
out componentData.ScorePartnerActual))
|
|
{
|
|
Debug.Log($"<color=#2d7cee>[EventPartner]Fail to get partner score. Id:{componentData}.</color>");
|
|
componentData.ScorePartnerActual = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
componentData.ScoreSelfActual = 0;
|
|
componentData.ScorePartnerActual = 0;
|
|
}
|
|
|
|
// Get display score.
|
|
if (p.DisplayScore.TryGetValue(idx, out var displayScore))
|
|
{
|
|
componentData.ScoreSelfDisplay =
|
|
displayScore.Item1 <= componentData.ScoreSelfActual ? displayScore.Item1 : componentData.ScoreSelfActual;
|
|
componentData.ScorePartnerDisplay = displayScore.Item2 <= componentData.ScorePartnerActual
|
|
? displayScore.Item2
|
|
: componentData.ScorePartnerActual;
|
|
}
|
|
else // Cache does not have this component index, create a new one from server data.
|
|
{
|
|
componentData.ScoreSelfDisplay = componentData.ScoreSelfActual;
|
|
componentData.ScorePartnerDisplay = componentData.ScorePartnerActual;
|
|
p.DisplayScore.Add(idx, (componentData.ScoreSelfDisplay, componentData.ScorePartnerDisplay));
|
|
}
|
|
|
|
if (d.LastProgressReceived.IsNullOrEmpty() || !d.LastProgressReceived.TryGetValue(idx, out var lastProgressReceived))
|
|
componentData.LastProgressReceived = 0;
|
|
else
|
|
componentData.LastProgressReceived = lastProgressReceived;
|
|
}
|
|
_whole = true;
|
|
// If there is a error and scheduled a new bot.
|
|
ToPlayfabData().Save();
|
|
}
|
|
|
|
public void ActivateRobotRecommend()
|
|
{
|
|
_data.InvitationCount = 200;
|
|
}
|
|
|
|
#if UNITY_EDITOR
|
|
public void ResetData()
|
|
{
|
|
// _data.EventId = 0;
|
|
int componentCount = 0;
|
|
componentCount = GetComponentCount();
|
|
_data.Components = new ComponentData[componentCount];
|
|
for (int i = 0; i < componentCount; i++)
|
|
{
|
|
_data.Components[i] = new ComponentData
|
|
{
|
|
ComponentIndex = i,
|
|
ComponentId = _tables.TbEventPartnerMain[RedirectId].ComponentList[i]
|
|
};
|
|
Components.Add(new Component(_data.Components[i]));
|
|
}
|
|
|
|
_data.TicketCount = int.MaxValue / 4096;
|
|
SavePlayerPreferenceData();
|
|
}
|
|
#endif
|
|
|
|
public void SavePlayerPreferenceData()
|
|
{
|
|
for (int i = 0; i < 4; i++)
|
|
Cache.DisplayScore[i] = (Components[i].ScoreSelfDisplay, Components[i].ScorePartnerDisplay);
|
|
string cache = JsonConvert.SerializeObject(Cache);
|
|
// Debug.Log($"<color=#c191ff>[EventPartner]Cache saved: {cache}</color>");
|
|
PlayerPrefs.SetString(_playerPreferenceKey, cache);
|
|
}
|
|
|
|
private int GetComponentIndexByPartnerId(string partnerId)
|
|
{
|
|
foreach (var c in Components.Where(c => c.PartnerId == partnerId))
|
|
return c.ComponentIndex;
|
|
return -10086;
|
|
}
|
|
|
|
public int GetComponentCount()
|
|
{
|
|
return _tables.TbEventPartnerMain.DataMap.ContainsKey(_data.RedirectId)
|
|
? _tables.TbEventPartnerMain[_data.RedirectId].ComponentList.Count
|
|
: 0;
|
|
}
|
|
|
|
public bool ContainsPartnerId(string id)
|
|
{
|
|
return Components.Any(c => c.IsMatched && c.PartnerId == id);
|
|
}
|
|
|
|
// public void AddPartnerTicketForce(int n)
|
|
// {
|
|
// _data.TicketCount += n;
|
|
// }
|
|
|
|
public bool AddTicket(int n)
|
|
{
|
|
_data.TicketCount += n;
|
|
if (_data.TicketCount < 0)
|
|
{
|
|
_data.TicketCount -= n;
|
|
return false;
|
|
}
|
|
GContext.container.Resolve<FishingEventData>().SaveTransitionData(_data.EventId, _data.TicketCount);
|
|
GContext.Publish(new EventPartnerTicketChangedEvent());
|
|
ToPlayfabData().Save();
|
|
return true;
|
|
}
|
|
|
|
public bool HasEnoughTicket(int cost)
|
|
{
|
|
return _data.TicketCount >= cost;
|
|
}
|
|
|
|
public void RecordWheelRotation(float rotation)
|
|
{
|
|
_data.WheelRotation = rotation;
|
|
}
|
|
public void AddInvitationCount()
|
|
{
|
|
_data.InvitationCount++;
|
|
}
|
|
|
|
public void Unlock()
|
|
{
|
|
_lock = false;
|
|
Debug.Log("[EventPartner] Unlock.");
|
|
}
|
|
|
|
|
|
public class Component
|
|
{
|
|
private static readonly IUserService UserService = GContext.container.Resolve<IUserService>();
|
|
private readonly ComponentData _data;
|
|
// private PartnerData _partnerData;
|
|
private readonly Tables _tables = GContext.container.Resolve<Tables>();
|
|
private readonly int _redirectId;
|
|
public bool IsMatched => _data.PartnerId != "";
|
|
public int Score => _data.ScoreSelfActual + _data.ScorePartnerActual;
|
|
public int ScoreSelf => _data.ScoreSelfActual;
|
|
public int ScorePartner => _data.ScorePartnerActual;
|
|
public bool IsPartnerRobot => _data.PartnerId.EndsWith(EventPartnerBot.RobotIdentifier);
|
|
public int BotIndex => EventPartnerBot.Id2Idx(_data.PartnerId);
|
|
public int BotTargetScore => _data.BotTargetScore;
|
|
/// Strength of bot adding score.
|
|
public int BotGrade
|
|
{
|
|
get => _data.BotGrade;
|
|
set => _data.BotGrade = value;
|
|
}
|
|
public Queue<EventBuildBotAddScoreAction> BotActionQueue
|
|
{
|
|
get
|
|
{
|
|
EventPartnerAct.Ctx.Data.Cache.ActionQ ??= new Dictionary<int, Queue<EventBuildBotAddScoreAction>>();
|
|
if (EventPartnerAct.Ctx.Data.Cache.ActionQ.TryGetValue(ComponentIndex, out var q))
|
|
return q;
|
|
q = new Queue<EventBuildBotAddScoreAction>();
|
|
EventPartnerAct.Ctx.Data.Cache.ActionQ.Add(ComponentIndex, q);
|
|
return q;
|
|
}
|
|
}
|
|
public string PartnerId
|
|
{
|
|
get => _data.PartnerId;
|
|
set => _data.PartnerId = value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// This component idx starts from 0 and has nothing to do with the component id in table EventPartnerComponent.
|
|
/// </summary>
|
|
public int ComponentIndex => _data.ComponentIndex;
|
|
public int ComponentId => _data.ComponentId;
|
|
public int ScoreDisplay => _data.ScoreSelfDisplay + _data.ScorePartnerDisplay;
|
|
public int ScorePartnerDisplay => _data.ScorePartnerDisplay;
|
|
public int ScoreSelfDisplay => _data.ScoreSelfDisplay;
|
|
public int DisplayStageProgress => GetProgressIdx(ScoreDisplay);
|
|
public int RedirectID => _redirectId;
|
|
|
|
public int LastProgressReceived
|
|
{
|
|
get => _data.LastProgressReceived;
|
|
set => _data.LastProgressReceived = value;
|
|
}
|
|
|
|
public bool IsFinished => _data.LastProgressReceived >= _tables.TbEventPartnerMain[_redirectId].StagePoint.Count;
|
|
|
|
public bool IsBuilt => Score >= MaxScore;
|
|
|
|
public Component(ComponentData data)
|
|
{
|
|
_data = data;
|
|
_redirectId = GContext.container.Resolve<EventPartnerData>().RedirectId;
|
|
}
|
|
|
|
public int MaxScore => _tables.TbEventPartnerMain[RedirectID].StagePoint[^1];
|
|
|
|
public string GetComponentName()
|
|
{
|
|
var componentTable = _tables.TbEventPartnerComponent;
|
|
return componentTable.DataMap.ContainsKey(_data.ComponentId) ? LocalizationMgr.GetText(componentTable[_data.ComponentId].Text_l10n_key) : "";
|
|
}
|
|
|
|
public string PartnerAvatarUrl => _data.AvatarUrl;
|
|
public string PartnerDisplayName => _data.DisplayName;
|
|
|
|
public DateTime BotWakeTime
|
|
{
|
|
get => _data.WakeStartTime;
|
|
set => _data.WakeStartTime = value;
|
|
}
|
|
|
|
public int BotWakingSeconds
|
|
{
|
|
get => _data.WakingSeconds;
|
|
set => _data.WakingSeconds = value;
|
|
}
|
|
|
|
public void SetComponent(string playfabId)
|
|
{
|
|
_data.PartnerId = playfabId;
|
|
var info = UserService.GetPlayInfo(playfabId);
|
|
_data.AvatarUrl = info.avatarUrl;
|
|
_data.DisplayName = info.name;
|
|
}
|
|
|
|
public void SetComponent(ScrollViewItemInfo info)
|
|
{
|
|
_data.PartnerId = info.PlayfabId;
|
|
_data.AvatarUrl = info.AvatarUrl;
|
|
_data.DisplayName = info.DisplayName;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get progress index according to score input. Result starts at 0, which means no upgrade accomplished, no
|
|
/// reward has been claimed yet.
|
|
/// </summary>
|
|
/// <param name="score">Score to look up.</param>
|
|
/// <returns></returns>
|
|
public int GetProgressIdx(int score)
|
|
{
|
|
var d = _tables.TbEventPartnerMain;
|
|
Assert.IsTrue(d.DataMap.ContainsKey(_redirectId),
|
|
$"RedirectId {_redirectId} not found in table.");
|
|
var scoreList = d[_redirectId].StagePoint;
|
|
int i = 0;
|
|
while (i < scoreList.Count && score >= scoreList[i])
|
|
i++;
|
|
// if (i == ScoreList.Count) return ScoreList.Count - 1;
|
|
return i;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called when a component matched to a bot got upgraded.
|
|
/// </summary>
|
|
public void ScheduleBotScoreAction()
|
|
{
|
|
var newActionQ = new Queue<EventBuildBotAddScoreAction>();
|
|
var currentProgress = GetProgressIdx(Score);
|
|
if (_data.BotGrade >= _tables.TbEventPartnerRobot.DataList.Count)
|
|
{
|
|
Debug.Log($"<color=#c191ff>[EventPartner]Grade {_data.BotGrade} out of range {_tables.TbEventPartnerRobot.DataList.Count}</color>");
|
|
return;
|
|
}
|
|
|
|
var robotData = _tables.TbEventPartnerRobot.DataList[_data.BotGrade];
|
|
var percentage = Random.Range(robotData.PointsRange[0], robotData.PointsRange[1]) / 100;
|
|
int newBotTargetScore = (int)(percentage * _tables.TbEventPartnerMain[RedirectID]
|
|
.StagePoint[currentProgress]);
|
|
if (newBotTargetScore < _data.BotTargetScore)
|
|
{
|
|
Debug.Log($"<color=#c191ff>[EventPartner]New bot target {newBotTargetScore} is smaller than old target {_data.BotTargetScore}</color>");
|
|
return;
|
|
}
|
|
|
|
var startTime = _data.WakeStartTime + TimeSpan.FromSeconds(
|
|
Random.Range(_tables.TbEventPartnerConfig.RobotDailyActiveTimeWindow[0],
|
|
_tables.TbEventPartnerConfig.RobotDailyActiveTimeWindow[1]));
|
|
while (startTime < ZZTimeHelper.UtcNow())
|
|
{
|
|
startTime += TimeSpan.FromDays(1);
|
|
}
|
|
|
|
var scheduleDuration = Random.Range(
|
|
_tables.TbEventPartnerConfig.RobotSingleAddPointsTimeWindow[0],
|
|
_tables.TbEventPartnerConfig.RobotSingleAddPointsTimeWindow[1]);
|
|
var scheduleAmount = Random.Range(
|
|
_tables.TbEventPartnerConfig.RobotSingleAddPointsOperations[0],
|
|
_tables.TbEventPartnerConfig.RobotSingleAddPointsOperations[1]);
|
|
|
|
var timeSet = new HashSet<int>();
|
|
while (timeSet.Count < scheduleAmount)
|
|
{
|
|
timeSet.Add(Random.Range(1, scheduleDuration));
|
|
}
|
|
|
|
var timeList = timeSet.OrderBy(t => t).ToList();
|
|
_data.BotTargetScore = newBotTargetScore;
|
|
var botScore = _data.ScorePartnerActual;
|
|
var gap = newBotTargetScore - botScore;
|
|
if (!FtMathUtils.RandomSplit(gap, scheduleAmount, out var scoreList))
|
|
Debug.Log($"<color=#c191ff>[EventPartner]Split {gap} into {scheduleAmount} @ {ComponentIndex}.</color>");
|
|
Debug.Log($"<color=#c191ff>[EventPartner]WakeTime:{_data.WakeStartTime}, StartTime: {startTime}, Duration: {scheduleDuration}s, Add {gap} points in {scheduleAmount} times.</color>");
|
|
Debug.Log($"<color=#c191ff>[EventPartner]Activation Delay: {startTime - _data.WakeStartTime}, BotAddScoreStrengthGrade: {_data.BotGrade}</color>");
|
|
int minWheelNumber = _tables.TbEventPartnerMain[_redirectId].SpinPoint[0];
|
|
for (int i = 1; i < _tables.TbEventPartnerMain[_redirectId].SpinPoint.Count; i++)
|
|
if (minWheelNumber > _tables.TbEventPartnerMain[_redirectId].SpinPoint[i])
|
|
minWheelNumber = _tables.TbEventPartnerMain[_redirectId].SpinPoint[i];
|
|
for (int i = 0; i < scheduleAmount; i++)
|
|
{
|
|
FtMathUtils.ScaleByBase(scoreList[i], minWheelNumber, out var score);
|
|
newActionQ.Enqueue(new EventBuildBotAddScoreAction
|
|
{
|
|
Score = score,
|
|
Time = startTime + TimeSpan.FromSeconds(timeList[i])
|
|
});
|
|
}
|
|
|
|
EventPartnerAct.Ctx.Data.Cache.ActionQ[ComponentIndex] = newActionQ;
|
|
EventPartnerAct.Ctx.Data.SavePlayerPreferenceData();
|
|
EventPartnerAct.Ctx.Data.ToPlayfabData().Save();
|
|
foreach (var a in newActionQ)
|
|
{
|
|
Debug.Log($"<color=#c191ff> [EventPartner]Add {a.Score} @ {a.Time} in slot {ComponentIndex}.</color>");
|
|
}
|
|
}
|
|
|
|
public int GetNextRewardId(int score)
|
|
{
|
|
var d = _tables.TbEventPartnerMain;
|
|
Assert.IsTrue(d.DataMap.ContainsKey(_redirectId),
|
|
$"RedirectId {_redirectId} not found in table.");
|
|
int i = GetProgressIdx(score);
|
|
if (i == d[_redirectId].StagePoint.Count)
|
|
i--;
|
|
return d[_redirectId].StageReward[i];
|
|
}
|
|
|
|
public float GetProgress(int score)
|
|
{
|
|
var d = _tables.TbEventPartnerMain;
|
|
Assert.IsTrue(d.DataMap.ContainsKey(_redirectId),
|
|
$"RedirectId {_redirectId} not found in table.");
|
|
var scoreList = d[_redirectId].StagePoint;
|
|
int idx = 0, count = scoreList.Count;
|
|
float progress = 0;
|
|
while (idx < count)
|
|
{
|
|
if (score < scoreList[idx])
|
|
{
|
|
if (idx == 0)
|
|
progress += (float)score / scoreList[0];
|
|
else
|
|
progress += (float)(score - scoreList[idx - 1]) / (scoreList[idx] - scoreList[idx - 1]);
|
|
break;
|
|
}
|
|
|
|
progress += 1f;
|
|
idx++;
|
|
}
|
|
|
|
return progress / count;
|
|
}
|
|
|
|
public float GetPartialProgress(int score)
|
|
{
|
|
var d = _tables.TbEventPartnerMain;
|
|
Assert.IsTrue(d.DataMap.ContainsKey(_redirectId), $"RedirectId {_redirectId} not found in table.");
|
|
var scoreList = d[_redirectId].StagePoint;
|
|
int idx = 0;
|
|
while (idx < scoreList.Count)
|
|
{
|
|
if (score < scoreList[idx])
|
|
{
|
|
if (idx == 0)
|
|
return (float)score / scoreList[0];
|
|
return (float)(score - scoreList[idx - 1]) / (scoreList[idx] - scoreList[idx - 1]);
|
|
}
|
|
|
|
if (score == MaxScore)
|
|
return 1;
|
|
if (score == scoreList[idx])
|
|
{
|
|
return _data.LastProgressReceived >= idx + 1 ? 0 : 1;
|
|
}
|
|
|
|
idx++;
|
|
}
|
|
|
|
Debug.LogWarning($"Score {score} did not found a match.");
|
|
return 1;
|
|
}
|
|
|
|
public void AddRobotScore()
|
|
{
|
|
if (!BotActionQueue.TryPeek(out var action) || ZZTimeHelper.UtcNow() < action.Time)
|
|
{
|
|
return;
|
|
}
|
|
Debug.Log($"<color=#ff4408>Score added by bot in slot{ComponentIndex} at {ZZTimeHelper.UtcNow()}</color>");
|
|
_data.ScorePartnerActual += action.Score;
|
|
BotActionQueue.Dequeue();
|
|
EventPartnerAct.Ctx.Data.SavePlayerPreferenceData();
|
|
EventPartnerAct.Ctx.Data.ToPlayfabData().Save();
|
|
EventPartnerAct.Ctx.EventAggregator.Publish(new EventPartnerPartnerAddScore());
|
|
}
|
|
|
|
public void SyncRobotScore()
|
|
{
|
|
EventPartnerAct.Ctx.Data.ToPlayfabData().Save();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Update partner's score.
|
|
/// </summary>
|
|
/// <param name="newScore">The target score.</param>
|
|
/// <returns>False if the new score is actually smaller than the current score. True if succeeded.</returns>
|
|
public bool UpdatePartnerScore(int newScore)
|
|
{
|
|
if (_data.ScorePartnerActual >= newScore)
|
|
return false;
|
|
_data.ScorePartnerActual = newScore;
|
|
return true;
|
|
}
|
|
|
|
public int GetComponentScoreGap(int score)
|
|
{
|
|
int stageProgress = GetProgressIdx(score);
|
|
//Score reaches top prize. Return random non-zero value.
|
|
if (stageProgress == _tables.TbEventPartnerMain[_redirectId].StageReward.Count)
|
|
return 1;
|
|
int currentStagePoint =
|
|
_tables.TbEventPartnerMain[_redirectId].StagePoint[stageProgress];
|
|
int previousStagePoint = stageProgress == 0
|
|
? 0
|
|
: _tables.TbEventPartnerMain[_redirectId].StagePoint[stageProgress - 1];
|
|
return currentStagePoint - previousStagePoint;
|
|
}
|
|
|
|
public void SyncDisplayScore()
|
|
{
|
|
_data.ScorePartnerDisplay = _data.ScorePartnerActual;
|
|
_data.ScoreSelfDisplay = _data.ScoreSelfActual;
|
|
EventPartnerAct.Ctx.Data.Cache.DisplayScore[ComponentIndex] = (_data.ScoreSelfActual, _data.ScorePartnerActual);
|
|
}
|
|
|
|
public void AddSelfScore(int n)
|
|
{
|
|
_data.ScoreSelfActual += n;
|
|
if (Score > MaxScore)
|
|
_data.ScoreSelfActual -= Score - MaxScore;
|
|
}
|
|
|
|
public async System.Threading.Tasks.Task AddSelfScoreAsync(int n)
|
|
{
|
|
var newScore = n + _data.ScoreSelfActual;
|
|
if (newScore + _data.ScorePartnerActual > MaxScore)
|
|
newScore -= newScore + _data.ScorePartnerActual - MaxScore;
|
|
var request = new EventBuildChangeScoreRequest
|
|
{
|
|
partnerId = PartnerId,
|
|
score = newScore,
|
|
slotId = ComponentIndex,
|
|
eventId = _redirectId
|
|
};
|
|
var res = await GContext.container.Resolve<ICustomServerMgr>()
|
|
.EventPartnerRequest<EventBuildOperationResp>(UpdateScoreUrl, request);
|
|
// if (res.State == EEventBuildState.Success)
|
|
_data.ScorePartnerActual = newScore;
|
|
}
|
|
|
|
public static int GetRandomIdxFromWeightList(IEnumerable<int> weightList)
|
|
{
|
|
var accWeightList = new List<int>();
|
|
int tmp = 0;
|
|
foreach (int w in weightList)
|
|
{
|
|
tmp += w;
|
|
accWeightList.Add(tmp);
|
|
}
|
|
|
|
tmp = Random.Range(0, accWeightList[^1]);
|
|
for (int i = 0; i < accWeightList.Count; i++)
|
|
{
|
|
if (tmp < accWeightList[i])
|
|
return i;
|
|
}
|
|
|
|
return accWeightList.Count - 1;
|
|
}
|
|
}
|
|
|
|
public class ComponentData
|
|
{
|
|
public int ScoreSelfActual, ScorePartnerActual, ComponentId, ScorePartnerDisplay, ScoreSelfDisplay, ComponentIndex, LastProgressReceived;
|
|
public string PartnerId, AvatarUrl, DisplayName;
|
|
|
|
#region BotData
|
|
|
|
// public int BotTargetScore, BotScoreGap;
|
|
public int BotGrade, BotIndex, BotTargetScore, WakingSeconds;
|
|
|
|
// public Queue<EventBuildBotAddScoreAction> BotActionQueue;
|
|
public DateTime WakeStartTime;
|
|
|
|
#endregion
|
|
}
|
|
|
|
public class MetaData
|
|
{
|
|
public ComponentData[] Components;
|
|
public int EventId, RedirectId, TicketCount, InvitationCount;
|
|
|
|
/// <summary>
|
|
/// In degrees.
|
|
/// </summary>
|
|
public float WheelRotation;
|
|
|
|
public bool IsBuildingRewardCollected, IsFirstOpen;
|
|
}
|
|
|
|
#region Cache
|
|
|
|
private string _playerPreferenceKey;
|
|
|
|
public class PlayerPreferenceCache
|
|
{
|
|
public DateTime? RecommendListExpireTime { get; set; }
|
|
public float WheelRotation = 0f;
|
|
public List<ScrollViewItemInfo> Recommend { get; set; }
|
|
public bool IsFirstTimeOpen = true;
|
|
|
|
/// <summary>
|
|
/// Score for display. Key: component index. value: (my display score, partner display score)
|
|
/// </summary>
|
|
public Dictionary<int, (int, int)> DisplayScore { get; set; }
|
|
/// <summary>
|
|
/// List of players that invited 'me'
|
|
/// </summary>
|
|
public List<ScrollViewItemInfo> ListInvitedBy { get; set; }
|
|
public Dictionary<int, Queue<EventBuildBotAddScoreAction>> ActionQ { get; set; }
|
|
/// <summary>
|
|
/// List of players that was invited by 'me'
|
|
/// </summary>
|
|
public List<ScrollViewItemInfo> ListInvitation { get; set; }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region HttpRequestModel
|
|
|
|
public const string RecommendUrl = "recommend",
|
|
DetailUrl = "detail",
|
|
InviteUrl = "invite",
|
|
IgnoreUrl = "refuse",
|
|
AcceptUrl = "accept",
|
|
UpdateScoreUrl = "score",
|
|
MatchRecentPlayerInfoUrl = "recent-player-info",
|
|
PlayerDisplayInfoUrl = "player-display-info",
|
|
BuildUrl = "build";
|
|
|
|
private Dictionary<string, int> _buildEventBuffer = new Dictionary<string, int>();
|
|
|
|
private async void OnPartnerBuild(EventBuildScoreEvt e)
|
|
{
|
|
await Awaiters.NextFrame;
|
|
int componentIdx = GetComponentIndexByPartnerId(e.partnerId);
|
|
Debug.Log($"<color=#c191ff>[EventPartner]Partner Build score {e.score} at slot {componentIdx}</color>");
|
|
if (componentIdx is < 0 or >= 4)
|
|
{
|
|
Debug.Log($"<color=#c191ff>Error: Component index of partner{e.partnerId} is {componentIdx}</color>");
|
|
return;
|
|
}
|
|
|
|
if (Components[componentIdx].UpdatePartnerScore(e.score))
|
|
EventPartnerAct.Ctx.EventAggregator.Publish(new EventPartnerPartnerAddScore());
|
|
}
|
|
|
|
private async void OnPartnerChange(EventBuildPartnerEvt e)
|
|
{
|
|
await Awaiters.NextFrame;
|
|
switch (e.evtType)
|
|
{
|
|
case 0: //Invited
|
|
RequestPartners.Add(e.partnerId);
|
|
EventPartnerAct.Ctx.EventAggregator.Publish(new EventPartnerOnInvited());
|
|
break;
|
|
case 1: //Accepted
|
|
_data.Components[e.slotId].ComponentIndex = e.slotId;
|
|
_data.Components[e.slotId].ComponentId = _tables.TbEventPartnerMain[RedirectId].ComponentList[e.slotId];
|
|
_data.Components[e.slotId].PartnerId = e.partnerId;
|
|
InvitePartners.Remove(e.partnerId);
|
|
var info = GContext.container.Resolve<IUserService>().GetPlayInfo(e.partnerId);
|
|
EventPartnerAct.Ctx.EventAggregator.Publish(new EventPartnerMatchSuccess
|
|
{
|
|
NamePartner = info.name,
|
|
IconPartner = info.avatarUrl,
|
|
NameComponent = Components[e.slotId].GetComponentName(),
|
|
SlotId = e.slotId,
|
|
PartnerId = e.partnerId
|
|
});
|
|
break;
|
|
case -1: //Refused
|
|
RefusePartners.Add(e.partnerId);
|
|
InvitePartners.Remove(e.partnerId);
|
|
break;
|
|
}
|
|
}
|
|
|
|
public void SubscribeEvent()
|
|
{
|
|
_disposables?.Dispose();
|
|
_disposables = new CompositeDisposable()
|
|
{
|
|
_rtService.OnEvent<EventBuildPartnerEvt>(OnPartnerChange),
|
|
_rtService.OnEvent<EventBuildScoreEvt>(OnPartnerBuild)
|
|
};
|
|
}
|
|
|
|
public enum EEventBuildState : byte
|
|
{
|
|
Success = 0,
|
|
Failed = 1,
|
|
InviteNotFound = 2,
|
|
AlreadyExist = 3,
|
|
NoActiveEvent = 4,
|
|
Full = 5
|
|
}
|
|
|
|
public enum EEventBuildTokenState : byte
|
|
{
|
|
Success = 0,
|
|
InsufficientToken = 1,
|
|
SaveInfoFailure = 2,
|
|
BadRequest = 3,
|
|
}
|
|
|
|
public enum EEventBuildUpdateProgressState : byte
|
|
{
|
|
Success = 0,
|
|
RedisSaveError = 1,
|
|
ProgressRewind = 2,
|
|
SlotIdOutofRange = 3,
|
|
EventBuildInfoNotFound = 4
|
|
}
|
|
|
|
public enum EEventBuildBuildState
|
|
{
|
|
Success = 0,
|
|
InsufficientToken = 1,
|
|
ScoreError = 2,
|
|
PlayerInfoNotFound = 3,
|
|
Failed = 4
|
|
}
|
|
|
|
public class EventBuildInfo
|
|
{
|
|
public Dictionary<int, string> Partners { get; set; }
|
|
|
|
//<summary>
|
|
//Invited Partners
|
|
//</summary>
|
|
public List<string> InvitePartners { get; set; }
|
|
|
|
//<summary>
|
|
//Received Invitations
|
|
//</summary>
|
|
public List<string> RequestPartners { get; set; }
|
|
|
|
//<summary>
|
|
//Refused Invitations
|
|
//</summary>
|
|
public List<string> RefusePartners { get; set; }
|
|
}
|
|
|
|
public class EventBuildBotInfo
|
|
{
|
|
public string Id { get; set; }
|
|
// public int Level { get; set; }
|
|
public int ScorePlayer { get; set; }
|
|
public int ScoreBot { get; set; }
|
|
[JsonIgnore]
|
|
public EventBuildBotAddScoreAction[] ActionQueue { get; set; }
|
|
|
|
/// <summary>
|
|
/// Score grade, 1-4
|
|
/// </summary>
|
|
public int Grade { get; set; }
|
|
public int TargetScore { get; set; }
|
|
public DateTime WakeStartTime { get; set; }
|
|
public int WakingSeconds { get; set; }
|
|
}
|
|
|
|
public class EventBuildBotAddScoreAction
|
|
{
|
|
public DateTime? Time { get; set; }
|
|
public int Score { get; set; }
|
|
}
|
|
|
|
public class EventBuildDetailRequest
|
|
{
|
|
public int eventId { get; set; }
|
|
}
|
|
|
|
|
|
public class EventBuildDetailResp
|
|
{
|
|
public EEventBuildState State { get; set; }
|
|
public string Message { get; set; }
|
|
public EventBuildInfo Info { get; set; }
|
|
public Dictionary<int, Dictionary<string, int>> Scores { get; set; }
|
|
}
|
|
|
|
public class EventBuildOperationResp
|
|
{
|
|
public EEventBuildState State { get; set; }
|
|
public int? SlotId { get; set; }
|
|
public string ErrorMessage { get; set; }
|
|
}
|
|
|
|
public class EventBuildRecommendPlayerRequest
|
|
{
|
|
public List<string> Exclude { get; set; }
|
|
public int? MaxLevel { get; set; }
|
|
public int? MinLevel { get; set; }
|
|
public int Count = 10;
|
|
}
|
|
|
|
public class EventBuildRecommendPlayerResp
|
|
{
|
|
public EEventBuildState State { get; set; }
|
|
public string ErrorMessage { get; set; }
|
|
public List<PlayerInfo> Players { get; set; }
|
|
}
|
|
|
|
public class EventBuildChangeScoreRequest
|
|
{
|
|
public string partnerId { get; set; }
|
|
public int slotId { get; set; }
|
|
public int score { get; set; }
|
|
public int eventId { get; set; }
|
|
}
|
|
|
|
public class EventBuildPartnerRequest
|
|
{
|
|
public string partnerId { get; set; }
|
|
public int eventId { get; set; }
|
|
}
|
|
|
|
public class EventBuildPartnerEvt
|
|
{
|
|
// 0 = invite 1 = accept -1 = reject
|
|
public int evtType { get; set; }
|
|
public string partnerId { get; set; }
|
|
public int slotId { get; set; }
|
|
}
|
|
|
|
public class EventBuildScoreEvt
|
|
{
|
|
public string partnerId { get; set; }
|
|
public int score { get; set; }
|
|
}
|
|
|
|
// public class EventBuildRewardStatusResp
|
|
// {
|
|
// public EEventBuildState State { get; set; }
|
|
// public string Message { get; set; }
|
|
// public bool IsRewardCollected { get; set; }
|
|
// }
|
|
|
|
// public class EventBuildUpdateProgressRequest
|
|
// {
|
|
// public int SlotId { get; set; }
|
|
// public int NewProgress { get; set; }
|
|
// }
|
|
|
|
public class PlayerInfo
|
|
{
|
|
public string PlayFabId { get; set; }
|
|
public string AvatarUrl { get; set; }
|
|
public string DisplayName { get; set; }
|
|
public int Level { get; set; }
|
|
public DateTime? lastLoginTime { get; set; }
|
|
public DateTime? createTime { get; set; }
|
|
}
|
|
|
|
public class EventBuildRecentPlayerInfoRequest
|
|
{
|
|
public string[] playerPrefabs { get; set; }
|
|
}
|
|
|
|
public class EventBuildRecentPlayerInfoResponse
|
|
{
|
|
public EEventBuildState State { get; set; }
|
|
public string Message { get; set; }
|
|
public List<PlayerInfo> playerInfos { get; set; }
|
|
public string[] leftOvers { get; set; }
|
|
}
|
|
|
|
public class EventBuildPlayerDisplayInfoRequest
|
|
{
|
|
public string[] PlayfabIds { get; set; }
|
|
}
|
|
|
|
public class EventBuildPlayerDisplayInfoResp
|
|
{
|
|
public EEventBuildState State { get; set; }
|
|
public string Message { get; set; }
|
|
public List<PlayerInfo> PlayerInfos { get; set; }
|
|
}
|
|
|
|
public class EventBuildBuildRequest
|
|
{
|
|
public string PartnerId { get; set; }
|
|
public int NewScore { get; set; }
|
|
public int EventId { get; set; }
|
|
}
|
|
|
|
public class EventBuildBuildResponse
|
|
{
|
|
public EEventBuildBuildState State { get; set; }
|
|
public string Message { get; set; }
|
|
}
|
|
|
|
#endregion
|
|
|
|
public class EventPartnerPlayfabData
|
|
{
|
|
[JsonIgnore]
|
|
public const string Key = "EventPartnerData";
|
|
public int EventId { get; set; }
|
|
public int TicketCount { get; set; }
|
|
public int InvitationCount { get; set; }
|
|
public bool IsBuildingRewardCollected { get; set; }
|
|
public Dictionary<int, int> LastProgressReceived { get; set; }
|
|
public Dictionary<int, EventBuildBotInfo> Bots { get; set; }
|
|
|
|
public void Save()
|
|
{
|
|
var s = JsonConvert.SerializeObject(this);
|
|
PlayFabMgr.Instance.UpdateUserDataValue("EventPartnerData", s);
|
|
}
|
|
|
|
public static EventPartnerPlayfabData FromString(string s)
|
|
{
|
|
try
|
|
{
|
|
if (s == null || s == "")
|
|
{
|
|
Debug.Log($"<color=#2d7cee>[EventPartner] Empty incoming data.</color>");
|
|
return new EventPartnerPlayfabData();
|
|
}
|
|
var data = JsonConvert.DeserializeObject<EventPartnerPlayfabData>(s);
|
|
return data;
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Debug.LogError("[EventPartner] Failed to parse EventPartnerPlayfabData");
|
|
Debug.LogError(e);
|
|
return new EventPartnerPlayfabData();
|
|
}
|
|
}
|
|
}
|
|
|
|
public EventPartnerPlayfabData ToPlayfabData()
|
|
{
|
|
var data = new EventPartnerPlayfabData
|
|
{
|
|
EventId = EventId,
|
|
TicketCount = TicketCount,
|
|
InvitationCount = InvitationCount,
|
|
IsBuildingRewardCollected = IsBuildingRewardCollected,
|
|
LastProgressReceived = Components.ToDictionary(c => c.ComponentIndex, c => c.LastProgressReceived),
|
|
Bots = Components.Where(c => c.PartnerId.EndsWith(EventPartnerBot.RobotIdentifier)).ToDictionary(c => c.ComponentIndex,
|
|
c => new EventBuildBotInfo
|
|
{
|
|
Id = c.PartnerId,
|
|
ScoreBot = c.ScorePartner,
|
|
ScorePlayer = c.ScoreSelf,
|
|
WakeStartTime = c.BotWakeTime,
|
|
WakingSeconds = c.BotWakingSeconds,
|
|
Grade = c.BotGrade,
|
|
TargetScore = c.BotTargetScore,
|
|
}),
|
|
};
|
|
return data;
|
|
}
|
|
}
|
|
|
|
public class EventPartnerTicketChangedEvent { } |