diff --git a/AscNet.Common/MsgPack/Types.cs b/AscNet.Common/MsgPack/Types.cs index 79ca454..33ebaa3 100644 --- a/AscNet.Common/MsgPack/Types.cs +++ b/AscNet.Common/MsgPack/Types.cs @@ -430,7 +430,7 @@ namespace AscNet.Common.MsgPack [global::MessagePack.MessagePackObject(true)] public class NotifyChatLoginData { - public UInt32 RefreshTime { get; set; } + public long RefreshTime { get; set; } [global::MessagePack.MessagePackObject(true)] public class NotifyChatLoginDataUnlockEmoji { diff --git a/AscNet.GameServer/Handlers/AccountModule.cs b/AscNet.GameServer/Handlers/AccountModule.cs index b272a6c..ad33dec 100644 --- a/AscNet.GameServer/Handlers/AccountModule.cs +++ b/AscNet.GameServer/Handlers/AccountModule.cs @@ -1,9 +1,11 @@ using AscNet.Common.Database; using AscNet.Common.MsgPack; using AscNet.Common.Util; +using AscNet.Table.share.chat; using AscNet.Table.share.guide; using AscNet.Table.share.item; using MessagePack; +using System.Diagnostics; namespace AscNet.GameServer.Handlers { @@ -161,10 +163,17 @@ namespace AscNet.GameServer.Handlers } }; + NotifyChatLoginData notifyChatLoginData = new() + { + RefreshTime = ((DateTimeOffset)Process.GetCurrentProcess().StartTime).ToUnixTimeSeconds(), + UnlockEmojis = EmojiTableReader.Instance.All.Select(x => new NotifyChatLoginData.NotifyChatLoginDataUnlockEmoji() { Id = (uint)x.Id }).ToList() + }; + session.SendPush(notifyLogin); session.SendPush(notifyCharacterData); session.SendPush(notifyEquipData); session.SendPush(notifyAssistData); + session.SendPush(notifyChatLoginData); // NEEDED to not softlock! session.SendPush(new NotifyFubenPrequelData() { FubenPrequelData = new() }); diff --git a/AscNet.GameServer/Handlers/ChatModule.cs b/AscNet.GameServer/Handlers/ChatModule.cs index 9285def..c05af65 100644 --- a/AscNet.GameServer/Handlers/ChatModule.cs +++ b/AscNet.GameServer/Handlers/ChatModule.cs @@ -1,8 +1,108 @@ using AscNet.Common.MsgPack; +using AscNet.Table.share.chat; +using MessagePack; namespace AscNet.GameServer.Handlers { - internal class ChatModule + #region MsgPackScheme +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + [MessagePackObject(true)] + public class SelectChatChannelRequest + { + public int ChannelId { get; set; } + } + + [MessagePackObject(true)] + public class SelectChatChannelResponse + { + public int Code { get; set; } + } + + [MessagePackObject(true)] + public class GetEmojiPackageIdResponse + { + public int Code { get; set; } + public List OrderEmojiPackageIds { get; set; } = new(); + } + + [MessagePackObject(true)] + public class SendChatRequest + { + public ChatData ChatData { get; set; } + public List TargetIdList { get; set; } = new(); + } + + [MessagePackObject(true)] + public class SendChatResponse + { + public int Code { get; set; } + public ChatData ChatData { get; set; } + public long RefreshTime { get; set; } + } + + [MessagePackObject(true)] + public class NotifyWorldChat + { + public List ChatMessages { get; set; } = new(); + } + + [MessagePackObject(true)] + public class ChatData + { + public int MessageId { get; set; } + public ChatChannelType ChannelType { get; set; } + public ChatMsgType MsgType { get; set; } + public long SenderId { get; set; } + public int Icon { get; set; } + public string NickName { get; set; } + public long TargetId { get; set; } + public long CreateTime { get; set; } + public string? Content { get; set; } + public int GiftId { get; set; } + public int GiftCount { get; set; } + public ChatGiftState GiftStatus { get; set; } + public bool IsRead { get; set; } + public int CurrMedalId { get; set; } + public int BabelTowerLevel { get; set; } + public int BabelTowerTitleId { get; set; } + public int GuildRankLevel { get; set; } + public string? GuildName { get; set; } + public int CollectWordId { get; set; } + public int NameplateId { get; set; } + } + + public enum ChatChannelType + { + System = 1, + World = 2, + Private = 3, + Room = 4, + Battle = 5, + Guild = 6, + Mentor = 7, + } + + public enum ChatMsgType + { + Normal = 1, + Emoji = 2, + Gift = 3, + Tips = 4, + RoomMsg = 5, + System = 6, + SpringFestival = 7, + } + + public enum ChatGiftState { + None = 0, + WaitReceive = 1, + Received = 2, + Fetched = 3, + } +#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. +#endregion + +internal class ChatModule { [RequestPacketHandler("EnterWorldChatRequest")] public static void EnterWorldChatRequestHandler(Session session, Packet.Request packet) @@ -21,9 +121,15 @@ namespace AscNet.GameServer.Handlers GetWorldChannelInfoResponse getWorldChannelInfoResponse = new(); getWorldChannelInfoResponse.ChannelInfos.Add(new() { - ChannelId = 0, + ChannelId = 0, // Channel 1 PlayerNum = 0 }); + getWorldChannelInfoResponse.ChannelInfos.Add(new() + { + ChannelId = 1, // Recuruit channel (we don't use this!) + PlayerNum = 0 + }); + session.SendResponse(getWorldChannelInfoResponse, packet.Id); } @@ -37,5 +143,44 @@ namespace AscNet.GameServer.Handlers }; session.SendResponse(offlineMessageResponse, packet.Id); } + + [RequestPacketHandler("SendChatRequest")] + public static void SendChatRequestHandler(Session session, Packet.Request packet) + { + SendChatRequest request = MessagePackSerializer.Deserialize(packet.Content); + request.ChatData.SenderId = session.player.PlayerData.Id; + request.ChatData.Icon = (int)session.player.PlayerData.CurrHeadPortraitId; + request.ChatData.NickName = session.player.PlayerData.Name; + + NotifyWorldChat notifyWorldChat = new(); + notifyWorldChat.ChatMessages.Add(request.ChatData); + + session.SendPush(notifyWorldChat); + session.SendResponse(new SendChatResponse() { Code = 0, ChatData = request.ChatData, RefreshTime = DateTimeOffset.Now.ToUnixTimeSeconds() }, packet.Id); + } + + [RequestPacketHandler("SelectChatChannelRequest")] + public static void SelectChatChannelRequestHandler(Session session, Packet.Request packet) + { + // SelectChatChannelRequest request = MessagePackSerializer.Deserialize(packet.Content); + + // disabling channel switching because the game is cringe and we don't need it anyway. + session.SendResponse(new SelectChatChannelResponse() + { + Code = 20033013 // ChatChannelNotExist + }, packet.Id); + } + + #region EmojiPackModule + [RequestPacketHandler("GetEmojiPackageIdRequest")] + public static void GetEmojiPackageIdRequestHandler(Session session, Packet.Request packet) + { + session.SendResponse(new GetEmojiPackageIdResponse() + { + Code = 0, + OrderEmojiPackageIds = EmojiPackTableReader.Instance.All.Select(x => x.Id).ToList() + }, packet.Id); + } + #endregion } } diff --git a/Resources/Configs/version_config.json b/Resources/Configs/version_config.json index cf373e6..cd3c8c5 100644 --- a/Resources/Configs/version_config.json +++ b/Resources/Configs/version_config.json @@ -7,10 +7,10 @@ "LaunchIndexSha1": "334196cd32a865ae030f39407b198016af0a8aa9" }, "1.31.0": { - "DocumentVersion": "1.31.4", - "LaunchModuleVersion": "1.31.0", + "DocumentVersion": "1.31.5", + "LaunchModuleVersion": "1.31.5", "IndexMd5": "c5d4baac85a6e37b8109ea43dc045d31", - "IndexSha1": "94d8e34686f0c52f80462f37469dcdb1e3b24db3", - "LaunchIndexSha1": "334196cd32a865ae030f39407b198016af0a8aa9" + "IndexSha1": "5e1c9a7213857d9f1c1223f4871feb425a598294", + "LaunchIndexSha1": "def7cf0ae2dbc6a31c5f85632f1d82d1f1d6cbfa" } } \ No newline at end of file