public static async Task OnPlayerMovePrototype(PacketHandlerContext c) { var request = new MSG_MOVE_GENERIC(c.Packet, c.Client.Build); var character = c.GetCharacter(); // Always trust the client (for now..) character.Position.X = request.MapX; character.Position.Y = request.MapY; character.Position.Z = request.MapZ; character.Position.Orientation = request.MapO; foreach (var client in c.World.Connections) { if (!client.IsInWorld) { continue; } if (client.CharacterId == c.Client.CharacterId) { continue; } // Put that in a queue and dont await it? await client.SendPacket(new MovementUpdate(character, request, c.Opcode, client.Build)); } }
public static async Task OnCharacterCreate(PacketHandlerContext c) { byte status; var character = CharacterFactory.Create(new CMSG_CHAR_CREATE(c.Packet)); if (!c.World.CharacterService.AddCharacter(character)) { c.Client.Log($"Could not add created character {character.Name} - {character.Id}.", LogLevel.Warning); status = c.Client.Build switch { ClientBuild.Vanilla => (byte)CharacterHandlerCode_Vanilla.CHAR_CREATE_ERROR, ClientBuild.TBC => (byte)CharacterHandlerCode_TBC.CHAR_CREATE_ERROR, _ => throw new NotImplementedException($"OnCharacterCreate(build: {c.Client.Build})"), }; } else { var account = c.AccountService.GetAccount(c.Client.Identifier); account.Characters.Add(character.Id); c.AccountService.UpdateAccount(account); status = c.Client.Build switch { ClientBuild.Vanilla => (byte)CharacterHandlerCode_Vanilla.CHAR_CREATE_SUCCESS, ClientBuild.TBC => (byte)CharacterHandlerCode_TBC.CHAR_CREATE_SUCCESS, _ => throw new NotImplementedException($"OnCharacterCreate(build: {c.Client.Build})"), }; } await c.Client.SendPacket(new SMSG_CHAR_CREATE(status)); }
public static Task OnSetSelection(PacketHandlerContext c) { var request = new CMSG_SET_SELECTION(c.Packet); c.Client.Player.TargetId = request.TargetId; return(Task.CompletedTask); }
public static async Task OnCharacterDelete(PacketHandlerContext c) { var request = new CMSG_CHAR_DELETE(c.Packet); var account = c.AccountService.GetAccount(c.Client.Identifier); // Removing character of other account if (!account.Characters.Contains(request.CharacterId)) { await c.Client.SendPacket(GetFailedPacket(c.Client.Build)); return; } if (!c.World.CharacterService.DeleteCharacter(request.CharacterId)) { await c.Client.SendPacket(GetFailedPacket(c.Client.Build)); return; } account.Characters.Remove(request.CharacterId); c.AccountService.UpdateAccount(account); var status = c.Client.Build switch { ClientBuild.Vanilla => (byte)CharacterHandlerCode_Vanilla.CHAR_DELETE_SUCCESS, ClientBuild.TBC => (byte)CharacterHandlerCode_TBC.CHAR_DELETE_SUCCESS, _ => throw new NotImplementedException($"OnCharacterDelete(build: {c.Client.Build})"), }; await c.Client.SendPacket(new SMSG_CHAR_DELETE(status)); }
public static async Task OnRealmSplit(PacketHandlerContext c) { using var reader = new PacketReader(c.Packet); var decision = reader.ReadUInt32(); await c.Client.SendPacket(new SMSG_REALM_SPLIT(decision)); }
public static async Task OnCharacterEnum(PacketHandlerContext c) { var account = c.AccountService.GetAccount(c.Client.Identifier); var characters = new List <Character>(); foreach (var id in account.Characters) { var character = c.World.CharacterService.GetCharacter(id); if (character is null) { c.Client.Log($"Could not find character with id {id} from player {account.Identifier}.", LogLevel.Warning); continue; } characters.Add(character); } ServerPacketBase <Opcode> characterEnum = c.Client.Build switch { ClientBuild.Vanilla => new SMSG_CHAR_ENUM_VANILLA(characters), ClientBuild.TBC => new SMSG_CHAR_ENUM_TBC(characters), _ => throw new NotImplementedException($"OnCharacterEnum(build: {c.Client.Build})"), }; await c.Client.SendPacket(characterEnum); }
public static async Task OnCastSpell(PacketHandlerContext c) { var request = new CMSG_CAST_SPELL(c.Packet); c.Client.Log($"Casting: {request.SpellId}"); var unit = c.World.Creatures.SingleOrDefault(creature => creature.ID == request.TargetId); if (unit is null) { c.Client.Log($"Could not find unit: {request.TargetId}"); return; } else { c.Client.Log($"{unit.ID} - {unit.Model}"); } // ???? //await args.Client.SendPacket(SMSG_CAST_RESULT.Success(request.SpellId)); // Opcode.SMSG_SPELLLOGEXECUTE //m_spellLogData.Initialize(SMSG_SPELLLOGEXECUTE); //m_spellLogData << m_spell->GetCaster()->GetPackGUID(); //m_spellLogData << uint32(m_spell->m_spellInfo->Id); //m_spellLogDataEffectsCounterPos = m_spellLogData.wpos(); //m_spellLogData << uint32(0); //placeholder //m_spellLogDataEffectsCounter = 0; }
public static async Task OnAttackSwing(PacketHandlerContext c) { var request = new CMSG_ATTACKSWING(c.Packet); // TODO: Also check players var unit = c.World.Creatures.SingleOrDefault(creature => creature.ID == request.Guid); if (unit is null) { c.Client.Log($"Could not find unit: {request.Guid}"); return; } // TODO: Checks if can attack, range check etc. await c.Client.SendPacket(new SMSG_ATTACKSTART(c.Client.CharacterId, unit.ID)); // TODO: Do this somewhere else (Add AttackController to Player??) _ = Task.Run(async() => { c.Client.Log("Attacking...", LogLevel.Information); for (var i = 0; i < 500; i++) { await Task.Delay(500); await c.Client.SendPacket(new SMSG_ATTACKERSTATEUPDATE(c.Client.CharacterId, unit.ID)); } }); }
public static Task OnZoneUpdate(PacketHandlerContext c) { var request = new CMSG_ZONEUPDATE(c.Packet); c.Client.Log($"{c.Client.Player.Name} entered {request.NewZone}"); c.GetCharacter().Position.Zone = request.NewZone; return(Task.CompletedTask); }
public static async Task OnPlayerLogoutRequested(PacketHandlerContext c) { await c.Client.SendPacket(SMSG_LOGOUT_COMPLETE.Success()); c.Client.CharacterId = default; c.Client.Player = null; // TODO: Remove from other clients }
public static async Task OnNameQuery(PacketHandlerContext c) { var request = new CMSG_NAME_QUERY(c.Packet); var character = c.World.CharacterService.GetCharacter(request.CharacterID); if (character is null) { return; } await c.Client.SendPacket(new SMSG_NAME_QUERY_RESPONSE(character, c.Client.Build)); }
public static async Task OnMessageChat(PacketHandlerContext c) { var request = new CMSG_MESSAGECHAT(c.Packet); // debugging stuff :D if (request.Message.StartsWith(".spawn")) { var spawnId = int.Parse(request.Message.Split(" ")[1]); var creature = new Creature { Model = spawnId, Position = c.GetCharacter().Position.Copy() }; await c.World.SpawnCreature(creature); } }
public static async Task OnAttackSwing(PacketHandlerContext c) { var request = new CMSG_ATTACKSWING(c.Packet); // TODO: Also check players var unit = c.World.Creatures.SingleOrDefault(creature => creature.ID == request.Guid); if (unit is null) { c.Client.Log($"Could not find unit: {request.Guid}"); return; } await c.Client.AttackController.StartAttacking(unit); }
public static async Task OnClientAuthenticationSession(PacketHandlerContext c) { var request = CMSG_AUTH_SESSION.Read(c.Packet); var build = (int)request.Build; if (c.Client.Build != build) { c.Client.Log($"Expected build {c.Client.Build} but is {build}.", LogLevel.Warning); c.Client.Build = build; } var session = c.AccountService.GetSession(request.Identifier); if (session is null) { // return [SMSG_AUTH_RESPONSE, 21] throw new ArgumentException($"No user with name {request.Identifier} found in db."); } ////: if server is full and NOT GM return [SMSG_AUTH_RESPONSE, 21] ////: if player is already connected return [SMSG_AUTH_RESPONSE, 13] using var sha = new SHA1CryptoServiceProvider(); var calculatedDigest = sha.ComputeHash( Encoding.ASCII.GetBytes(request.Identifier) .Concat(new byte[] { 0, 0, 0, 0 }) .Concat(BitConverter.GetBytes(request.Seed)) .Concat(SMSG_AUTH_CHALLENGE.AuthSeed) .Concat(session.SessionKey) .ToArray()); if (!calculatedDigest.SequenceEqual(request.Digest)) { //return [SMSG_AUTH_RESPONSE, 21] throw new InvalidOperationException("Wrong digest SMSG_AUTH_RESPONSE"); } c.Client.HeaderCrypt = HeaderCryptFactory.Create(session.SessionKey, build); c.Client.Identifier = request.Identifier; await c.Client.SendPacket(new SMSG_AUTH_RESPONSE(build)); }
public static async Task GroupInvite(PacketHandlerContext c) { var request = new CMSG_GROUP_INVITE(c.Packet); var recipient = c.GetCharacter(request.Membername); if (recipient is null) { c.Client.Log($"Could not find player {request.Membername}", LogLevel.Warning); return; // TODO Send response to sender } var recipientClient = c.World.Connections.SingleOrDefault(c => c.CharacterId == recipient.Id); if (recipientClient is null) { // This should only rarely happen -> critical c.Client.Log($"Could not find WorldClient of player {request.Membername}", LogLevel.Critical); return; // TODO Send response to sender } await recipientClient.SendPacket(new SMSG_GROUP_INVITE(c.GetCharacter().Name)); }
public static async Task OnMessageChat(PacketHandlerContext c) { var request = new CMSG_MESSAGECHAT(c.Packet); // debugging stuff :D if (request.Message == ".update") { if (c.IsVanilla()) { await c.Client.SendPacket(SMSG_UPDATE_OBJECT_VANILLA.UpdateValues(c.World.Creatures)); } return; } if (request.Message.StartsWith(".spawn")) { var spawnId = int.Parse(request.Message.Split(" ")[1]); var creature = new Creature { Model = spawnId, Position = c.GetCharacter().Position.Copy() }; await c.World.SpawnCreature(creature); } }
public void HandlePacket(PacketHandlerContext ctx) { /*if(!ctx.HasUser) * return; * * if(!long.TryParse(ctx.Args.ElementAtOrDefault(1), out long userId) || ctx.User.UserId != userId) * return; * * string channelName = ctx.Args.ElementAtOrDefault(2)?.ToLowerInvariant(); * if(!string.IsNullOrWhiteSpace(channelName)) * return; * * IChannel channel = ctx.User.GetChannels().FirstOrDefault(c => c.Name.ToLowerInvariant() == channelName); * if(channel == null || !channel.CanType(ctx.User)) * return; * * ctx.Session.LastChannel = channel; * * ChannelTyping info = channel.RegisterTyping(ctx.User); * if(info == null) * return; * * channel.SendPacket(new TypingPacket(channel, info));*/ }
public static bool IsTBC(this PacketHandlerContext c) => c.Client.Build == ClientBuild.TBC;
public static Character GetCharacter(this PacketHandlerContext c) => c.World.CharacterService.GetCharacter(c.Client.CharacterId);
public static async Task OnPlayerLogin(PacketHandlerContext c) { var request = new CMSG_PLAYER_LOGIN(c.Packet); var character = c.GetCharacter(request.CharacterID); var account = c.AccountService.GetAccount(c.Client.Identifier); // Login with a deleted character or a character from another account. // TODO: Split for different log messages. if (character is null || !account.Characters.Contains(character.Id)) { c.Client.Log( $"{account.Identifier} tried to login with a deleted character or a character from another account.", LogLevel.Warning); return; } c.Client.Log($"Player logged in with char {character.Name}"); if (c.IsTBC()) { await c.SendPacket <MSG_SET_DUNGEON_DIFFICULTY>(); } await c.Client.SendPacket(new SMSG_LOGIN_VERIFY_WORLD(character)); await c.SendPacket <SMSG_ACCOUNT_DATA_TIMES>(); if (c.IsTBC()) { await c.SendPacket <SMSG_FEATURE_SYSTEM_STATUS>(); } await c.Client.SendPacket(new SMSG_EXPECTED_SPAM_RECORDS(Enumerable.Empty <string>())); if (c.IsVanilla()) { await c.Client.SendPacket(new SMSG_MESSAGECHAT(character.Id, MessageOfTheDay)); } else if (c.IsTBC()) { await c.Client.SendPacket(new SMSG_MOTD(MessageOfTheDay)); } // await args.Client.SendPacket(new SMSG_NAME_QUERY_RESPONSE(character, args.Client.Build)); // if (GUILD) -> SMSG_GUILD_EVENT if (character.Stats.Life == 0) { await c.SendPacket <SMSG_CORPSE_RECLAIM_DELAY>(); } await c.SendPacket <SMSG_SET_REST_START>(); await c.Client.SendPacket(new SMSG_BINDPOINTUPDATE(character)); await c.SendPacket <SMSG_TUTORIAL_FLAGS>(); if (c.IsTBC()) { await c.SendPacket <SMSG_INSTANCE_DIFFICULTY>(); } await c.Client.SendPacket(new SMSG_INITIAL_SPELLS(character.Spells)); // SMSG_SEND_UNLEARN_SPELLS await c.Client.SendPacket(new SMSG_ACTION_BUTTONS(character.ActionBar)); await c.Client.SendPacket(new SMSG_INITIALIZE_FACTIONS(ClientBuild.Vanilla)); // BUG?? await c.SendPacket <SMSG_LOGIN_SETTIMESPEED>(); // await args.Client.SendPacket(new SMSG_TRIGGER_CINEMATIC(CinematicID.NightElf)); c.Client.CharacterId = character.Id; await c.Client.SendPacket(SMSG_UPDATE_OBJECT.CreateOwnPlayerObject(character, c.Client.Build, out var player)); c.Client.Player = player; // TODO: Implement for TBC if (c.IsVanilla()) { // Initially spawn all creatures foreach (var unit in c.World.Creatures) { // TODO: Add range check await c.Client.SendPacket(SMSG_UPDATE_OBJECT_VANILLA.CreateUnit(unit)); } } await c.World.SpawnPlayer(character, c.Client.Build); // if (GROUP) -> SMSG_GROUP_LIST // if Vanilla // SMSG_FRIEND_LIST // SMSG_IGNORE_LIST // if TBC // SMSG_CONTACT_LIST if (c.IsTBC()) { await c.SendPacket <SMSG_TIME_SYNC_REQ>(); } // SMSG_ITEM_ENCHANT_TIME_UPDATE // SMSG_ITEM_TIME_UPDATE // SMSG_FRIEND_STATUS }
public static Task OnAttackStop(PacketHandlerContext c) { c.Client.AttackController.StopAttacking(); return(Task.CompletedTask); }
public static async Task OnQueryTime(PacketHandlerContext c) => await c.Client.SendPacket(new SMSG_QUERY_TIME_RESPONSE());
public static Character GetCharacter(this PacketHandlerContext c, string name) => c.World.CharacterService.GetCharacter(name);
public static async Task OnPing(PacketHandlerContext c) { var request = new CMSG_PING(c.Packet); await c.Client.SendPacket(new SMSG_PONG(request.Latency)); }
public static async Task SendPacket <T>(this PacketHandlerContext c) where T : ServerPacketBase <Opcode>, new() => await c.Client.SendPacket(new T());
public static Task UpdateAccountData(PacketHandlerContext c) { var request = new CMSG_UPDATE_ACCOUNT_DATA(c.Packet); return(Task.CompletedTask); }
public static Character GetCharacter(this PacketHandlerContext c, ulong id) => c.World.CharacterService.GetCharacter(id);
public static async Task OnSetSheathed(PacketHandlerContext c) { var request = new CMSG_SETSHEATHED(c.Packet); c.Client.Log(request.Sheated.ToString()); }
public static bool IsVanilla(this PacketHandlerContext c) => c.Client.Build == ClientBuild.Vanilla;
public static async Task OnAttackStop(PacketHandlerContext c) { // AttackController.Stop??? }