/// <summary> /// Handles the contents of a network message. /// </summary> /// <param name="server">A reference to the tcp server instance which owns the listener at which this request landed.</param> /// <param name="incomingPacket">The packet to handle.</param> /// <param name="client">A reference to the client from where this request originated from, for context.</param> /// <returns>A collection of <see cref="IOutboundPacket"/>s that compose that synchronous response, if any.</returns> public override IEnumerable <IOutboundPacket> HandleRequestPacket(ITcpServer server, IInboundPacket incomingPacket, IClient client) { server.ThrowIfNull(nameof(server)); incomingPacket.ThrowIfNull(nameof(incomingPacket)); client.ThrowIfNull(nameof(client)); if (!(incomingPacket is IGameLogInInfo loginInfo)) { this.Logger.LogError($"Expected packet info of type {nameof(IGameLogInInfo)} but got {incomingPacket.GetType().Name}."); return(null); } if (!(client.Connection is ISocketConnection socketConnection)) { this.Logger.LogError($"Expected a {nameof(ISocketConnection)} got a {client.Connection.GetType().Name}."); return(null); } // Associate the xTea key to allow future validate packets from this connection. socketConnection.SetupAuthenticationKey(loginInfo.XteaKey); // TODO: possibly a friendly name conversion here. Also, the actual values might change per version, so this really should be set by the packet reader. client.Type = Enum.IsDefined(typeof(AgentType), loginInfo.ClientOs) ? (AgentType)loginInfo.ClientOs : AgentType.Windows; client.Version = loginInfo.ClientVersion.ToString(); if (loginInfo.ClientVersion != server.Options.SupportedClientVersion.Numeric) { this.Logger.LogInformation($"Client attempted to connect with version: {loginInfo.ClientVersion}, OS: {loginInfo.ClientOs}. Expected version: {server.Options.SupportedClientVersion.Numeric}."); // TODO: hardcoded messages. return(new GameServerDisconnectPacket($"You need client version {server.Options.SupportedClientVersion.Description} to connect to this server.").YieldSingleItem()); } var(playerId, error) = server.RequestPlayerLogIn(loginInfo.AccountIdentifier, loginInfo.Password, loginInfo.CharacterName); if (!string.IsNullOrWhiteSpace(error)) { return(new GatewayServerDisconnectPacket(error).YieldSingleItem()); } client.PlayerId = playerId; this.clientsManager.Register(client); // We don't return anything synchronously in this particular case, the game will send out the login notifications when they are ready. return(null); }
/// <summary> /// Handles the contents of a network message. /// </summary> /// <param name="server">A reference to the tcp server instance which owns the listener at which this request landed.</param> /// <param name="incomingPacket">The packet to handle.</param> /// <param name="client">A reference to the client from where this request originated from, for context.</param> /// <returns>A collection of <see cref="IOutboundPacket"/>s that compose that synchronous response, if any.</returns> public override IEnumerable <IOutboundPacket> HandleRequestPacket(ITcpServer server, IInboundPacket incomingPacket, IClient client) { server.ThrowIfNull(nameof(server)); incomingPacket.ThrowIfNull(nameof(incomingPacket)); client.ThrowIfNull(nameof(client)); if (!(incomingPacket is ILookAtInfo lookAtInfo)) { this.Logger.LogError($"Expected packet info of type {nameof(ILookAtInfo)} but got {incomingPacket.GetType().Name}."); return(null); } server.RequestTextDescriptionAtAsync(client.PlayerId, lookAtInfo.Location, lookAtInfo.StackPosition, lookAtInfo.ThingId); return(null); }
/// <summary> /// Handles the contents of a network message. /// </summary> /// <param name="server">A reference to the tcp server instance which owns the listener at which this request landed.</param> /// <param name="incomingPacket">The packet to handle.</param> /// <param name="client">A reference to the client from where this request originated from, for context.</param> /// <returns>A collection of <see cref="IOutboundPacket"/>s that compose that synchronous response, if any.</returns> public override IEnumerable <IOutboundPacket> HandleRequestPacket(ITcpServer server, IInboundPacket incomingPacket, IClient client) { server.ThrowIfNull(nameof(server)); incomingPacket.ThrowIfNull(nameof(incomingPacket)); client.ThrowIfNull(nameof(client)); if (!(incomingPacket is ISpeechInfo speechInfo)) { this.Logger.LogError($"Expected packet info of type {nameof(ISpeechInfo)} but got {incomingPacket.GetType().Name}."); return(null); } server.RequestSendMessageAsync(client.PlayerId, speechInfo.SpeechType, speechInfo.ChannelType, speechInfo.Content, speechInfo.Receiver); return(null); }
/// <summary> /// Handles the contents of a network message. /// </summary> /// <param name="server">A reference to the tcp server instance which owns the listener at which this request landed.</param> /// <param name="incomingPacket">The packet to handle.</param> /// <param name="client">A reference to the client from where this request originated from, for context.</param> /// <returns>A collection of <see cref="IOutboundPacket"/>s that compose that synchronous response, if any.</returns> public override IEnumerable <IOutboundPacket> HandleRequestPacket(ITcpServer server, IInboundPacket incomingPacket, IClient client) { server.ThrowIfNull(nameof(server)); incomingPacket.ThrowIfNull(nameof(incomingPacket)); client.ThrowIfNull(nameof(client)); if (!(incomingPacket is IModesInfo modesInfo)) { this.Logger.LogError($"Expected packet info of type {nameof(IModesInfo)} but got {incomingPacket.GetType().Name}."); return(null); } server.RequestToUpdateModesAsync(client.PlayerId, modesInfo.FightMode, modesInfo.ChaseMode, modesInfo.SafeModeOn); return(null); }
/// <summary> /// Handles the contents of a network message. /// </summary> /// <param name="server">A reference to the tcp server instance which owns the listener at which this request landed.</param> /// <param name="incomingPacket">The packet to handle.</param> /// <param name="client">A reference to the client from where this request originated from, for context.</param> /// <returns>A collection of <see cref="IOutboundPacket"/>s that compose that synchronous response, if any.</returns> public override IEnumerable <IOutboundPacket> HandleRequestPacket(ITcpServer server, IInboundPacket incomingPacket, IClient client) { server.ThrowIfNull(nameof(server)); incomingPacket.ThrowIfNull(nameof(incomingPacket)); client.ThrowIfNull(nameof(client)); if (!(incomingPacket is IWalkOnDemandInfo walkOnDemandInfo)) { this.Logger.LogError($"Expected packet info of type {nameof(IWalkOnDemandInfo)} but got {incomingPacket.GetType().Name}."); return(null); } server.RequestToUpdateWalkPlanAsync(client.PlayerId, new[] { walkOnDemandInfo.Direction }); return(null); }
/// <summary> /// Handles the contents of a network message. /// </summary> /// <param name="server">A reference to the tcp server instance which owns the listener at which this request landed.</param> /// <param name="incomingPacket">The packet to handle.</param> /// <param name="client">A reference to the client from where this request originated from, for context.</param> /// <returns>A collection of <see cref="IOutboundPacket"/>s that compose that synchronous response, if any.</returns> public override IEnumerable <IOutboundPacket> HandleRequestPacket(ITcpServer server, IInboundPacket incomingPacket, IClient client) { server.ThrowIfNull(nameof(server)); incomingPacket.ThrowIfNull(nameof(incomingPacket)); client.ThrowIfNull(nameof(client)); if (!(incomingPacket is ITurnOnDemandInfo turnOnDemandInfo)) { this.Logger.LogError($"Expected packet info of type {nameof(ITurnOnDemandInfo)} but got {incomingPacket.GetType().Name}."); return(null); } // TODO: cancel other pending actions. server.RequestToTurnCreatureAsync(client.PlayerId, turnOnDemandInfo.Direction); return(null); }
/// <summary> /// Handles the contents of a network message. /// </summary> /// <param name="server">A reference to the tcp server instance which owns the listener at which this request landed.</param> /// <param name="incomingPacket">The packet to handle.</param> /// <param name="client">A reference to the client from where this request originated from, for context.</param> /// <returns>A collection of <see cref="IOutboundPacket"/>s that compose that synchronous response, if any.</returns> public override IEnumerable <IOutboundPacket> HandleRequestPacket(ITcpServer server, IInboundPacket incomingPacket, IClient client) { server.ThrowIfNull(nameof(server)); incomingPacket.ThrowIfNull(nameof(incomingPacket)); client.ThrowIfNull(nameof(client)); if (!(incomingPacket is IGatewayLoginInfo accountLoginInfo)) { this.Logger.LogError($"Expected packet info of type {nameof(IGatewayLoginInfo)} but got {incomingPacket.GetType().Name}."); return(null); } if (!(client.Connection is ISocketConnection socketConnection)) { this.Logger.LogError($"Expected a {nameof(ISocketConnection)} got a {client.Connection.GetType().Name}."); return(null); } // Associate the xTea key to allow future validate packets from this connection. socketConnection.SetupAuthenticationKey(accountLoginInfo.XteaKey); if (accountLoginInfo.ClientVersion != server.Options.SupportedClientVersion.Numeric) { this.Logger.LogInformation($"Client attempted to connect with version: {accountLoginInfo.ClientVersion}, OS: {accountLoginInfo.ClientOs}. Expected version: {server.Options.SupportedClientVersion.Numeric}."); // TODO: hardcoded messages. return(new GatewayServerDisconnectPacket($"You need client version {server.Options.SupportedClientVersion.Description} to connect to this server.").YieldSingleItem()); } var(characters, premDays, error) = server.DoAccountLogin(accountLoginInfo.AccountName, accountLoginInfo.Password); if (!string.IsNullOrWhiteSpace(error)) { return(new GatewayServerDisconnectPacket(error).YieldSingleItem()); } return(new IOutboundPacket[] { new MessageOfTheDayPacket(server.InformationalMessage), new CharacterListPacket(characters, (ushort)premDays), }); }
/// <summary> /// Handles the contents of a network message. /// </summary> /// <param name="server">A reference to the tcp server instance which owns the listener at which this request landed.</param> /// <param name="incomingPacket">The packet to handle.</param> /// <param name="client">A reference to the client from where this request originated from, for context.</param> /// <returns>A collection of <see cref="IOutboundPacket"/>s that compose that synchronous response, if any.</returns> public override IEnumerable <IOutboundPacket> HandleRequestPacket(ITcpServer server, IInboundPacket incomingPacket, IClient client) { server.ThrowIfNull(nameof(server)); incomingPacket.ThrowIfNull(nameof(incomingPacket)); client.ThrowIfNull(nameof(client)); if (!(incomingPacket is IActionWithoutContentInfo actionInfo)) { this.Logger.LogError($"Expected packet info of type {nameof(IActionWithoutContentInfo)} but got {incomingPacket.GetType().Name}."); return(null); } switch (actionInfo.Action) { case InboundPacketType.AutoMoveCancel: server.RequestToCancelPlayerOperationsAsync(client.PlayerId, OperationCategory.Movement); break; case InboundPacketType.HeartbeatResponse: // NO-OP. break; case InboundPacketType.Heartbeat: server.SendHeartbeatResponseAsync(client); break; case InboundPacketType.LogOut: server.RequestPlayerLogOutAsync(client.PlayerId); break; case InboundPacketType.StartOutfitChange: // this.Game.RequestPlayerOutfitChange(client.PlayerId); break; case InboundPacketType.StopAllActions: server.RequestToCancelPlayerOperationsAsync(client.PlayerId); break; } return(null); }
/// <summary> /// Handles the contents of a network message. /// </summary> /// <param name="server">A reference to the tcp server instance which owns the listener at which this request landed.</param> /// <param name="incomingPacket">The packet to handle.</param> /// <param name="client">A reference to the client from where this request originated from, for context.</param> /// <returns>A collection of <see cref="IOutboundPacket"/>s that compose that synchronous response, if any.</returns> public override IEnumerable <IOutboundPacket> HandleRequestPacket(ITcpServer server, IInboundPacket incomingPacket, IClient client) { server.ThrowIfNull(nameof(server)); incomingPacket.ThrowIfNull(nameof(incomingPacket)); client.ThrowIfNull(nameof(client)); if (!(incomingPacket is IFollowInfo followInfo)) { this.Logger.LogError($"Expected packet info of type {nameof(IFollowInfo)} but got {incomingPacket.GetType().Name}."); return(null); } // First stop attacking if we are. server.RequestToAttackCreatureAsync(client.PlayerId); server.RequestToFollowCreatureAsync(client.PlayerId, followInfo.TargetCreatureId); return(null); }
/// <summary> /// Handles the contents of a network message. /// </summary> /// <param name="server">A reference to the tcp server instance which owns the listener at which this request landed.</param> /// <param name="incomingPacket">The packet to handle.</param> /// <param name="client">A reference to the client from where this request originated from, for context.</param> /// <returns>A collection of <see cref="IOutboundPacket"/>s that compose that synchronous response, if any.</returns> public override IEnumerable <IOutboundPacket> HandleRequestPacket(ITcpServer server, IInboundPacket incomingPacket, IClient client) { server.ThrowIfNull(nameof(server)); incomingPacket.ThrowIfNull(nameof(incomingPacket)); client.ThrowIfNull(nameof(client)); if (!(incomingPacket is IAttackInfo attackInfo)) { this.Logger.LogError($"Expected packet info of type {nameof(IAttackInfo)} but got {incomingPacket.GetType().Name}."); return(null); } // First stop following (formally) if we are. server.RequestToFollowCreatureAsync(client.PlayerId); // And then start attacking. Game will handle if that implicitly means follow the target of the attack. server.RequestToAttackCreatureAsync(client.PlayerId, attackInfo.TargetCreatureId); return(null); }
/// <summary> /// Handles the contents of a network message. /// </summary> /// <param name="server">A reference to the tcp server instance which owns the listener at which this request landed.</param> /// <param name="incomingPacket">The packet to handle.</param> /// <param name="client">A reference to the client from where this request originated from, for context.</param> /// <returns>A collection of <see cref="IOutboundPacket"/>s that compose that synchronous response, if any.</returns> public override IEnumerable <IOutboundPacket> HandleRequestPacket(ITcpServer server, IInboundPacket incomingPacket, IClient client) { server.ThrowIfNull(nameof(server)); incomingPacket.ThrowIfNull(nameof(incomingPacket)); client.ThrowIfNull(nameof(client)); if (!(incomingPacket is IBytesInfo debugInfo)) { this.Logger.LogError($"Expected packet info of type {nameof(IBytesInfo)} but got {incomingPacket.GetType().Name}."); return(null); } var sb = new StringBuilder(); foreach (var b in debugInfo.Bytes) { sb.AppendFormat("{0:x2} ", b); } this.Logger.LogInformation($"Default handler drained packet with content:\n\n{sb}"); return(null); }