async public void Start() { if (_isListening) throw new InvalidOperationException("Server is already listening"); _listener.Start(); _isListening = true; while (_isListening) { try { var client = await _listener.AcceptTcpClientAsync(); var session = new TcpSession(client); session.PacketReceived += ClientPacketReceived; session.Disconnected += ClientDisconnected; session.Error += ClientError; if (!_sessions.TryAdd(session.Guid, session)) continue; RaiseClientConnected(new ClientConnectedEventArgs(session)); session.StartListening(); } catch (ObjectDisposedException) { break; } } }
public override bool OnPacket(TcpSession session, Packet packet) { var cancel = false; foreach (var plugin in Plugins) { if (plugin.OnPacket(session, packet)) cancel = true; } return cancel; }
private void HandleChannelListRequest(TcpSession session, Packet p) { //_logger.Debug("-C_CHANLIST_REQ-"); var ack = new Packet(EChatPacket.SChannelListAck); ack.Write((uint)_channels.Count); foreach (var chan in _channels.Values) { ack.Write((byte)chan.ID); // unk ack.Write((uint)chan.ID); // id?? ack.WriteStringBuffer(chan.Name, 21, Encoding.ASCII); } session.Send(ack); }
private void HandshakeConnection(string Type, IPEndPoint ip, string username, string password, TcpSession session, Packet ack) { switch (Type) { // Success case "success": var newSession = _sessions.AddSession(AuthDatabase.Instance.GetAccountID(username), ip.Address); _logger.Info("Succesfully authenticated Username: {0} with SessionID: {1}", username, newSession.SessionID); ack.Write(newSession.SessionID); // session id ack.Write(new byte[12]); // unk ack.Write((byte)ELoginResult.OK); session.Send(ack); break; // Invalid password/username combination case "failed": _logger.Error("Failed login for Username: {0}", username); ack.Write((uint)0); ack.Write(new byte[12]); ack.Write((byte)ELoginResult.AccountError); session.Send(ack); session.StopListening(); break; // Banned account tried to login case "banned": _logger.Error("Failed login for Username: {0}", username); ack.Write((uint)0); ack.Write(new byte[12]); ack.Write((byte)ELoginResult.AccountBlocked); session.Send(ack); session.StopListening(); break; default: break; } }
private void HandleDeleteCharacter(TcpSession session, Packet p) { var slot = p.ReadByte(); //_logger.Debug("-C_SELECT_CHARACTER_REQ- Slot: {0}", slot); Player plr; if (!Players.TryGetValue(session.Guid, out plr)) { session.StopListening(); return; } var res = plr.Characters.Where(c => c.Slot == slot); if (!res.Any()) // cheater { session.StopListening(); return; } var character = plr.Characters.First(c => c.Slot == slot); if (character == null) { session.StopListening(); return; } plr.Characters.Remove(character); GameDatabase.Instance.DeleteCharacter(plr.AccountID, slot); var ack = new Packet(EGamePacket.SDeleteCharacterAck); ack.Write(slot); session.Send(ack); }
private void HandleSetDataRequest(TcpSession session, Packet p) { //_logger.Debug("-C_SETDATA_REQ-"); Player plr; if (!_players.TryGetValue(session.Guid, out plr)) { session.StopListening(); return; } p.ReadUInt16(); // unk p.ReadUInt64(); // accID plr.ServerID = p.ReadUInt16(); var channelID = p.ReadInt16(); var roomID = p.ReadInt32(); if(roomID == -1) roomID = 0; if (channelID == -1) channelID = 0; plr.Room = new Room(null, EServerType.Chat) { ID = (uint)roomID }; plr.CommunityByte = p.ReadByte(); p.ReadUInt32(); // total exp p.ReadBytes(32); // td/dm info plr.AllowCombiRequest = (EAllowCommunityRequest)p.ReadByte(); plr.AllowFriendRequest = (EAllowCommunityRequest)p.ReadByte(); plr.AllowInvite = (EAllowCommunityRequest)p.ReadByte(); plr.AllowInfoRequest = (EAllowCommunityRequest)p.ReadByte(); plr.CommunityData = p.ReadBytes(41); Channel channel; if (!_channels.TryGetValue((ushort)channelID, out channel)) return; if (plr.Channel == null && channelID > 0) // join { var ack = new Packet(EChatPacket.SChannelPlayerListInfoAck); ack.Write((uint)channel.ID); ack.Write(channel.Players.Count); foreach (var player in channel.Players.Values) ack.WriteChatUserData(player); session.Send(ack); channel.Join(plr); } else if(channelID == 0) // leave { if(plr.Channel != null) plr.Channel.Leave(plr); } else // update { var ack = new Packet(EChatPacket.SChannelPlayerListInfoAck); ack.Write((uint)channel.ID); ack.Write(channel.Players.Count); foreach (var player in channel.Players.Values) ack.WriteChatUserData(player); channel.Broadcast(ack); } }
private static void HandleLoginRequest(TcpSession session, Packet p) { var serverList = AuthDatabase.Instance.GetServerList(); var ack = new Packet(EAuthPacket.SServerlistAck); ack.Write((byte)serverList.Count); foreach (var server in serverList) { ack.Write(server.ID); ack.Write(server.Type); ack.WriteStringBuffer(server.Name, 40); ack.Write(server.PlayersOnline); ack.Write(server.PlayerLimit); ack.Write(server.IP.GetAddressBytes()); ack.Write(server.Port); } session.Send(ack); }
private void HandleFriendListRequest(TcpSession session, Packet p) { //_logger.Debug("-C_FRIENDLIST_REQ-"); Player plr; if (!_players.TryGetValue(session.Guid, out plr)) { session.StopListening(); return; } SendFriendList(plr); }
private void HandleLoginRequest(TcpSession session, Packet p) { var ip = session.Client.Client.RemoteEndPoint as IPEndPoint; var accID = p.ReadUInt64(); var nickname = p.ReadCString(); _logger.Info("-CLoginReq- User: {0} ID: {1}", nickname, accID); var ack = new Packet(EChatPacket.SLoginAck); if (accID == 0 || !ValidateSession(accID, nickname, ip.Address) || _players.GetPlayerByID(accID) != null /* prevent multiple logins! */) { ack.Write((uint)1); // error code session.Send(ack); session.StopListening(); return; } var plr = GameDatabase.Instance.GetPlayer(accID); plr.Session = session; _players.TryAdd(session.Guid, plr); ack.Write((uint)0); // error code session.Send(ack); }
private void HandleBuyItem(TcpSession session, Packet p) { int count = p.ReadByte(); Player player; if (!Players.TryGetValue(session.Guid, out player)) { session.StopListening(); return; } var buyTime = DateTime.Now; var itemsToBuy = new List<Tuple<Item, ShopItem>>(); uint penCost = 0; uint apCost = 0; for (var i = 0; i < count; i++) { var item = new Item(); var mixedID = p.ReadBytes(4); item.Category = mixedID[0]; item.SubCategory = mixedID[1]; item.ItemID = BitConverter.ToUInt16(mixedID, 2); item.ProductID = p.ReadByte(); item.EffectID = p.ReadUInt32(); item.PurchaseTime = HelperUtils.GetUnixTimestamp(buyTime); var shopItem = GameDatabase.Instance.GetShopItem(item.Category, item.SubCategory, item.ItemID, item.ProductID); if (shopItem == null) // hacker { Logger.Error("-CBuyItemReq FAILED(HAX)- ItemID: {0} Category: {1} SubCategory: {2} Type: {3} EffectID: {4}", item.ItemID, item.Category, item.SubCategory, item.ProductID, item.EffectID); session.StopListening(); return; } item.Energy = shopItem.Energy; item.ExpireTime = (shopItem.Time == -1) ? -1 : HelperUtils.GetUnixTimestamp(buyTime.AddSeconds(shopItem.Time)); penCost += shopItem.Price; apCost += shopItem.Cash; itemsToBuy.Add(new Tuple<Item, ShopItem>(item, shopItem)); } Packet ack; if (player.PEN < penCost || player.AP < apCost) { ack = new Packet(EGamePacket.SBuyItemAck); ack.Write((byte)EBuyItemResult.NotEnoughMoney); session.Send(ack); return; } _pluginManager.OnBuyItem(player, itemsToBuy.Select(e => e.Item1).ToList()); foreach (var tuple in itemsToBuy) { var item = tuple.Item1; var shopItem = tuple.Item2; //_logger.Debug("-C_BUY_ITEM_REQ- ItemID: {0} Category: {1} SubCategory: {2} Type: {3} EffectID: {4}", item.ItemID, item.Category, item.SubCategory, item.ProductID, item.EffectID); player.PEN -= shopItem.Price; player.AP -= shopItem.Cash; var id = GameDatabase.Instance.CreateItem(item, player.AccountID); if (id == 0) { ack = new Packet(EGamePacket.SBuyItemAck); ack.Write((byte)EBuyItemResult.DBError); session.Send(ack); continue; } item.ID = id; item.SetupAPWeapon(); player.AddItem(item); ack = new Packet(EGamePacket.SBuyItemAck); ack.Write((byte)EBuyItemResult.OK); ack.Write(item.Category); ack.Write(item.SubCategory); ack.Write(item.ItemID); ack.Write(item.ProductID); ack.Write(item.EffectID); ack.Write(item.ID); session.Send(ack); } player.UpdateMoney(); }
private void HandleRefundItem(TcpSession session, Packet p) { var itemID = p.ReadUInt64(); Player player; if (!Players.TryGetValue(session.Guid, out player)) { session.StopListening(); return; } var itm = player.Inventory.FirstOrDefault(i => i.ID == itemID); if (itm == null) { session.StopListening(); return; } player.Inventory.Remove(itm); GameDatabase.Instance.RemoveItem(itemID); var ack = new Packet(EGamePacket.SRefundItemAck); ack.Write((byte)0); ack.Write(itemID); session.Send(ack); player.PEN += itm.SellPrice; player.UpdateMoney(); }
private void HandleChannelLeave(TcpSession session, Packet p) { //_logger.Debug("-C_CHAN_LEAVE_REQ-"); Player plr; if (!Players.TryGetValue(session.Guid, out plr)) { session.StopListening(); return; } if (plr.Channel == null) return; plr.Channel.Leave(plr); var ack = new Packet(EGamePacket.SResultAck); ack.Write((uint)8); session.Send(ack); }
private void HandleChannelInformation(TcpSession session, Packet p) { var t = p.ReadByte(); //_logger.Debug("-C_CHAN_INFO_REQ- Type: {0}", t); switch (t) { case 5: // channel info var ack = new Packet(EGamePacket.SChannelInfoAck); ack.Write((ushort)Channels.Count); foreach (var channel in Channels.Values) { ack.Write(channel.ID); ack.Write((ushort)channel.Players.Count); } session.Send(ack); break; case 4: // room info SendRoomList(session); break; case 3: // ?? break; } }
async private void HandleChannelEnter(TcpSession session, Packet p) { var id = p.ReadUInt32(); //_logger.Debug("-C_CHAN_ENTER_REQ- ID: {0}", id); Player plr; if (!Players.TryGetValue(session.Guid, out plr)) { session.StopListening(); return; } Channel channel; if (!Channels.TryGetValue((ushort)id, out channel)) return; channel.Join(plr); var ack = new Packet(EGamePacket.SResultAck); ack.Write((uint)5); session.Send(ack); ack = new Packet(EGamePacket.SCashUpdateAck); ack.Write(plr.PEN); ack.Write(plr.AP); session.Send(ack); //if (plr.ConnectionType == 0x06) // Alice.SendMessageTo(plr.AccountID, "Mit deinem Router ist es leider nicht möglich hier zu spielen :("); //else if (plr.ConnectionType == 0x04) // Alice.SendMessageTo(plr.AccountID, "Mit deinem Router kannst du leider nur einen Raum erstellen :("); await Task.Delay(1000); SendRoomList(session); }
private void HandleTimeSync(TcpSession session, Packet p) { var time = p.ReadUInt32(); var ts = DateTime.Now - Process.GetCurrentProcess().StartTime; var ack = new Packet(EGamePacket.STimeSyncAck); ack.Write(time); ack.Write((uint)ts.TotalMilliseconds); session.Send(ack); Player plr; if (!Players.TryGetValue(session.Guid, out plr)) return; plr.Ping = time - plr.LastSyncTime - 3000; plr.LastSyncTime = time; }
private void HandleAvatarChange(TcpSession session, Packet p) { // TODO //ulong accountID = p.ReadUInt64(); ////Costume Ids //for (int i = 0; i < 7; i++) // p.ReadInt32(); ////Skill ids (Action) //for (int i = 0; i < 2; i++) // p.ReadInt32(); ////Weapon Ids //for (int i = 0; i < 3; i++) // p.ReadInt32(); //_logger.Debug("-C_AVATAR_CHANGE_REQ-"); Player plr; if (!Players.TryGetValue(session.Guid, out plr)) { session.StopListening(); return; } var data = p.ReadToEnd(); var ack = new Packet(EGamePacket.SAvatarChangeAck); ack.Write(data); plr.Room.Broadcast(ack, plr.AccountID) ; }
private void HandleChatMessage(TcpSession session, Packet p) { var channelID = p.ReadUInt32(); var msgSize = p.ReadUInt16(); var msg = Encoding.ASCII.GetString(p.ReadBytes(msgSize)); //_logger.Debug("-C_MESSAGE_REQ- ChannelID: {0} Msg: {1}", channelID, msg); Player plr; if (!_players.TryGetValue(session.Guid, out plr)) { session.StopListening(); return; } if (plr.Channel == null) return; var ack = new Packet(EChatPacket.SMessageAck); ack.Write(plr.AccountID); ack.Write((uint)plr.Channel.ID); ack.Write((ushort)msg.Length); ack.Write(msg); plr.Channel.Broadcast(ack); }
private void HandleRepairItem(TcpSession session, Packet p) { var itemID = p.ReadUInt64(); Player player; if (!Players.TryGetValue(session.Guid, out player)) { session.StopListening(); return; } var itm = player.Inventory.FirstOrDefault(i => i.ID == itemID); if (itm == null) { session.StopListening(); return; } itm.Energy = itm.MaxEnergy; var ack = new Packet(EGamePacket.SRepairItemAck); ack.Write((byte)0); ack.Write(itemID); session.Send(ack); player.PEN -= 0; // repair cost player.UpdateMoney(); }
private void HandleCombiListRequest(TcpSession session, Packet p) { //_logger.Debug("-C_COMBILIST_REQ-"); Player plr; if (!_players.TryGetValue(session.Guid, out plr)) return; var ack = new Packet(EChatPacket.SCombiListAck); ack.Write(plr.AccountID); ack.Write((uint)0); session.Send(ack); }
private void HandleRefreshEQItems(TcpSession session, Packet p) { Player plr; if (!Players.TryGetValue(session.Guid, out plr)) { session.StopListening(); return; } var items = plr.Inventory; var res = items.Where(item => item.TimeLeft == 0); var ls = res as IList<Item> ?? res.ToList(); //_logger.Debug("-C_REFRESH_EQ_ITEMS_REQ- Count: {0}", ls.Count); var ack = new Packet(EGamePacket.SRefreshInvalidateEQItemsAck); ack.Write((byte)ls.Count()); foreach (var item in ls) { ack.Write(item.ID); } session.Send(ack); }
private void HandleGetData(TcpSession session, Packet p) { var accID = p.ReadUInt64(); //_logger.Debug("-C_GET_DATA_REQ- ID: {0}", accID); var ack = new Packet(EChatPacket.SGetDataAck); ack.Write(accID); // accid Player sender; if (!_players.TryGetValue(session.Guid, out sender)) { session.StopListening(); return; } var plr = _players.GetPlayerByID(accID); if(plr == null) { ack.Write((byte)0x01); session.Send(ack); return; } ack.Write((byte)0x00); // result code ack.WriteChatUserData(plr, true); session.Send(ack); }
private void HandleAddFriend(TcpSession session, Packet p) { var accID = p.ReadUInt64(); var nickname = p.ReadCStringBuffer(31); //_logger.Debug("-C_ADD_FRIEND_REQ- ID: {0} Nickname: {1}", accID, nickname); Player plr; if (!_players.TryGetValue(session.Guid, out plr)) { session.StopListening(); return; } var ack = new Packet(EChatPacket.SAddFriendAck); ack.Write(accID); var plrToRequest = _players.GetPlayerByID(accID); if (plrToRequest == null) { ack.Write((byte)EAddFriendResult.DoenstExist); } else { var friend = plr.FriendList.FirstOrDefault(f => f.ID == accID); if (friend == null) { plr.FriendList.Add(new Friend() { ID = accID, Nickname = nickname, Accepted = false }); GameDatabase.Instance.AddFriend(plr.AccountID, accID, nickname); SendBRSFriendNotify(plr, plrToRequest, EFriendNotify.Request); ack.Write((byte)EAddFriendResult.MadeRequest); } else { if (friend.Accepted) ack.Write((byte)EAddFriendResult.AlreadyInList); else ack.Write((byte)EAddFriendResult.AlreadyRequested); } } ack.WriteStringBuffer(nickname, 31); session.Send(ack); }
private void HandleRemoveDeny(TcpSession session, Packet p) { var accID = p.ReadUInt64(); var nickname = p.ReadCStringBuffer(31); //_logger.Debug("-C_REMOVE_DENY_REQ- ID: {0} Nickname: {1}", accID, nickname); Player plr; if (!_players.TryGetValue(session.Guid, out plr)) { session.StopListening(); return; } var ack = new Packet(EChatPacket.SRemoveDenyAck); if (plr.DenyList.ContainsKey(accID)) { plr.DenyList.Remove(accID); GameDatabase.Instance.RemoveDeny(plr.AccountID, accID); ack.Write((byte)EDenyResult.OK); } else { ack.Write((byte)EDenyResult.Failed2); } ack.Write(accID); ack.WriteStringBuffer(nickname, 31); session.Send(ack); SendDenyList(plr); }
private void HandleBRSFriendNotify(TcpSession session, Packet p) { var accID = p.ReadUInt64(); var accepted = p.ReadInt32() > 0; var nickname = p.ReadCStringBuffer(31); //_logger.Debug("-C_ADD_FRIEND_REQ- ID: {0} Nickname: {1}", accID, nickname); Player plr; if (!_players.TryGetValue(session.Guid, out plr)) { session.StopListening(); return; } Packet ack; var plrFromRequest = _players.GetPlayerByID(accID); if (plrFromRequest == null) return; if (accepted) { SendBRSFriendNotify(plr, plrFromRequest, EFriendNotify.Accepted); SendBRSFriendNotify(plrFromRequest, plr, EFriendNotify.Accepted); } else { SendBRSFriendNotify(plr, plrFromRequest, EFriendNotify.Denied); SendBRSFriendNotify(plr, plrFromRequest, EFriendNotify.DeleteRelation); SendBRSFriendNotify(plrFromRequest, plr, EFriendNotify.DeleteRelation); } var friend = plrFromRequest.FriendList.FirstOrDefault(f => f.ID == plr.AccountID); if (friend == null) return; if (accepted) { friend.Accepted = true; GameDatabase.Instance.UpdateFriend(plrFromRequest.AccountID, friend.ID, friend.Accepted); var newFriend = new Friend() { ID = plrFromRequest.AccountID, Nickname = plrFromRequest.Nickname, Accepted = true }; plr.FriendList.Add(newFriend); GameDatabase.Instance.AddFriend(plr.AccountID, newFriend.ID, newFriend.Nickname, newFriend.Accepted); } else { plrFromRequest.FriendList.Remove(friend); GameDatabase.Instance.RemoveFriend(plrFromRequest.AccountID, friend.ID); } }
private void HandleWhisper(TcpSession session, Packet p) { var accID = p.ReadUInt64(); var unk1 = p.ReadUInt32(); var unk2 = p.ReadByte(); var msgSize = p.ReadUInt16(); var msg = Encoding.ASCII.GetString(p.ReadBytes(msgSize)); _logger.Debug("-C_WHISPER_REQ- accID: {0} unk1: {1} unk2: {2} Size: {3} Msg: {4}", accID, unk1, unk2, msgSize, msg); var target = _players.GetPlayerByID(accID); Player plr; if (!_players.TryGetValue(session.Guid, out plr)) { session.StopListening(); return; } if (target == null) return; var ack = new Packet(EChatPacket.SWhisperAck); ack.Write(plr.AccountID); ack.Write(unk1); ack.Write(unk2); ack.Write(msgSize); ack.Write(msg); target.Session.Send(ack); }
private void HandleNATInfo(TcpSession session, Packet p) { var ip = (IPEndPoint) session.Client.Client.RemoteEndPoint; Player plr; if (!Players.TryGetValue(session.Guid, out plr)) { session.StopListening(); return; } plr.PrivateIP = p.ReadUInt32(); plr.PrivatePort = p.ReadUInt16(); plr.PublicIP = p.ReadUInt32(); plr.PublicPort = p.ReadUInt16(); // ignore public stuff from client plr.PublicIP = (uint)ip.Address.Address; plr.PublicPort = plr.PrivatePort; plr.NATUnk = p.ReadUInt16(); plr.ConnectionType = p.ReadByte(); if (ip.Address.ToString() == "127.0.0.1") plr.ConnectionType = 1; if (plr.ConnectionType == 6) plr.ConnectionType = 4; Logger.Info("-CNATInfoReq- NATUnk: {0} Type: {1}", plr.NATUnk, plr.ConnectionType); }
private void HandleAuthRequest(TcpSession session, Packet p) { var ack = new Packet(EAuthPacket.SAuthAck); var ip = session.Client.Client.RemoteEndPoint as IPEndPoint; var username = p.ReadCStringBuffer(13); var password = p.ReadCString(); // SHA256 encoding password = SHA256.ComputeHash(password); //TODO: Implement IP logging options to MySQL after failed handshaking attempts String[] userDetails = { username, password }; // Update user's lastIP connected in auth string ip_str = ip.ToString(); AuthDatabase.Instance.UpdateLastIP(ip_str,userDetails[0]); // Check if account exists if (!AuthDatabase.Instance.ValidateAccount(userDetails[0], userDetails[1])) { HandshakeConnection("failed", ip, userDetails[0], userDetails[1], session, ack); return; } // Check if account is banned if (AuthDatabase.Instance.IsAccountBanned(userDetails[0])) { HandshakeConnection("banned", ip, userDetails[0], userDetails[1], session, ack); return; } // Login successfully HandshakeConnection("success", ip, userDetails[0], userDetails[1], session, ack); }
private void HandleChannelLeave(TcpSession session, Packet p) { //_logger.Debug("-C_CHAN_LEAVE_REQ-"); Player plr; if (_players.TryGetValue(session.Guid, out plr)) return; session.StopListening(); }
private void HandleChannelEnter(TcpSession session, Packet p) { var chanName = p.ReadCString(); //_logger.Debug("-C_CHANENTER_REQ- Name: {0}", chanName); Player plr; if (!_players.TryGetValue(session.Guid, out plr)) { session.StopListening(); return; } var chan = _channels.GetChannelByName(chanName); if (chan.ID == 0) return; var ack = new Packet(EChatPacket.SChannelEnterAck); ack.Write((uint)chan.ID); session.Send(ack); }
private void HandleCreateCharacter(TcpSession session, Packet p) { var slot = p.ReadByte(); var avatar = p.ReadUInt32(); //_logger.Debug("-C_CREATE_CHARACTER_REQ- Slot: {0} Avatar: {1}", slot, avatar); Player plr; if (!Players.TryGetValue(session.Guid, out plr)) { session.StopListening(); return; } if (plr.Characters.Count >= 3) // no cheating my friend! { session.StopListening(); return; } var character = new Character {Slot = slot, Avatar = avatar}; plr.Characters.Add(character); GameDatabase.Instance.CreateCharacter(plr.AccountID, slot, avatar); var ack = new Packet(EGamePacket.SCreateCharacterAck); ack.Write(slot); ack.Write(avatar); ack.Write((byte)1); // SKILL COUNT ack.Write((byte)3); // WEAPON COUNT session.Send(ack); }