diff --git a/Common/Database/PrivateMessage.cs b/Common/Database/PrivateMessage.cs new file mode 100644 index 0000000..4554904 --- /dev/null +++ b/Common/Database/PrivateMessage.cs @@ -0,0 +1,86 @@ +using Common.Resources.Proto; +using MongoDB.Bson; +using MongoDB.Bson.Serialization.Attributes; +using MongoDB.Driver; +using Newtonsoft.Json; + +namespace Common.Database +{ + public class PrivateMessage + { + public static readonly IMongoCollection collection = Global.db.GetCollection("PrivateMessages"); + + public static PrivateMessageScheme Create(uint uid, uint targetUid, ChatMsg chatMsg) + { + PrivateMessageScheme doc = new() { Msg = chatMsg, SenderUid = uid, TargetUid = targetUid, TimeSent = Global.GetUnixInSeconds() }; + collection.InsertOne(doc); + return doc; + } + + public static List GetMessages(uint uid, uint targetUid = 0) + { + List historyPrivateChats = new(); + + if (uid == 0) + { + var gropedMessages = collection.AsQueryable().Where(x => x.SenderUid == uid || x.TargetUid == uid).ToList().GroupBy(x => x, new PrivateMessageComparer()); + + foreach (var group in gropedMessages) + { + List targetedMessages = group.ToList(); + targetUid = targetedMessages.First().TargetUid == uid ? targetedMessages.First().SenderUid : targetedMessages.First().TargetUid; + historyPrivateChats.Add(new() { Uid = targetUid }); + historyPrivateChats.First(x => x.Uid == targetUid).ChatMsgLists.AddRange(targetedMessages.Select(x => x.Msg)); + } + } + else + { + List targetedMessages = collection.AsQueryable().Where(x => (x.SenderUid == uid && x.TargetUid == targetUid) || (x.SenderUid == targetUid && x.TargetUid == uid)).ToList(); + historyPrivateChats.Add(new() { Uid = targetUid }); + historyPrivateChats.First(x => x.Uid == targetUid).ChatMsgLists.AddRange(targetedMessages.Select(x => x.Msg)); + } + + return historyPrivateChats; + } + + public class PrivateMessageComparer : IEqualityComparer + { +#pragma warning disable CS8767 + public bool Equals(PrivateMessageScheme x, PrivateMessageScheme y) + { + return x.SenderUid == y.TargetUid || y.SenderUid == x.TargetUid; + } +#pragma warning restore CS8767 + + public int GetHashCode(PrivateMessageScheme obj) + { + return (obj.SenderUid + obj.TargetUid).GetHashCode(); + } + } + } + +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + [BsonIgnoreExtraElements] + public class PrivateMessageScheme + { + public ObjectId Id { get; set; } + public uint TargetUid { get; set; } + public uint SenderUid { get; set; } + + [BsonIgnore] + public ChatMsg Msg + { + get + { + return JsonConvert.DeserializeObject(SerializedMsg) ?? new ChatMsg(); + } + set + { + SerializedMsg = JsonConvert.SerializeObject(value); + } + } + + public string SerializedMsg { get; set; } + public long TimeSent { get; set; } + } +} diff --git a/GameServer/Game/Chatrooms/PrivateChatManager.cs b/GameServer/Game/Chatrooms/PrivateChatManager.cs new file mode 100644 index 0000000..a0a0dd7 --- /dev/null +++ b/GameServer/Game/Chatrooms/PrivateChatManager.cs @@ -0,0 +1,49 @@ +using Common.Database; +using Common; +using Common.Resources.Proto; + +namespace PemukulPaku.GameServer.Game.Chatrooms +{ + public static class PrivateChatManager + { + public static void OnSendChatMsg(Session session, SendChatMsgNotify chatMsgNotify) + { + ChatMsg chatMsg = chatMsgNotify.ChatMsg; + string? StringMsg = chatMsg.Content.Items.Where(item => item.MsgStr != null).FirstOrDefault()?.MsgStr; + if (StringMsg != null) + { + chatMsg.CheckResult = new() + { + ShieldType = 0, + NumberCheck = 0, + RewriteText = StringMsg + }; + chatMsg.Msg = StringMsg; + } + UserScheme User = session.Player.User; + chatMsg.Uid = User.Uid; + chatMsg.Nickname = User.Nick; + chatMsg.Time = (uint)Global.GetUnixInSeconds(); + chatMsg.AvatarId = (uint)User.AssistantAvatarId; + chatMsg.DressId = session.Player.AvatarList.Where(avatar => avatar.AvatarId == User.AssistantAvatarId).First().DressId; + chatMsg.FrameId = User.FrameId < 200001 ? 200001 : (uint)User.FrameId; + chatMsg.CustomHeadId = (uint)User.CustomHeadId; + + foreach (uint targetUid in chatMsgNotify.TargetUidLists) + { + SendPrivateMessage(session, targetUid, chatMsg); + } + } + + public static void SendPrivateMessage(Session session, uint targetUid, ChatMsg chatMsg) + { + PrivateMessageScheme privateMessage = PrivateMessage.Create(session.Player.User.Uid, targetUid, chatMsg); + Session? targetSession = Session.FromUid(targetUid); + RecvChatMsgNotify notify = new() { }; + notify.ChatMsgLists.Add(privateMessage.Msg); + + session.Send(Packet.FromProto(notify, CmdId.RecvChatMsgNotify)); + targetSession?.Send(Packet.FromProto(notify, CmdId.RecvChatMsgNotify)); + } + } +} diff --git a/GameServer/Handlers/Chat/GetPrivateHistoryChatMsgReqHandler.cs b/GameServer/Handlers/Chat/GetPrivateHistoryChatMsgReqHandler.cs new file mode 100644 index 0000000..06592ff --- /dev/null +++ b/GameServer/Handlers/Chat/GetPrivateHistoryChatMsgReqHandler.cs @@ -0,0 +1,29 @@ +using Common.Database; +using Common.Resources.Proto; + +namespace PemukulPaku.GameServer.Handlers.Chat +{ + [PacketCmdId(CmdId.GetPrivateHistoryChatMsgReq)] + internal class GetPrivateHistoryChatMsgReqHandler : IPacketHandler + { + public void Handle(Session session, Packet packet) + { + GetPrivateHistoryChatMsgReq Data = packet.GetDecodedBody(); + GetPrivateHistoryChatMsgRsp Rsp = new() { retcode = GetPrivateHistoryChatMsgRsp.Retcode.Succ }; + + if (Data.UidLists.Length > 0) + { + foreach (uint targetUid in Data.UidLists) + { + Rsp.ChatLists.AddRange(PrivateMessage.GetMessages(session.Player.User.Uid, targetUid)); + } + } + else + { + Rsp.ChatLists.AddRange(PrivateMessage.GetMessages(session.Player.User.Uid)); + } + + session.Send(Packet.FromProto(Rsp, CmdId.GetPrivateHistoryChatMsgRsp)); + } + } +} diff --git a/GameServer/Handlers/Chat/SendChatMsgNotifyHandler.cs b/GameServer/Handlers/Chat/SendChatMsgNotifyHandler.cs index bfd1e54..36b11af 100644 --- a/GameServer/Handlers/Chat/SendChatMsgNotifyHandler.cs +++ b/GameServer/Handlers/Chat/SendChatMsgNotifyHandler.cs @@ -1,4 +1,5 @@ -using Common.Resources.Proto; +using Common.Database; +using Common.Resources.Proto; using PemukulPaku.GameServer.Game.Chatrooms; namespace PemukulPaku.GameServer.Handlers @@ -11,6 +12,8 @@ namespace PemukulPaku.GameServer.Handlers SendChatMsgNotify Data = packet.GetDecodedBody(); if (Data.ChatMsg.Channel == ChatMsg.MsgChannel.World) WorldChatroom.GetInstance().GetChatroom(session).OnSendChat(session, Data.ChatMsg); + else if (Data.ChatMsg.Channel == ChatMsg.MsgChannel.Private) + PrivateChatManager.OnSendChatMsg(session, Data); } } } diff --git a/GameServer/Handlers/One/SelectNewStigmataRuneReqHandler.cs b/GameServer/Handlers/One/SelectNewStigmataRuneReqHandler.cs index c4d3361..05ac4ba 100644 --- a/GameServer/Handlers/One/SelectNewStigmataRuneReqHandler.cs +++ b/GameServer/Handlers/One/SelectNewStigmataRuneReqHandler.cs @@ -34,7 +34,7 @@ namespace PemukulPaku.GameServer.Handlers } } } - stigmata.WaitSelectRuneGroupLists.Clear(); + stigmata.WaitSelectRuneGroupLists?.Clear(); } session.Player.Equipment.Save(); session.Send(Packet.FromProto(Rsp, CmdId.SelectNewStigmataRuneRsp)); diff --git a/GameServer/Handlers/Two/GetOtherPlayerCardDataReqHandler.cs b/GameServer/Handlers/Two/GetOtherPlayerCardDataReqHandler.cs index 73c36a6..0f0799d 100644 --- a/GameServer/Handlers/Two/GetOtherPlayerCardDataReqHandler.cs +++ b/GameServer/Handlers/Two/GetOtherPlayerCardDataReqHandler.cs @@ -16,7 +16,9 @@ namespace PemukulPaku.GameServer.Handlers.Two if(user is not null) { - Player player = new(user); + Player? player = Session.FromUid(user.Uid)?.Player; + player ??= new(user); + Rsp.CardData = new() { Uid = player.User.Uid, diff --git a/GameServer/Session.cs b/GameServer/Session.cs index c957664..8dbc6af 100644 --- a/GameServer/Session.cs +++ b/GameServer/Session.cs @@ -154,5 +154,10 @@ namespace PemukulPaku.GameServer { return Id; } + + public static Session? FromUid(uint uid) + { + return Server.GetInstance().Sessions.FirstOrDefault(s => s.Value.Player.User.Uid == uid).Value; + } } } diff --git a/Program.cs b/Program.cs index 9ada0ec..77f0ff4 100644 --- a/Program.cs +++ b/Program.cs @@ -4,8 +4,8 @@ using PemukulPaku.GameServer; using Common.Database; using PemukulPaku.GameServer.Game; using PemukulPaku.GameServer.Commands; -using Common.Utils.ExcelReader; -using Newtonsoft.Json; +using MongoDB.Bson; +using Common.Resources.Proto; namespace PemukulPaku { @@ -18,7 +18,8 @@ namespace PemukulPaku #endif Global.c.Log("Starting..."); - Global.config.Gameserver.Host = NetworkInterface.GetAllNetworkInterfaces().Where(i => i.NetworkInterfaceType != NetworkInterfaceType.Loopback && i.OperationalStatus == OperationalStatus.Up).First().GetIPProperties().UnicastAddresses.Where(a => a.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork).First().Address.ToString(); + if (Global.config.Gameserver.Host == "127.0.0.1") + Global.config.Gameserver.Host = NetworkInterface.GetAllNetworkInterfaces().Where(i => i.NetworkInterfaceType != NetworkInterfaceType.Loopback && i.OperationalStatus == OperationalStatus.Up).First().GetIPProperties().UnicastAddresses.Where(a => a.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork).First().Address.ToString(); CommandFactory.LoadCommandHandlers(); PacketFactory.LoadPacketHandlers();