/// <inheritdoc /> protected override IRemoteSocialTextChatHubClient GetBroadcastGroup(IHubConnectionMessageContext <IRemoteSocialTextChatHubClient> context) { if (!GuildStatusMappable.ContainsKey(context.CallerGuid)) { throw new InvalidOperationException($"Tried to send Guild Message for Entity: {context.CallerGuid} but no guild data was available."); } //TODO: We should have guild status model, including pending invites and such. if (!GuildStatusMappable[context.CallerGuid].isSuccessful) { //TODO: Log } return(context.Clients.Group($"guild:{GuildStatusMappable[context.CallerGuid].GuildId}")); }
protected EntityAssociatedData <T> BuildForwardableAssociatedData <T>([JetBrains.Annotations.NotNull] IHubConnectionMessageContext context, [JetBrains.Annotations.NotNull] T envolpeContents) { if (context == null) { throw new ArgumentNullException(nameof(context)); } if (envolpeContents == null) { throw new ArgumentNullException(nameof(envolpeContents)); } //TODO: We should cache somehow the identifier's int value, parsing it each time I think can be costly. NetworkEntityGuid guid = new NetworkEntityGuidBuilder() .WithId(int.Parse(context.HubConntext.UserIdentifier)) .WithType(EntityType.Player) .Build(); return(new EntityAssociatedData <T>(guid, envolpeContents)); }
/// <inheritdoc /> protected override async Task OnMessageRecieved(IHubConnectionMessageContext <IRemoteSocialTextChatHubClient> context, TMessageType message) { //TODO: We may want to do validation for the message sent more than this if (message.TargetChannel != TargetChannel) { return; } //TODO: We need to check if zone messaging is even enabled for the connection. This could be a WEB ONLY connection. if (String.IsNullOrWhiteSpace(message.Message)) { return; } TSendMessageType outgoingMessage = OutgoingMessageFactory.Create(new GenericChatMessageContext <TMessageType>(message, context)); await SendOutgoingMessage(GetBroadcastGroup(context), outgoingMessage) .ConfigureAwait(false); }
protected override async Task OnMessageRecieved(IHubConnectionMessageContext <IRemoteSocialHubClient> context, GuildMemberInviteRequestModel payload) { var nameQueryResponseTask = NameQueryService.RetrievePlayerGuidAsync(payload.MemberToInvite); //First we need to check if they're in a guild. //We don't really need to handle the response for this, since it should never really happen. var guildStatus = await SocialService.GetCharacterMembershipGuildStatus(context.CallerGuid.EntityId); if (!guildStatus.isSuccessful) { if (Logger.IsEnabled(LogLevel.Warning)) { Logger.LogWarning($"User: {context.CallerGuid} attempted to Invite: {payload.MemberToInvite} to a guild but was not apart of a guild."); } return; } //Now we should know what guild the caller is in due to the query. //Now we need to do a reverse namequery to get the guid of who they're attempting to invite. var nameQueryResponse = await nameQueryResponseTask; //If it's not successful, assume the user doesn't exist. if (!nameQueryResponse.isSuccessful) { await SendGuildInviteResponse(context, GuildMemberInviteResponseCode.PlayerNotFound, NetworkEntityGuid.Empty); return; } //Now check if the user is already guilded //If they are we should indicate that to the client. if (await CheckIfGuilded(nameQueryResponse.Result)) { await SendGuildInviteResponse(context, GuildMemberInviteResponseCode.PlayerAlreadyInGuild, nameQueryResponse.Result); return; } //Ok, the reverse name query was successful. Check if there is a pending invite. //TODO: Right now we rely on local state to indicate if there is a pending invite. We need to NOT do that because it won't work when we scale out. ProjectVersionStage.AssertBeta(); //TODO: There is a race condition if multiple invites are sent at the same time, should we care?? //If they have a pending invite. if (PendingInviteData.ContainsKey(nameQueryResponse.Result)) { //If NOT expired then we need to say they're currently pending an invite if (!PendingInviteData[nameQueryResponse.Result].isInviteExpired()) { await SendGuildInviteResponse(context, GuildMemberInviteResponseCode.PlayerAlreadyHasPendingInvite, nameQueryResponse.Result); return; } else { //The invite is EXPIRED so let's added a new one. PendingInviteData.ReplaceObject(nameQueryResponse.Result, GeneratePendingInviteData(context.CallerGuid, guildStatus.Result.GuildId)); } } else { PendingInviteData.AddObject(nameQueryResponse.Result, GeneratePendingInviteData(context.CallerGuid, guildStatus.Result.GuildId)); } //TODO: There is currently no handling to indicate that they are online. //Now they have a valid pending invite, so let's address the client //that needs to recieve the guild invite. IRemoteSocialHubClient playerClient = context.Clients.RetrievePlayerClient(nameQueryResponse.Result); //Indicate the player has been invited. await SendGuildInviteResponse(context, GuildMemberInviteResponseCode.Success, nameQueryResponse.Result); //Now tell the remote/target player they're being invited to a guild. await playerClient.ReceiveGuildInviteEventAsync(new GuildMemberInviteEventModel(guildStatus.Result.GuildId, context.CallerGuid)); }
private static async Task SendGuildInviteResponse(IHubConnectionMessageContext <IRemoteSocialHubClient> context, GuildMemberInviteResponseCode code, NetworkEntityGuid inviteeGuid) { await context.Clients.Caller.ReceiveGuildInviteResponseAsync(new GuildMemberInviteResponseModel(code, inviteeGuid)); }
/// <inheritdoc /> public GenericChatMessageContext([JetBrains.Annotations.NotNull] TMessageType incomingMessage, [JetBrains.Annotations.NotNull] IHubConnectionMessageContext hubContext) { IncomingMessage = incomingMessage ?? throw new ArgumentNullException(nameof(incomingMessage)); HubContext = hubContext ?? throw new ArgumentNullException(nameof(hubContext)); }
protected EntityAssociatedData <TargetlessChannelChatMessageRequestModel> BuildForwardableTargetlessChannelChatMessage(IHubConnectionMessageContext context, TargetlessChannelChatMessageRequestModel message) => BuildForwardableAssociatedData(context, message);
protected abstract Task OnMessageRecieved(IHubConnectionMessageContext <TRemoteClientHubInterfaceType> context, TMessageType payload);
/// <inheritdoc /> protected override IRemoteSocialTextChatHubClient GetBroadcastGroup(IHubConnectionMessageContext <IRemoteSocialTextChatHubClient> context) { return(context.Clients.Group($"zone:{ZoneLookupService.Retrieve(context.HubConntext.ConnectionId)}")); }
protected override async Task OnMessageRecieved(IHubConnectionMessageContext <IRemoteSocialHubClient> context, PendingGuildInviteHandleRequest payload) { //Really shouldn't happen, don't tell client anything. if (!PendingInviteData.ContainsKey(context.CallerGuid)) { if (Logger.IsEnabled(LogLevel.Error)) { Logger.LogError($"User: {context.CallerGuid} tried to claim pending guild invite but none existed."); } return; } PendingGuildInviteData inviteData = PendingInviteData.RetrieveEntity(context.CallerGuid); //Now we can check if they wanted to join if (payload.isSuccessful) { bool guildJoinResult = false; //Important that we dispose of this, since this handler is not created every request. using (var characterGuildMembershipRepositoryContainer = CharacterGuildMembershipRepositoryFactory.Create()) { //When successful, we must add them to the guild database //and then alert the guild channel (everyone in the guild) that they joined //AND let the client itself know that it joined a guild. guildJoinResult = await characterGuildMembershipRepositoryContainer.Repository.TryCreateAsync(new CharacterGuildMemberRelationshipModel(context.CallerGuid.EntityId, inviteData.GuildId)); } //This should never happen if (!guildJoinResult) { if (Logger.IsEnabled(LogLevel.Error)) { Logger.LogError($"User: {context.CallerGuid} tried to join Guild: {inviteData.GuildId} but failed."); } return; } //TODO: Don't hardcode this //$"guild:{GuildStatusMappable.RetrieveEntity(guid).GuildId} //Their membership is within the database now. //Broadcast to everyone that a player joined the guild. await context.Clients.Group($"guild:{inviteData.GuildId}").ReceiveGuildMemberJoinedEventAsync(new GuildMemberJoinedEventModel(context.CallerGuid)); await context.Groups.AddToGroupAsync(context.HubConntext.ConnectionId, $"guild:{inviteData.GuildId}"); //Let the local client know that their guild status also changed. await context.Clients.RetrievePlayerClient(context.CallerGuid).ReceiveGuildStatusChangedEventAsync(new GuildStatusChangedEventModel(context.CallerGuid, inviteData.GuildId)); } else { //On failure, we just remove the pending invite //and let the inviting client know that they declined an invite. PendingInviteData.RemoveEntityEntry(context.CallerGuid); IRemoteSocialHubClient inviterClient = context.Clients.RetrievePlayerClient(inviteData.InviterGuid); //Tell the inviter this failed. await inviterClient.ReceiveGuildInviteResponseAsync(new GuildMemberInviteResponseModel(GuildMemberInviteResponseCode.PlayerDeclinedGuildInvite, context.CallerGuid)); } }
protected override async Task OnMessageRecieved(IHubConnectionMessageContext <IRemoteSocialHubClient> context, TestSocialModel payload) { Logger.LogError($"Recieved TestMessage: {payload.TestMessage}"); }
/// <summary> /// TODO /// </summary> /// <returns></returns> protected abstract IRemoteSocialTextChatHubClient GetBroadcastGroup(IHubConnectionMessageContext <IRemoteSocialTextChatHubClient> context);