public static async void CharacterDelete(ClientPacketFragment fragment, Session session) { string account = fragment.Payload.ReadString16L(); uint characterSlot = fragment.Payload.ReadUInt32(); if (account != session.Account) { session.SendCharacterError(CharacterError.Delete); return; } var cachedCharacter = session.CachedCharacters.SingleOrDefault(c => c.SlotId == characterSlot); if (cachedCharacter == null) { session.SendCharacterError(CharacterError.Delete); return; } // TODO: check if character is already pending removal session.LoginSession.EnqueueSend(new GameMessageCharacterDelete()); DatabaseManager.Character.DeleteOrRestore(Time.GetUnixTime() + 3600ul, cachedCharacter.Guid.Low); var result = await DatabaseManager.Character.GetByAccount(session.Id); session.UpdateCachedCharacters(result); session.WorldSession.EnqueueSend(new GameMessageCharacterList(result, session.Account)); }
public static void CharacterEnterWorld(ClientPacketFragment fragment, Session session) { ObjectGuid guid = fragment.Payload.ReadGuid(); string account = fragment.Payload.ReadString16L(); if (account != session.Account) { session.SendCharacterError(CharacterError.EnterGameCharacterNotOwned); return; } var cachedCharacter = session.CachedCharacters.SingleOrDefault(c => c.Guid.Full == guid.Full); if (cachedCharacter == null) { session.SendCharacterError(CharacterError.EnterGameCharacterNotOwned); return; } session.CharacterRequested = cachedCharacter; // this isn't really that necessary since ACE doesn't split login/world to multiple daemons, handle it anyway byte[] connectionKey = new byte[sizeof(ulong)]; RandomNumberGenerator.Create().GetNonZeroBytes(connectionKey); session.WorldConnectionKey = BitConverter.ToUInt64(connectionKey, 0); string[] sessionIPAddress = session.EndPoint.Address.ToString().Split('.'); session.LoginSession.EnqueueSend(new PacketOutboundReferral(session.WorldConnectionKey, sessionIPAddress)); session.State = SessionState.WorldLoginRequest; }
public static async void CharacterDelete(ClientPacketFragment fragment, Session session) { string account = fragment.Payload.ReadString16L(); uint characterSlot = fragment.Payload.ReadUInt32(); if (account != session.Account) { session.SendCharacterError(CharacterError.Delete); return; } var cachedCharacter = session.CachedCharacters.SingleOrDefault(c => c.SlotId == characterSlot); if (cachedCharacter == null) { session.SendCharacterError(CharacterError.Delete); return; } // TODO: check if character is already pending removal var characterDelete = new ServerPacket(0x0B, PacketHeaderFlags.EncryptedChecksum); var characterDeleteFragment = new ServerPacketFragment(9, GameMessageOpcode.CharacterDelete); characterDelete.Fragments.Add(characterDeleteFragment); NetworkManager.SendPacket(ConnectionType.Login, characterDelete, session); DatabaseManager.Character.DeleteOrRestore(Time.GetUnixTime() + 3600ul, cachedCharacter.Guid.Low); var result = await DatabaseManager.Character.GetByAccount(session.Id); AuthenticationHandler.CharacterListSelectCallback(result, session); }
public static void HandleGameAction(ClientPacketFragment fragement, Session session) { uint sequence = fragement.Payload.ReadUInt32(); uint opcode = fragement.Payload.ReadUInt32(); PacketManager.HandleGameAction((GameActionOpcode)opcode, fragement, session); }
public static void CharacterRestore(ClientPacketFragment fragment, Session session) { ObjectGuid guid = fragment.Payload.ReadGuid(); var cachedCharacter = session.CachedCharacters.SingleOrDefault(c => c.Guid.Full == guid.Full); if (cachedCharacter == null) { return; } bool isAvailable = DatabaseManager.Character.IsNameAvailable(cachedCharacter.Name); if (!isAvailable) { SendCharacterCreateResponse(session, CharacterGenerationVerificationResponse.NameInUse); /* Name already in use. */ return; } DatabaseManager.Character.DeleteOrRestore(0, guid.Low); var characterRestore = new ServerPacket(0x0B, PacketHeaderFlags.EncryptedChecksum); var characterRestoreFragment = new ServerPacketFragment(9, GameMessageOpcode.CharacterRestoreResponse); characterRestoreFragment.Payload.Write(1u /* Verification OK flag */); characterRestoreFragment.Payload.WriteGuid(guid); characterRestoreFragment.Payload.WriteString16L(cachedCharacter.Name); characterRestoreFragment.Payload.Write(0u /* secondsGreyedOut */); characterRestore.Fragments.Add(characterRestoreFragment); NetworkManager.SendPacket(ConnectionType.Login, characterRestore, session); }
public static Appearance FromFragment(ClientPacketFragment fragment) { Appearance appearance = new Appearance() { Eyes = fragment.Payload.ReadUInt32(), Nose = fragment.Payload.ReadUInt32(), Mouth = fragment.Payload.ReadUInt32(), HairColor = fragment.Payload.ReadUInt32(), EyeColor = fragment.Payload.ReadUInt32(), HairStyle = fragment.Payload.ReadUInt32(), HeadgearStyle = fragment.Payload.ReadUInt32(), HeadgearColor = fragment.Payload.ReadUInt32(), ShirtStyle = fragment.Payload.ReadUInt32(), ShirtColor = fragment.Payload.ReadUInt32(), PantsStyle = fragment.Payload.ReadUInt32(), PantsColor = fragment.Payload.ReadUInt32(), FootwearStyle = fragment.Payload.ReadUInt32(), FootwearColor = fragment.Payload.ReadUInt32(), SkinHue = fragment.Payload.ReadDouble(), HairHue = fragment.Payload.ReadDouble(), HeadgearHue = fragment.Payload.ReadDouble(), ShirtHue = fragment.Payload.ReadDouble(), PantsHue = fragment.Payload.ReadDouble(), FootwearHue = fragment.Payload.ReadDouble() }; return(appearance); }
public static void CharacterEnterWorld(ClientPacketFragment fragment, Session session) { ObjectGuid guid = fragment.Payload.ReadGuid(); string account = fragment.Payload.ReadString16L(); if (account != session.Account) { session.SendCharacterError(CharacterError.EnterGameCharacterNotOwned); return; } var cachedCharacter = session.AccountCharacters.SingleOrDefault(c => c.Guid.Full == guid.Full); if (cachedCharacter == null) { session.SendCharacterError(CharacterError.EnterGameCharacterNotOwned); return; } session.CharacterRequested = cachedCharacter; session.InitSessionForWorldLogin(); session.State = SessionState.WorldConnected; // check the value of the welcome message. Only display it if it is not empty if (!String.IsNullOrEmpty(ConfigManager.Config.Server.Welcome)) { session.Network.EnqueueSend(new GameEventPopupString(session, ConfigManager.Config.Server.Welcome)); } LandblockManager.PlayerEnterWorld(session); }
public static void CharacterEnterWorldRequest(ClientPacketFragment fragment, Session session) { var characterEnterWorldServerReady = new ServerPacket(0x0B, PacketHeaderFlags.EncryptedChecksum); characterEnterWorldServerReady.Fragments.Add(new ServerPacketFragment(9, GameMessageOpcode.CharacterEnterWorldServerReady)); NetworkManager.SendPacket(ConnectionType.Login, characterEnterWorldServerReady, session); }
public static void HandleGameAction(ClientPacketFragment fragement, Session session) { // TODO: verify sequence uint sequence = fragement.Payload.ReadUInt32(); uint opcode = fragement.Payload.ReadUInt32(); InboundMessageManager.HandleGameAction((GameActionType)opcode, fragement, session); }
public static void TurbineChatReceived(ClientPacketFragment fragment, Session session) { fragment.Payload.ReadUInt32(); // Bytes to follow var turbineChatType = (TurbineChatType)fragment.Payload.ReadUInt32(); fragment.Payload.ReadUInt32(); // Always 2 fragment.Payload.ReadUInt32(); // Always 1 fragment.Payload.ReadUInt32(); // Always 0 fragment.Payload.ReadUInt32(); // Always 0 fragment.Payload.ReadUInt32(); // Always 0 fragment.Payload.ReadUInt32(); // Always 0 fragment.Payload.ReadUInt32(); // Bytes to follow if (turbineChatType == TurbineChatType.OutboundMessage) { fragment.Payload.ReadUInt32(); // 0x01 - 0x71 (maybe higher), typically though 0x01 - 0x0F fragment.Payload.ReadUInt32(); // Always 2 fragment.Payload.ReadUInt32(); // Always 2 var channelID = fragment.Payload.ReadUInt32(); var messageLen = fragment.Payload.ReadByte(); var messageBytes = fragment.Payload.ReadBytes(messageLen * 2); var message = Encoding.Unicode.GetString(messageBytes); fragment.Payload.ReadUInt32(); // Always 0x0C var senderID = fragment.Payload.ReadUInt32(); fragment.Payload.ReadUInt32(); // Always 0 fragment.Payload.ReadUInt32(); // Always 1 or 2 if (channelID == 7) // TODO this is hardcoded right now { ChatPacket.SendServerMessage(session, "You do not belong to a society.", ChatMessageType.Broadcast); // I don't know if this is how it was done on the live servers return; } var gameMessageTurbineChat = new GameMessageTurbineChat(TurbineChatType.InboundMessage, channelID, session.Player.Name, message, senderID); // TODO This should check if the recipient is subscribed to the channel foreach (var recipient in WorldManager.GetAll()) { recipient.WorldSession.EnqueueSend(gameMessageTurbineChat); } } else { Console.WriteLine($"Unhandled TurbineChatHandler TurbineChatType: 0x{(uint)turbineChatType:X4}"); } }
public static void HandleGameAction(GameActionOpcode opcode, ClientPacketFragment fragment, Session session) { if (!actionHandlers.ContainsKey(opcode)) { Console.WriteLine($"Received unhandled action opcode: 0x{(uint)opcode:X4}"); } else { Type actionType; if (actionHandlers.TryGetValue(opcode, out actionType)) { var gameAction = (GameActionPacket)Activator.CreateInstance(actionType, session, fragment); gameAction.Read(); gameAction.Handle(); } } }
public static async void CharacterCreate(ClientPacketFragment fragment, Session session) { // known issues: // 1. getting the "next" character id is not thread-safe string account = fragment.Payload.ReadString16L(); if (account != session.Account) { return; } Character character = Character.CreateFromClientFragment(fragment.Payload, session.Id); // TODO: profanity filter // sendCharacterCreateResponse(session, 4); bool isAvailable = DatabaseManager.Character.IsNameAvailable(character.Name); if (!isAvailable) { SendCharacterCreateResponse(session, CharacterGenerationVerificationResponse.NameInUse); return; } uint lowGuid = DatabaseManager.Character.GetMaxId(); character.Id = lowGuid; character.AccountId = session.Id; if (!await DatabaseManager.Character.CreateCharacter(character)) { SendCharacterCreateResponse(session, CharacterGenerationVerificationResponse.DatabaseDown); return; } CharacterCreateSetDefaultCharacterOptions(character); DatabaseManager.Character.SaveCharacterOptions(character); var guid = new ObjectGuid(lowGuid, GuidType.Player); session.CachedCharacters.Add(new CachedCharacter(guid, (byte)session.CachedCharacters.Count, character.Name, 0)); SendCharacterCreateResponse(session, CharacterGenerationVerificationResponse.Ok, guid, character.Name); }
public static void CharacterEnterWorld(ClientPacketFragment fragment, Session session) { ObjectGuid guid = fragment.Payload.ReadGuid(); string account = fragment.Payload.ReadString16L(); if (account != session.Account) { session.SendCharacterError(CharacterError.EnterGameCharacterNotOwned); return; } var cachedCharacter = session.CachedCharacters.SingleOrDefault(c => c.Guid.Full == guid.Full); if (cachedCharacter == null) { session.SendCharacterError(CharacterError.EnterGameCharacterNotOwned); return; } session.CharacterRequested = cachedCharacter; // this isn't really that necessary since ACE doesn't split login/world to multiple daemons, handle it anyway byte[] connectionKey = new byte[sizeof(ulong)]; RandomNumberGenerator.Create().GetNonZeroBytes(connectionKey); session.WorldConnectionKey = BitConverter.ToUInt64(connectionKey, 0); var referralPacket = new ServerPacket(0x0B, PacketHeaderFlags.EncryptedChecksum | PacketHeaderFlags.Referral); referralPacket.Payload.Write(session.WorldConnectionKey); referralPacket.Payload.Write((ushort)2); referralPacket.Payload.WriteUInt16BE((ushort)ConfigManager.Config.Server.Network.WorldPort); referralPacket.Payload.Write(ConfigManager.Host); referralPacket.Payload.Write(0ul); referralPacket.Payload.Write((ushort)0x18); referralPacket.Payload.Write((ushort)0); referralPacket.Payload.Write(0u); NetworkManager.SendPacket(ConnectionType.Login, referralPacket, session); session.State = SessionState.WorldLoginRequest; }
public static void HandleClientFragment(ClientPacketFragment fragment, Session session) { var opcode = (GameMessageOpcode)fragment.Payload.ReadUInt32(); if (!fragmentHandlers.ContainsKey(opcode)) { Console.WriteLine($"Received unhandled fragment opcode: 0x{(uint)opcode:X4}"); } else { MessageHandlerInfo fragmentHandlerInfo; if (fragmentHandlers.TryGetValue(opcode, out fragmentHandlerInfo)) { if (fragmentHandlerInfo.Attribute.State == session.State) { fragmentHandlerInfo.Handler.Invoke(fragment, session); } } } }
public static Character CreateFromClientFragment(ClientPacketFragment fragment, uint accountId) { Character character = new Character(); fragment.Payload.Skip(4); /* Unknown constant (1) */ character.Heritage = fragment.Payload.ReadUInt32(); character.Gender = fragment.Payload.ReadUInt32(); character.Appearance = Appearance.FromFragment(fragment); character.TemplateOption = fragment.Payload.ReadUInt32(); character.Strength.Base = fragment.Payload.ReadUInt32(); character.Endurance.Base = fragment.Payload.ReadUInt32(); character.Coordination.Base = fragment.Payload.ReadUInt32(); character.Quickness.Base = fragment.Payload.ReadUInt32(); character.Focus.Base = fragment.Payload.ReadUInt32(); character.Self.Base = fragment.Payload.ReadUInt32(); character.Slot = fragment.Payload.ReadUInt32(); character.ClassId = fragment.Payload.ReadUInt32(); // characters start with max vitals character.Health.Current = character.Health.UnbuffedValue; character.Stamina.Current = character.Stamina.UnbuffedValue; character.Mana.Current = character.Mana.UnbuffedValue; uint numOfSkills = fragment.Payload.ReadUInt32(); for (uint i = 0; i < numOfSkills; i++) { character.AddSkill((Skill)i, (SkillStatus)fragment.Payload.ReadUInt32(), 0); } character.Name = fragment.Payload.ReadString16L(); character.StartArea = fragment.Payload.ReadUInt32(); character.IsAdmin = Convert.ToBoolean(fragment.Payload.ReadUInt32()); character.IsEnvoy = Convert.ToBoolean(fragment.Payload.ReadUInt32()); character.TotalSkillPoints = fragment.Payload.ReadUInt32(); return(character); }
public static void CharacterRestore(ClientPacketFragment fragment, Session session) { ObjectGuid guid = fragment.Payload.ReadGuid(); var cachedCharacter = session.CachedCharacters.SingleOrDefault(c => c.Guid.Full == guid.Full); if (cachedCharacter == null) { return; } bool isAvailable = DatabaseManager.Character.IsNameAvailable(cachedCharacter.Name); if (!isAvailable) { SendCharacterCreateResponse(session, CharacterGenerationVerificationResponse.NameInUse); /* Name already in use. */ return; } DatabaseManager.Character.DeleteOrRestore(0, guid.Low); session.LoginSession.EnqueueSend(new GameMessageCharacterRestore(guid, cachedCharacter.Name, 0u)); }
public GameActionRemoveAllFriends(Session session, ClientPacketFragment fragment) : base(session, fragment) { }
public static void DDD_EndDDD(ClientPacketFragment fragment, Session session) { // We don't need to reply to this message. }
public GameActionPacket(Session session, ClientPacketFragment fragment) { this.session = session; this.fragment = fragment; }
public static void DDD_InterrogationResponse(ClientPacketFragment fragment, Session session) { // Because we're not delivering any content at this time, we can instruct the client to end the DDD session. }
public static void CharacterEnterWorldRequest(ClientPacketFragment fragment, Session session) { session.LoginSession.EnqueueSend(new GameMessageCharacterEnterWorldServerReady()); }
public GameActionRaiseVital(Session session, ClientPacketFragment fragment) : base(session, fragment) { }
public GameActionChatChannel(Session session, ClientPacketFragment fragment) : base(session, fragment) { }
public GameActionSetCharacterOptions(Session session, ClientPacketFragment fragment) : base(session, fragment) { }
public GameActionSetTitle(Session session, ClientPacketFragment fragment) : base(session, fragment) { }
public GameActionHouseQuery(Session session, ClientPacketFragment fragment) : base(session, fragment) { }
public GameActionAutonomousPosition(Session session, ClientPacketFragment fragment) : base(session, fragment) { }
public GameActionAdvocateTeleport(Session session, ClientPacketFragment fragment) : base(session, fragment) { }
public GameActionTell(Session session, ClientPacketFragment fragment) : base(session, fragment) { }
public GameActionLoginComplete(Session session, ClientPacketFragment fragment) : base(session, fragment) { }