feat(upserver): 接入认证与KV存档并完成限定钓鱼闭环

This commit is contained in:
Liubing\LB
2026-09-28 18:14:01 +08:00
parent f40a816cc4
commit 0eb43b2b40
129 changed files with 11612 additions and 573 deletions

View File

@@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using UnityEngine;
using Newtonsoft.Json.Linq;
namespace game
{
@@ -47,6 +48,27 @@ namespace game
public DateTime? signTime { get; private set; }
LureDonateData lureDonateData;
// KV loading owns these three fields only; membership, transport and chat lifecycle stay untouched.
internal static PlayerDataStorage.PlayerKVClubState DecodeForKVLoad(IReadOnlyDictionary<string,string> raw,
PlayerDataStorage.PlayerKVSchemaSnapshot snapshot, PlayerDataStorage.PlayerKVSchemaDiagnostics errors) =>
PlayerDataStorage.PlayerKVSaveSchema.DecodeClub(raw,snapshot,errors);
internal void ResetForKVLoad()
{
signTime = null;
lureDonateData = new LureDonateData();
IsOpenClubRed = true;
}
internal void ReplaceFromKVDecoded(PlayerDataStorage.PlayerKVClubState state)
{
if (state == null) throw new ArgumentNullException(nameof(state));
var donation = new LureDonateData { DonateCountTime=state.DonateTime,
ClubLureDonateCount=state.DonateCount, ClubLureRequestCDEnd=state.RequestEnd };
signTime = state.SignTime; lureDonateData = donation; IsOpenClubRed = state.OpenRed;
}
internal PlayerDataStorage.PlayerKVClubState SnapshotForKVValidation() =>
new PlayerDataStorage.PlayerKVClubState(signTime,lureDonateData.DonateCountTime,
lureDonateData.ClubLureDonateCount,lureDonateData.ClubLureRequestCDEnd,IsOpenClubRed);
public int ClubLureDonateCount => lureDonateData.ClubLureDonateCount;
public DateTime ClubLureRequestCDEnd => lureDonateData.ClubLureRequestCDEnd;
@@ -154,28 +176,37 @@ namespace game
}
public async void GetSelfClub()
{
if (!userService.IsAuthorized || string.IsNullOrEmpty(userService.ApiPlayerId))
return;
var sessionVersion = customServerMgr.SessionVersion;
GetSelfClubRequest getSelfClubRequest = new GetSelfClubRequest()
{
playerId = userService.UserId,
playerId = userService.ApiPlayerId,
};
string json = await customServerMgr.ClubRequest("GetSelfClub", getSelfClubRequest);
if (!string.IsNullOrEmpty(json) && json != "[]")
if (sessionVersion != customServerMgr.SessionVersion) return;
if (string.IsNullOrWhiteSpace(json)) return;
GetSelfClubResp response;
try
{
GetSelfClubResp getSelfClubResp = Newtonsoft.Json.JsonConvert.DeserializeObject<GetSelfClubResp>(json);
myClubInfo = getSelfClubResp.clubInfo;
if (myClubInfo != null)
{
memberRole = getSelfClubResp.role;
//signTime = getSelfClubResp.signTime;
internalIdToPlayerId = getSelfClubResp.playerIDs;
SetClubPlayerProfile(getSelfClubResp.clubPlayerProfiles);
chatService.GetConversationList((long)myClubInfo.id);
}
var body = JObject.Parse(json);
if (!body.TryGetValue("clubInfo", out var club) ||
(club.Type != JTokenType.Null && club.Type != JTokenType.Object)) return;
response = body.ToObject<GetSelfClubResp>();
if (response == null) return;
if (club.Type == JTokenType.Object &&
(response.clubInfo == null || response.clubInfo.id == 0 ||
body["role"]?.Type != JTokenType.Integer || !Enum.IsDefined(typeof(EMemberRole), response.role))) return;
}
else
catch (Newtonsoft.Json.JsonException) { return; }
catch (OverflowException) { return; }
myClubInfo = response.clubInfo;
memberRole = myClubInfo == null ? EMemberRole.Member : response.role;
internalIdToPlayerId = response.playerIDs ?? new Dictionary<long, string>();
if (myClubInfo != null)
{
memberRole = EMemberRole.Member;
myClubInfo = null;
SetClubPlayerProfile(response.clubPlayerProfiles);
chatService.GetConversationList((long)myClubInfo.id);
}
SetClubRed();
MyClubInfoChange();
@@ -218,16 +249,48 @@ namespace game
}
}
private static bool IsDecimalPlayerId(string id) =>
long.TryParse(id, System.Globalization.NumberStyles.None,
System.Globalization.CultureInfo.InvariantCulture, out var number) && number > 0;
private bool TryGetClubSession(out string playerId, out int version)
{
playerId = userService.ApiPlayerId;
version = customServerMgr.SessionVersion;
return userService.IsAuthorized && IsDecimalPlayerId(playerId);
}
private bool IsClubSessionCurrent(string playerId, int version) =>
version == customServerMgr.SessionVersion && userService.IsAuthorized && playerId == userService.ApiPlayerId;
private static bool TryReadClubResponse<T>(string json, out T result, params int[] acceptedCodes) where T : class
{
result = null;
if (string.IsNullOrWhiteSpace(json)) return false;
try
{
var body = Newtonsoft.Json.Linq.JObject.Parse(json);
var code = body["code"];
if (code?.Type != Newtonsoft.Json.Linq.JTokenType.Integer || !acceptedCodes.Contains(code.Value<int>())) return false;
result = body.ToObject<T>();
return result != null;
}
catch (Newtonsoft.Json.JsonException) { return false; }
catch (OverflowException) { return false; }
}
public async Task<List<SocialInfoItemData>> GetClubDetails(ulong clubID, bool applyState = false)
{
if (!TryGetClubSession(out var apiPlayerId, out var sessionVersion)) return null;
ApplyState = false;
GetClubDetailsRequest getClubDetailsRequest = new GetClubDetailsRequest()
{
id = clubID,
playerId = userService.UserId,
playerId = apiPlayerId,
applyState = applyState,
};
string json = await customServerMgr.ClubRequest("GetClubDetails", getClubDetailsRequest);
if (!IsClubSessionCurrent(apiPlayerId, sessionVersion)) return null;
if (!string.IsNullOrEmpty(json) && json != "[]")
{
GetClubDetailsResp clubDetails = Newtonsoft.Json.JsonConvert.DeserializeObject<GetClubDetailsResp>(json);
@@ -243,6 +306,7 @@ namespace game
}
List<long> longs1 = clubDetails.playerIDs.Keys.ToList();
HashSet<long> longs = await chatService.GetOnlineUsers(longs1);
if (!IsClubSessionCurrent(apiPlayerId, sessionVersion)) return null;
List<ClubPlayerProfile> clubPlayerProfiles = clubDetails.clubPlayerProfiles;
SetClubPlayerProfile(clubPlayerProfiles);
@@ -284,40 +348,27 @@ namespace game
public async Task<ClubInfo> CreateClub(ClubSettingData clubSettingData)
{
CreateClubRequest createClubRequest = new CreateClubRequest()
{
playerId = userService.UserId,
//entityKey = userService.entityKey.Id,
clubSettingData = clubSettingData,
};
string json = await customServerMgr.ClubRequest("CreateClub", createClubRequest);
if (!string.IsNullOrEmpty(json) && json != "[]")
{
CreateClubResp createClubResp = Newtonsoft.Json.JsonConvert.DeserializeObject<CreateClubResp>(json);
if (createClubResp.code != 2)
{
if (createClubResp.code == 0)
{
memberRole = EMemberRole.Owner;
ShowPromote();
}
myClubInfo = createClubResp.clubInfo;
chatService.GetConversationList((long)myClubInfo.id);
internalIdToPlayerId[userService.InternalId] = userService.UserId;
MyClubInfoChange(true);
return myClubInfo;
}
}
else
{
myClubInfo = null;
}
MyClubInfoChange();
if (!TryGetClubSession(out var apiPlayerId, out var sessionVersion)) return null;
var internalId = userService.InternalId;
var request = new CreateClubRequest { playerId = apiPlayerId, clubSettingData = clubSettingData };
var json = await customServerMgr.ClubRequest("CreateClub", request);
if (!IsClubSessionCurrent(apiPlayerId, sessionVersion)) return null;
// Code 1 means already a member; returning a club would charge the create UI again.
if (!TryReadClubResponse<CreateClubResp>(json, out var response, 0) || response.clubInfo == null || response.clubInfo.id == 0)
return null;
memberRole = EMemberRole.Owner;
myClubInfo = response.clubInfo;
internalIdToPlayerId[internalId] = apiPlayerId;
ShowPromote();
chatService.GetConversationList((long)myClubInfo.id);
MyClubInfoChange(true);
return myClubInfo;
}
public async void ShowPromote()
{
if (!TryGetClubSession(out var apiPlayerId, out var sessionVersion)) return;
GameObject go = await UIManager.Instance.ShowUI(UITypes.ClubPromoteNoticePopupPanel);
if (!IsClubSessionCurrent(apiPlayerId, sessionVersion) || go == null) return;
var ClubPromoteNoticePopupPanel = go.GetComponent<ClubPromoteNoticePopupPanel>();
ClubPromoteNoticePopupPanel.SetRole(memberRole);
}
@@ -344,19 +395,21 @@ namespace game
public async Task<bool> ApplyClub(ulong clubID)
{
memberRole = EMemberRole.Member;
if (!TryGetClubSession(out var apiPlayerId, out var sessionVersion)) return false;
ApplyClubRequest applyClubRequest = new ApplyClubRequest()
{
playerId = userService.UserId,
playerId = apiPlayerId,
//entityKey = userService.entityKey.Id,
id = clubID,
};
string json = await customServerMgr.ClubRequest("ApplyClub", applyClubRequest);
if (!IsClubSessionCurrent(apiPlayerId, sessionVersion)) return false;
if (!string.IsNullOrEmpty(json) && json != "[]")
{
ApplyClubResp applyClubResp = Newtonsoft.Json.JsonConvert.DeserializeObject<ApplyClubResp>(json);
if (applyClubResp.code == 0)
{
memberRole = EMemberRole.Member;
ToastPanel.Show(LocalizationMgr.GetText("UI_ToastPanel_41"));
myClubInfo = applyClubResp.clubInfo;
internalIdToPlayerId = applyClubResp.playerIDs;
@@ -380,6 +433,10 @@ namespace game
public async void HandleApply(bool isAgree, string applyId)
{
if (!TryGetClubSession(out var apiPlayerId, out var sessionVersion)) return;
if (applyId == "" && isAgree) return;
if (applyId != "" && !IsDecimalPlayerId(applyId)) return;
if (myClubInfo == null) return;
if (isAgree && myClubInfo.curMembers >= myClubInfo.maxMembers)
{
//人数已满
@@ -392,31 +449,32 @@ namespace game
isAgree = isAgree,
id = myClubInfo.id,
};
if (applyId == "")
{
clubPlayerInfos.Clear();
RedPointManager.Instance.SetRedPointState(RedPointName.ApplyList, false);
}
else
{
for (int i = 0; i < clubPlayerInfos.Count; i++)
{
if (clubPlayerInfos[i].playFabId == applyId)
{
clubPlayerInfos.RemoveAt(i);
RedPointManager.Instance.SetRedPointState(RedPointName.ApplyList, clubPlayerInfos.Count > 0
&& CanAccepted);
break;
}
}
}
string json = await customServerMgr.ClubRequest("HandleApply", handleApplyRequest);
if (!IsClubSessionCurrent(apiPlayerId, sessionVersion)) return;
if (!string.IsNullOrEmpty(json) && json != "[]")
{
HandleApplyResp handleApplyResp = Newtonsoft.Json.JsonConvert.DeserializeObject<HandleApplyResp>(json);
if (handleApplyResp.code == 0)
if (!TryReadClubResponse<HandleApplyResp>(json, out var handleApplyResp, applyId == "" ? 4 : 0) || myClubInfo == null) return;
if (handleApplyResp.code == 0 || handleApplyResp.code == 4)
{
myClubInfo.curMembers++;
if (applyId == "")
{
clubPlayerInfos.Clear();
RedPointManager.Instance.SetRedPointState(RedPointName.ApplyList, false);
}
else
{
for (int i = 0; i < clubPlayerInfos.Count; i++)
{
if (clubPlayerInfos[i].playFabId == applyId)
{
clubPlayerInfos.RemoveAt(i);
RedPointManager.Instance.SetRedPointState(RedPointName.ApplyList, clubPlayerInfos.Count > 0
&& CanAccepted);
break;
}
}
}
if (isAgree) myClubInfo.curMembers++;
GContext.Publish(new ClubSttingUpdateEvent());
}
}
@@ -424,17 +482,19 @@ namespace game
public async void GetApplyList()
{
clubPlayerInfos = new List<SocialInfoItemData>();
RedPointManager.Instance.SetRedPointState(RedPointName.ApplyList, false);
if (!TryGetClubSession(out var apiPlayerId, out var sessionVersion)) return;
if (myClubInfo == null) return;
GetApplyListRequest getApplyListRequest = new GetApplyListRequest()
{
playerId = userService.UserId,
playerId = apiPlayerId,
id = myClubInfo.id,
};
string json = await customServerMgr.ClubRequest("GetApplyList", getApplyListRequest);
if (!IsClubSessionCurrent(apiPlayerId, sessionVersion)) return;
if (!string.IsNullOrEmpty(json) && json != "[]")
{
GetApplyListResp getApplyListResp = Newtonsoft.Json.JsonConvert.DeserializeObject<GetApplyListResp>(json);
clubPlayerInfos = new List<SocialInfoItemData>();
SetClubPlayerProfile(getApplyListResp.clubPlayerProfiles);
for (int i = 0; i < getApplyListResp.userIDList.Count; i++)
{
@@ -467,16 +527,12 @@ namespace game
}
public async void QuitClub(string appointId = "0")
{
QuitClubRequest quitClubRequest = new QuitClubRequest()
{
playerId = userService.UserId,
appointId = appointId,
};
string json = await customServerMgr.ClubRequest("QuitClub", quitClubRequest);
//if (!string.IsNullOrEmpty(json) && json != "[]")
//{
// QuitClubResp quitClubResp = Newtonsoft.Json.JsonConvert.DeserializeObject<QuitClubResp>(json);
//}
if (!TryGetClubSession(out var apiPlayerId, out var sessionVersion)) return;
if (!string.IsNullOrEmpty(appointId) && appointId != "0" && (!IsDecimalPlayerId(appointId) || appointId == apiPlayerId)) return;
var request = new QuitClubRequest { playerId = apiPlayerId, appointId = appointId };
var json = await customServerMgr.ClubRequest("QuitClub", request);
if (!IsClubSessionCurrent(apiPlayerId, sessionVersion)) return;
if (!TryReadClubResponse<QuitClubResp>(json, out var response, 0, 1)) return;
chatService.OnQuit();
myClubInfo = null;
ClearLikeCursorIds();
@@ -485,36 +541,49 @@ namespace game
}
public async void Demote(string playerId)
{
if (!TryGetClubSession(out var apiPlayerId, out var sessionVersion)) return;
if (!IsDecimalPlayerId(playerId) || playerId == apiPlayerId) return;
if (myClubInfo == null) return;
DemoteClubRequest demoteClubRequest = new DemoteClubRequest()
{
culbId = myClubInfo.id,
demoteId = playerId,
playerId = userService.UserId,
playerId = apiPlayerId,
};
string json = await customServerMgr.ClubRequest("DemoteClub", demoteClubRequest);
if (!IsClubSessionCurrent(apiPlayerId, sessionVersion)) return;
}
public async void Promote(string playerId, EMemberRole role)
{
if (!TryGetClubSession(out var apiPlayerId, out var sessionVersion)) return;
if (!IsDecimalPlayerId(playerId) || playerId == apiPlayerId) return;
if (myClubInfo == null) return;
PromoteClubRequest promoteClubRequest = new PromoteClubRequest()
{
culbId = myClubInfo.id,
promoteId = playerId,
playerId = userService.UserId,
playerId = apiPlayerId,
role = role,
};
string json = await customServerMgr.ClubRequest("PromoteClub", promoteClubRequest);
if (!IsClubSessionCurrent(apiPlayerId, sessionVersion)) return;
}
public async void Kickout(string playerId)
{
if (!TryGetClubSession(out var apiPlayerId, out var sessionVersion)) return;
if (!IsDecimalPlayerId(playerId) || playerId == apiPlayerId) return;
if (myClubInfo == null) return;
KickoutClubRequest kickoutClubRequest = new KickoutClubRequest()
{
culbId = myClubInfo.id,
kickoutId = playerId,
playerId = userService.UserId,
playerId = apiPlayerId,
};
myClubInfo.curMembers--;
GContext.Publish(new ClubSttingUpdateEvent());
string json = await customServerMgr.ClubRequest("KickoutClub", kickoutClubRequest);
if (!IsClubSessionCurrent(apiPlayerId, sessionVersion)) return;
if (!TryReadClubResponse<KickoutClubResp>(json, out var response, 0) || myClubInfo == null) return;
myClubInfo.curMembers = Math.Max(0, myClubInfo.curMembers - 1);
GContext.Publish(new ClubSttingUpdateEvent());
//if (!string.IsNullOrEmpty(json) && json != "[]")
//{
// KickoutClubResp quitClubResp = Newtonsoft.Json.JsonConvert.DeserializeObject<KickoutClubResp>(json);
@@ -522,52 +591,67 @@ namespace game
}
public async void ReadClubEvent()
{
if (!TryGetClubSession(out var apiPlayerId, out var sessionVersion)) return;
ReadClubEventRequest readClubEventRequest = new ReadClubEventRequest()
{
playerId = userService.UserId,
playerId = apiPlayerId,
};
string json = await customServerMgr.ClubRequest("ReadClubEvent", readClubEventRequest);
if (!IsClubSessionCurrent(apiPlayerId, sessionVersion)) return;
//if (!string.IsNullOrEmpty(json) && json != "[]")
//{
// ReadClubEventResp readClubEventResp = Newtonsoft.Json.JsonConvert.DeserializeObject<ReadClubEventResp>(json);
//}
}
public async void ClubSingin()
private int? signingSession;
public async Task ClubSingin()
{
signTime = ZZTimeHelper.UtcNow().UtcNowOffset();
ClubSinginRequest clubSinginRequest = new ClubSinginRequest()
if (!TryGetClubSession(out var apiPlayerId, out var sessionVersion)) return;
if (myClubInfo == null) return;
if (signingSession == sessionVersion || signTime?.Date == ZZTimeHelper.UtcNow().UtcNowOffset().Date) return;
signingSession = sessionVersion;
try
{
playerId = userService.UserId,
id = myClubInfo.id,
};
string json = await customServerMgr.ClubRequest("ClubSingin", clubSinginRequest);
if (!string.IsNullOrEmpty(json) && json != "[]")
{
ClubSinginResp clubSinginResp = Newtonsoft.Json.JsonConvert.DeserializeObject<ClubSinginResp>(json);
signTime = ZZTimeHelper.UtcNow().UtcNowOffset();
PlayFabMgr.Instance.UpdateUserDataValue("ClubSignin", signTime.Value.ToString("yyyy-MM-dd HH:mm:ss"));
if (clubSinginResp.code == 0)
ClubSinginRequest clubSinginRequest = new ClubSinginRequest()
{
chatService.SendSystemMessage($"{MessageChatType.SI}_{userService.UserId}");
//签到成功奖励
GContext.container.Resolve<PlayerItemData>().AddItemByDrop(GContext.container.Resolve<cfg.Tables>().TbServerConfig.ClubSignReward, null);
GContext.Publish(new ShowData());
#if AGG
using (var e = GEvent.GameEvent("guild_sign"))
playerId = apiPlayerId,
id = myClubInfo.id,
};
string json = await customServerMgr.ClubRequest("ClubSingin", clubSinginRequest);
if (!IsClubSessionCurrent(apiPlayerId, sessionVersion)) return;
if (!string.IsNullOrEmpty(json) && json != "[]")
{
if (!TryReadClubResponse<ClubSinginResp>(json, out var clubSinginResp, 0)) return;
signTime = ZZTimeHelper.UtcNow().UtcNowOffset();
PlayFabMgr.Instance.UpdateUserDataValue("ClubSignin", signTime.Value.ToString("yyyy-MM-dd HH:mm:ss"));
if (clubSinginResp.code == 0)
{
e.AddContent("guild_id", myClubInfo.id)
.AddContent("drop_list", GContext.container.Resolve<cfg.Tables>().TbServerConfig.ClubSignReward);
chatService.SendSystemMessage($"{MessageChatType.SI}_{apiPlayerId}");
//签到成功奖励
GContext.container.Resolve<PlayerItemData>().AddItemByDrop(GContext.container.Resolve<cfg.Tables>().TbServerConfig.ClubSignReward, null);
GContext.Publish(new ShowData());
#if AGG
using (var e = GEvent.GameEvent("guild_sign"))
{
e.AddContent("guild_id", myClubInfo.id)
.AddContent("drop_list", GContext.container.Resolve<cfg.Tables>().TbServerConfig.ClubSignReward);
}
#endif
}
#endif
}
SetClubRed();
}
finally
{
if (signingSession == sessionVersion) signingSession = null;
}
SetClubRed();
}
public void SendSystemMessage2(int index)
{
chatService.SendSystemMessage2($"{userService.UserId}_{index}");
if (!TryGetClubSession(out var apiPlayerId, out _)) return;
chatService.SendSystemMessage2($"{apiPlayerId}_{index}");
}
/// <summary>
@@ -583,15 +667,17 @@ namespace game
}
public async void GetServiceEvent()
{
energyAddCount = 0;
if (!TryGetClubSession(out var apiPlayerId, out var sessionVersion)) return;
GetPictureRequest getPictureRequest = new GetPictureRequest()
{
playerId = userService.UserId,
playerId = apiPlayerId,
};
string json = await customServerMgr.ClubRequest("GetPictureList", getPictureRequest);
if (!IsClubSessionCurrent(apiPlayerId, sessionVersion)) return;
if (!string.IsNullOrEmpty(json) && json != "[]")
{
GetPictureResp getPictureResp = Newtonsoft.Json.JsonConvert.DeserializeObject<GetPictureResp>(json);
energyAddCount = 0;
//var pictureDatas = getPictureResp.pictureDataList;
//if (pictureDatas != null && pictureDatas.Count > 0)
//{