private void SendConnectionInfo(MooNetClient client) { // Lock party and close privacy level while entering game if (client.CurrentChannel != null) { var channelStatePrivacyLevel = bnet.protocol.channel.ChannelState.CreateBuilder() .SetPrivacyLevel(bnet.protocol.channel.ChannelState.Types.PrivacyLevel.PRIVACY_LEVEL_CLOSED).Build(); var notificationPrivacyLevel = bnet.protocol.channel.UpdateChannelStateNotification.CreateBuilder() .SetAgentId(client.Account.CurrentGameAccount.BnetEntityId) .SetStateChange(channelStatePrivacyLevel) .Build(); client.MakeTargetedRPC(client.CurrentChannel, () => bnet.protocol.channel.ChannelSubscriber.CreateStub(client).NotifyUpdateChannelState(null, notificationPrivacyLevel, callback => { })); var channelStatePartyLock = bnet.protocol.channel.ChannelState.CreateBuilder() .AddAttribute(bnet.protocol.attribute.Attribute.CreateBuilder() .SetName("D3.Party.LockReasons") .SetValue(bnet.protocol.attribute.Variant.CreateBuilder().SetIntValue(1).Build()) .Build()).Build(); var notificationPartyLock = bnet.protocol.channel.UpdateChannelStateNotification.CreateBuilder() .SetAgentId(client.Account.CurrentGameAccount.BnetEntityId) .SetStateChange(channelStatePartyLock) .Build(); client.MakeTargetedRPC(client.CurrentChannel, () => bnet.protocol.channel.ChannelSubscriber.CreateStub(client).NotifyUpdateChannelState(null, notificationPartyLock, callback => { })); } // send the notification. var connectionInfo = GetConnectionInfoForClient(client); var connectionInfoAttribute = bnet.protocol.attribute.Attribute.CreateBuilder().SetName("connection_info") .SetValue(bnet.protocol.attribute.Variant.CreateBuilder().SetMessageValue(connectionInfo.ToByteString()).Build()) .Build(); var gameHandleAttribute = bnet.protocol.attribute.Attribute.CreateBuilder().SetName("game_handle") .SetValue(bnet.protocol.attribute.Variant.CreateBuilder().SetMessageValue(this.GameHandle.ToByteString()).Build()) .Build(); var requestIdAttribute = bnet.protocol.attribute.Attribute.CreateBuilder().SetName("game_request_id") .SetValue(bnet.protocol.attribute.Variant.CreateBuilder().SetUintValue(this.RequestId).Build()) .Build(); var notificationBuilder = bnet.protocol.notification.Notification.CreateBuilder() .SetSenderId(bnet.protocol.EntityId.CreateBuilder().SetHigh((ulong)EntityIdHelper.HighIdType.GameAccountId).SetLow(0).Build()) .SetTargetId(client.Account.CurrentGameAccount.BnetEntityId) .SetType("GAME_ENTRY") .AddAttribute(connectionInfoAttribute) .AddAttribute(gameHandleAttribute) .AddAttribute(requestIdAttribute) .Build(); client.MakeRPC(() => bnet.protocol.notification.NotificationListener.CreateStub(client).OnNotificationReceived(null, notificationBuilder, callback => { })); }
protected void MakeRPC(MooNetClient client, List <bnet.protocol.presence.FieldOperation> operations) { // Create a presence.ChannelState var state = bnet.protocol.presence.ChannelState.CreateBuilder().SetEntityId(this.BnetEntityId).AddRangeFieldOperation(operations).Build(); // Embed in channel.ChannelState var channelState = bnet.protocol.channel.ChannelState.CreateBuilder().SetExtension(bnet.protocol.presence.ChannelState.Presence, state); // Put in AddNotification message var builder = bnet.protocol.channel.AddNotification.CreateBuilder().SetChannelState(channelState); // Make the RPC call to all online game accounts //TODO: Split notifications per game type client.MakeTargetedRPC(this, () => bnet.protocol.channel.ChannelSubscriber.CreateStub(client).NotifyAdd(null, builder.Build(), callback => { })); //foreach (var gameClient in client.Account.GameAccounts) //{ // if (gameClient.Value.IsOnline) // { // gameClient.Value.LoggedInClient.MakeTargetedRPC(this, () => // bnet.protocol.channel.ChannelSubscriber.CreateStub(gameClient.Value.LoggedInClient).NotifyAdd(null, builder.Build(), callback => { })); // } //} }
public Channel HandleAccept(MooNetClient client, bnet.protocol.channel_invitation.AcceptInvitationRequest request) { if (!this._onGoingInvitations.ContainsKey(request.InvitationId)) { return(null); } var invitation = this._onGoingInvitations[request.InvitationId]; var channel = ChannelManager.GetChannelByEntityId(invitation.GetExtension(bnet.protocol.channel_invitation.ChannelInvitation.ChannelInvitationProp).ChannelDescription.ChannelId); var notification = bnet.protocol.channel_invitation.InvitationRemovedNotification.CreateBuilder().SetInvitation(invitation.ToBuilder()).SetReason((uint)InvitationRemoveReason.Accepted); this._onGoingInvitations.Remove(invitation.Id); // notify invitee and let him remove the handled invitation. client.MakeTargetedRPC(this, () => bnet.protocol.channel_invitation.ChannelInvitationNotify.CreateStub(client).NotifyReceivedInvitationRemoved(null, notification.Build(), callback => { })); channel.Join(client, request.ObjectId); // add invitee to channel -- so inviter and other members will also be notified too. var inviter = GameAccountManager.GetAccountByPersistentID(invitation.InviterIdentity.AccountId.Low); var stateNotification = bnet.protocol.channel.UpdateChannelStateNotification.CreateBuilder() .SetAgentId(bnet.protocol.EntityId.CreateBuilder().SetHigh(0).SetLow(0).Build()) .SetStateChange(bnet.protocol.channel.ChannelState.CreateBuilder().AddRangeInvitation(channel.Invitations.Values).SetReason(0).Build()) .Build(); foreach (var member in channel.Members.Keys) { member.MakeTargetedRPC(channel, () => bnet.protocol.channel.ChannelSubscriber.CreateStub(member).NotifyUpdateChannelState(null, stateNotification, callback => { })); } return(channel); }
public static void HandleRemove(MooNetClient client, bnet.protocol.friends.GenericFriendRequest request) { var removee = AccountManager.GetAccountByPersistentID(request.TargetId.Low); var remover = client.Account; var removeeAsFriend = bnet.protocol.friends.Friend.CreateBuilder().SetId(removee.BnetAccountID).Build(); var removerAsFriend = bnet.protocol.friends.Friend.CreateBuilder().SetId(remover.BnetAccountID).Build(); var removed = Friends.Remove(remover.BnetAccountID.Low, removeeAsFriend); if (!removed) { Logger.Warn("No friendship mapping between {0} and {1}", remover.BnetAccountID.Low, removeeAsFriend); } removed = Friends.Remove(removee.BnetAccountID.Low, removerAsFriend); if (!removed) { Logger.Warn("No friendship mapping between {0} and {1}", removee.BnetAccountID.Low, removerAsFriend); } RemoveFriendshipFromDB(remover, removee); var notifyRemover = bnet.protocol.friends.FriendNotification.CreateBuilder().SetTarget(removeeAsFriend).Build(); client.MakeTargetedRPC(FriendManager.Instance, () => bnet.protocol.friends.FriendsNotify.CreateStub(client).NotifyFriendRemoved(null, notifyRemover, callback => { })); if (removee.IsOnline) { var notifyRemovee = bnet.protocol.friends.FriendNotification.CreateBuilder().SetTarget(removerAsFriend).Build(); removee.LoggedInClient.MakeTargetedRPC(FriendManager.Instance, () => bnet.protocol.friends.FriendsNotify.CreateStub(removee.LoggedInClient).NotifyFriendRemoved(null, notifyRemovee, callback => { })); } }
public void Revoke(MooNetClient client, bnet.protocol.channel_invitation.RevokeInvitationRequest request) { if (!this._onGoingInvitations.ContainsKey(request.InvitationId)) { return; } var invitation = this._onGoingInvitations[request.InvitationId]; //notify inviter about revoke var updateChannelNotification = bnet.protocol.channel.UpdateChannelStateNotification.CreateBuilder() .SetAgentId(bnet.protocol.EntityId.CreateBuilder().SetHigh(0).SetLow(0)) // caps have this set to high: 0 low: 0 /dustin .SetStateChange(bnet.protocol.channel.ChannelState.CreateBuilder() .AddInvitation(invitation) .SetReason((uint)InvitationRemoveReason.Revoked)); this._onGoingInvitations.Remove(request.InvitationId); client.MakeTargetedRPC(client.CurrentChannel, () => bnet.protocol.channel.ChannelSubscriber.CreateStub(client).NotifyUpdateChannelState(null, updateChannelNotification.Build(), callback => { })); //notify invitee about revoke var invitationRemoved = bnet.protocol.channel_invitation.InvitationRemovedNotification.CreateBuilder() .SetInvitation(invitation) .SetReason((uint)InvitationRemoveReason.Revoked); var invitee = ToonManager.GetToonByLowID(invitation.InviteeIdentity.ToonId.Low); invitee.Owner.LoggedInClient.MakeTargetedRPC(this, () => bnet.protocol.channel_invitation.ChannelInvitationNotify.CreateStub(invitee.Owner.LoggedInClient).NotifyReceivedInvitationRemoved(null, invitationRemoved.Build(), callback => { })); }
public static void HandleRemove(MooNetClient client, bnet.protocol.friends.GenericFriendRequest request) { var removee = AccountManager.GetAccountByPersistentID(request.TargetId.Low); var remover = client.Account; var removeeAsFriend = bnet.protocol.friends.Friend.CreateBuilder().SetId(removee.BnetEntityId).Build(); var removerAsFriend = bnet.protocol.friends.Friend.CreateBuilder().SetId(remover.BnetEntityId).Build(); RemoveFriendshipFromDB(remover, removee); var notifyRemover = bnet.protocol.friends.FriendNotification.CreateBuilder().SetTarget(removeeAsFriend).Build(); client.MakeTargetedRPC(FriendManager.Instance, () => bnet.protocol.friends.FriendsNotify.CreateStub(client).NotifyFriendRemoved(null, notifyRemover, callback => { })); var removeeGameAccounts = GameAccountManager.GetGameAccountsForAccount(removee); foreach (var removeeGameAccount in removeeGameAccounts) { if (!removeeGameAccount.IsOnline) { continue; } var notifyRemovee = bnet.protocol.friends.FriendNotification.CreateBuilder().SetTarget(removerAsFriend).Build(); removeeGameAccount.LoggedInClient.MakeTargetedRPC(FriendManager.Instance, () => bnet.protocol.friends.FriendsNotify.CreateStub(removeeGameAccount.LoggedInClient).NotifyFriendRemoved(null, notifyRemovee, callback => { })); } }
public void AddMember(MooNetClient client) { if (HasUser(client)) { Logger.Warn("Attempted to add client {0} to channel when it was already a member of the channel", client.Connection.RemoteEndPoint.ToString()); return; } var identity = client.GetIdentity(false, false, true); bool isOwner = client == this.Owner; var addedMember = new Member(identity, (isOwner) ? Member.Privilege.UnkCreator : Member.Privilege.UnkMember); if (this.Members.Count > 0) { addedMember.AddRoles((isOwner) ? Member.Role.PartyLeader : Member.Role.PartyMember, Member.Role.ChannelMember); } else { addedMember.AddRole((isOwner) ? Member.Role.ChannelCreator : Member.Role.ChannelMember); } // This needs to be here so that the foreach below will also send to the client that was just added this.Members.Add(client, addedMember); // Cache the built state and member var channelState = this.State; // added member should recieve a NotifyAdd. var addNotification = bnet.protocol.channel.AddNotification.CreateBuilder() .SetChannelState(channelState) .SetSelf(addedMember.BnetMember) .AddRangeMember(this.Members.Values.ToList().Select(member => member.BnetMember).ToList()).Build(); client.MakeTargetedRPC(this, () => bnet.protocol.channel.ChannelSubscriber.CreateStub(client).NotifyAdd(null, addNotification, callback => { })); client.CurrentChannel = this; // set clients current channel to one he just joined. if (this.Members.Count < 2) { return; } // other members should recieve a NotifyJoin. var joinNotification = bnet.protocol.channel.JoinNotification.CreateBuilder() .SetMember(addedMember.BnetMember).Build(); foreach (var pair in this.Members.Where(pair => pair.Value != addedMember)) // only send this to previous members of the channel. { pair.Key.MakeTargetedRPC(this, () => bnet.protocol.channel.ChannelSubscriber.CreateStub(pair.Key).NotifyJoin(null, joinNotification, callback => { })); } }
protected override void NotifySubscriptionAdded(MooNetClient client) { var operations = new List <bnet.protocol.presence.FieldOperation>(); // Selected toon if (this.LoggedInClient != null && this.Digest.LastPlayedHeroId != AccountHasNoToons) { var selectedToonKey = FieldKeyHelper.Create(FieldKeyHelper.Program.D3, 1, 1, 0); var selectedToonField = bnet.protocol.presence.Field.CreateBuilder().SetKey(selectedToonKey).SetValue(bnet.protocol.attribute.Variant.CreateBuilder().SetMessageValue(this.Digest.LastPlayedHeroId.ToByteString()).Build()).Build(); operations.Add(bnet.protocol.presence.FieldOperation.CreateBuilder().SetField(selectedToonField).Build()); } // RealID name field - NOTE: Probably won't ever use this for its actual purpose, but showing the email in final might not be a good idea var realNameKey = FieldKeyHelper.Create(FieldKeyHelper.Program.BNet, 1, 1, 0); var realNameField = bnet.protocol.presence.Field.CreateBuilder().SetKey(realNameKey).SetValue(bnet.protocol.attribute.Variant.CreateBuilder().SetStringValue(this.Email).Build()).Build(); operations.Add(bnet.protocol.presence.FieldOperation.CreateBuilder().SetField(realNameField).Build()); // Account online? var accountOnlineKey = FieldKeyHelper.Create(FieldKeyHelper.Program.BNet, 1, 2, 0); var accountOnlineField = bnet.protocol.presence.Field.CreateBuilder().SetKey(accountOnlineKey).SetValue(bnet.protocol.attribute.Variant.CreateBuilder().SetBoolValue(this.IsOnline).Build()).Build(); operations.Add(bnet.protocol.presence.FieldOperation.CreateBuilder().SetField(accountOnlineField).Build()); // toon list foreach (var pair in this.Toons) { var toonKey = FieldKeyHelper.Create(FieldKeyHelper.Program.BNet, 1, 4, 0); var toonField = bnet.protocol.presence.Field.CreateBuilder().SetKey(toonKey).SetValue(bnet.protocol.attribute.Variant.CreateBuilder().SetMessageValue(pair.Value.BnetEntityID.ToByteString()).Build()).Build(); operations.Add(bnet.protocol.presence.FieldOperation.CreateBuilder().SetField(toonField).Build()); } var tempNameKey = FieldKeyHelper.Create(FieldKeyHelper.Program.BNet, 1, 5, 0); var tempNameField = bnet.protocol.presence.Field.CreateBuilder().SetKey(tempNameKey).SetValue(bnet.protocol.attribute.Variant.CreateBuilder().SetStringValue("NICKTEMPNAME").Build()).Build(); operations.Add(bnet.protocol.presence.FieldOperation.CreateBuilder().SetField(tempNameField).Build()); // Create a presence.ChannelState var state = bnet.protocol.presence.ChannelState.CreateBuilder().SetEntityId(this.BnetAccountID).AddRangeFieldOperation(operations).Build(); // Embed in channel.ChannelState var channelState = bnet.protocol.channel.ChannelState.CreateBuilder().SetExtension(bnet.protocol.presence.ChannelState.Presence, state); // Put in addnotification message var notification = bnet.protocol.channel.AddNotification.CreateBuilder().SetChannelState(channelState); // Make the rpc call client.MakeTargetedRPC(this, () => bnet.protocol.channel.ChannelSubscriber.CreateStub(client).NotifyAdd(null, notification.Build(), callback => { })); }
public Channel HandleAccept(MooNetClient client, bnet.protocol.channel_invitation.AcceptInvitationRequest request) { if (!this._onGoingInvitations.ContainsKey(request.InvitationId)) { return(null); } var invitation = this._onGoingInvitations[request.InvitationId]; var channel = ChannelManager.GetChannelByEntityId(invitation.GetExtension(bnet.protocol.channel_invitation.Invitation.ChannelInvitation).ChannelDescription.ChannelId); channel.Join(client, request.ObjectId); // add invitee to channel -- so inviter and other members will also be notified too. var notification = bnet.protocol.channel_invitation.InvitationRemovedNotification.CreateBuilder().SetInvitation(invitation).SetReason((uint)InvitationRemoveReason.Accepted); this._onGoingInvitations.Remove(invitation.Id); // notify invitee and let him remove the handled invitation. client.MakeTargetedRPC(this, () => bnet.protocol.channel_invitation.ChannelInvitationNotify.CreateStub(client).NotifyReceivedInvitationRemoved(null, notification.Build(), callback => { })); return(channel); }
protected override void NotifySubscriptionAdded(MooNetClient client) { var operations = new List <bnet.protocol.presence.FieldOperation>(); // Banner configuration var fieldKey1 = FieldKeyHelper.Create(FieldKeyHelper.Program.D3, 2, 1, 0); var field1 = bnet.protocol.presence.Field.CreateBuilder().SetKey(fieldKey1).SetValue(bnet.protocol.attribute.Variant.CreateBuilder().SetMessageValue(client.Account.BannerConfiguration.ToByteString()).Build()).Build(); operations.Add(bnet.protocol.presence.FieldOperation.CreateBuilder().SetField(field1).Build()); // Class var fieldKey2 = FieldKeyHelper.Create(FieldKeyHelper.Program.D3, 3, 1, 0); var field2 = bnet.protocol.presence.Field.CreateBuilder().SetKey(fieldKey2).SetValue(bnet.protocol.attribute.Variant.CreateBuilder().SetIntValue(this.ClassID).Build()).Build(); operations.Add(bnet.protocol.presence.FieldOperation.CreateBuilder().SetField(field2).Build()); // Level var fieldKey3 = FieldKeyHelper.Create(FieldKeyHelper.Program.D3, 3, 2, 0); var field3 = bnet.protocol.presence.Field.CreateBuilder().SetKey(fieldKey3).SetValue(bnet.protocol.attribute.Variant.CreateBuilder().SetIntValue(this.Level).Build()).Build(); operations.Add(bnet.protocol.presence.FieldOperation.CreateBuilder().SetField(field3).Build()); // Equipment var fieldKey4 = FieldKeyHelper.Create(FieldKeyHelper.Program.D3, 3, 3, 0); var field4 = bnet.protocol.presence.Field.CreateBuilder().SetKey(fieldKey4).SetValue(bnet.protocol.attribute.Variant.CreateBuilder().SetMessageValue(this.Equipment.ToByteString()).Build()).Build(); operations.Add(bnet.protocol.presence.FieldOperation.CreateBuilder().SetField(field4).Build()); // Flags var fieldKey5 = FieldKeyHelper.Create(FieldKeyHelper.Program.D3, 3, 4, 0); var field5 = bnet.protocol.presence.Field.CreateBuilder().SetKey(fieldKey5).SetValue(bnet.protocol.attribute.Variant.CreateBuilder().SetIntValue((uint)(this.Flags | ToonFlags.AllUnknowns)).Build()).Build(); operations.Add(bnet.protocol.presence.FieldOperation.CreateBuilder().SetField(field5).Build()); // Name var fieldKey6 = FieldKeyHelper.Create(FieldKeyHelper.Program.BNet, 3, 2, 0); var field6 = bnet.protocol.presence.Field.CreateBuilder().SetKey(fieldKey6).SetValue(bnet.protocol.attribute.Variant.CreateBuilder().SetStringValue(this.Name + "#" + this.HashCodeString).Build()).Build(); operations.Add(bnet.protocol.presence.FieldOperation.CreateBuilder().SetField(field6).Build()); // Is it selected toon? var fieldKey7 = FieldKeyHelper.Create(FieldKeyHelper.Program.BNet, 3, 3, 0); var field7 = bnet.protocol.presence.Field.CreateBuilder().SetKey(fieldKey7).SetValue(bnet.protocol.attribute.Variant.CreateBuilder().SetBoolValue(this.IsSelected).Build()).Build(); operations.Add(bnet.protocol.presence.FieldOperation.CreateBuilder().SetField(field7).Build()); //AwayStatus - Available, Away, Busy var fieldKey10 = FieldKeyHelper.Create(FieldKeyHelper.Program.BNet, 3, 5, 0); var field10 = bnet.protocol.presence.Field.CreateBuilder().SetKey(fieldKey10).SetValue(bnet.protocol.attribute.Variant.CreateBuilder().SetIntValue((uint)(this.AwayStatus)).Build()).Build(); operations.Add(bnet.protocol.presence.FieldOperation.CreateBuilder().SetField(field10).Build()); // Program - FourCC "D3" var fieldKey8 = FieldKeyHelper.Create(FieldKeyHelper.Program.BNet, 3, 9, 0); var field8 = bnet.protocol.presence.Field.CreateBuilder().SetKey(fieldKey8).SetValue(bnet.protocol.attribute.Variant.CreateBuilder().SetFourccValue("D3").Build()).Build(); operations.Add(bnet.protocol.presence.FieldOperation.CreateBuilder().SetField(field8).Build()); // Unknown int - maybe highest completed act? /raist var fieldKey9 = FieldKeyHelper.Create(FieldKeyHelper.Program.BNet, 3, 10, 0); var field9 = bnet.protocol.presence.Field.CreateBuilder().SetKey(fieldKey9).SetValue(bnet.protocol.attribute.Variant.CreateBuilder().SetIntValue(0).Build()).Build(); operations.Add(bnet.protocol.presence.FieldOperation.CreateBuilder().SetField(field9).Build()); //Unknown string = always "NICKTEMPNAME" -Egris var fieldKey11 = FieldKeyHelper.Create(FieldKeyHelper.Program.BNet, 3, 12, 0); var field11 = bnet.protocol.presence.Field.CreateBuilder().SetKey(fieldKey11).SetValue(bnet.protocol.attribute.Variant.CreateBuilder().SetStringValue("NICKTEMPNAME").Build()).Build(); operations.Add(bnet.protocol.presence.FieldOperation.CreateBuilder().SetField(field11).Build()); // Create a presence.ChannelState var state = bnet.protocol.presence.ChannelState.CreateBuilder().SetEntityId(this.BnetEntityID).AddRangeFieldOperation(operations).Build(); // Embed in channel.ChannelState var channelState = bnet.protocol.channel.ChannelState.CreateBuilder().SetExtension(bnet.protocol.presence.ChannelState.Presence, state); // Put in AddNotification message var builder = bnet.protocol.channel.AddNotification.CreateBuilder().SetChannelState(channelState); // Make the RPC call client.MakeTargetedRPC(this, () => bnet.protocol.channel.ChannelSubscriber.CreateStub(client).NotifyAdd(null, builder.Build(), callback => { })); }
public void AddMember(MooNetClient client) { if (HasUser(client)) { Logger.Warn("Attempted to add client {0} to channel when it was already a member of the channel", client.Connection.RemoteEndPoint.ToString()); return; } var identity = client.GetIdentity(false, true, false); bool isOwner = client == this.Owner; var addedMember = new Member(identity, (isOwner) ? Member.Privilege.UnkCreator : Member.Privilege.UnkJoinedMember); //if (this.Members.Count > 0) //{ // addedMember.AddRoles((isOwner) ? Member.Role.PartyLeader : Member.Role.PartyMember, Member.Role.ChannelMember); //} //else //{ addedMember.AddRole((isOwner) ? Member.Role.ChannelCreator : Member.Role.ChannelMember); //} // This needs to be here so that the foreach below will also send to the client that was just added this.Members.Add(client, addedMember); // Cache the built state and member var channelState = this.State.ToBuilder(); if (this.Attributes.Count > 0) { channelState.AddRangeAttribute(this.Attributes.Values); } if (this.Invitations.Count > 0) { channelState.AddRangeInvitation(this.Invitations.Values); } // added member should recieve a NotifyAdd. var addNotification = bnet.protocol.channel.AddNotification.CreateBuilder() .SetChannelState(channelState.Build()) .SetSelf(addedMember.BnetMember) .AddRangeMember(this.Members.Values.ToList().Select(member => member.BnetMember).ToList()).Build(); client.MakeTargetedRPC(this, () => bnet.protocol.channel.ChannelSubscriber.CreateStub(client).NotifyAdd(null, addNotification, callback => { })); //send bnet,2,7 target = addedmember.gameaccount //this always follows channel.AddNotification var fieldKey = FieldKeyHelper.Create(FieldKeyHelper.Program.D3, FieldKeyHelper.OriginatingClass.GameAccount, 7, 0); var field = bnet.protocol.presence.Field.CreateBuilder().SetKey(fieldKey); field.SetValue(bnet.protocol.attribute.Variant.CreateBuilder().SetStringValue(client.Account.BnetEntityId.Low.ToString() + "#1").Build()); var operation = bnet.protocol.presence.FieldOperation.CreateBuilder().SetField(field.Build()).Build(); var state = bnet.protocol.presence.ChannelState.CreateBuilder().SetEntityId(client.Account.CurrentGameAccount.BnetEntityId).AddFieldOperation(operation).Build(); var channelStatePresense = bnet.protocol.channel.ChannelState.CreateBuilder().SetExtension(bnet.protocol.presence.ChannelState.Presence, state); var notification = bnet.protocol.channel.UpdateChannelStateNotification.CreateBuilder().SetStateChange(channelStatePresense).Build(); client.MakeTargetedRPC(client.Account.CurrentGameAccount, () => bnet.protocol.channel.ChannelSubscriber.CreateStub(client).NotifyUpdateChannelState(null, notification, callback => { })); if (this.IsGameChannel) { if (client.GameChannel != null) { Logger.Warn("Client {0} in game channel {1}, but joining game channel {2}.", client, client.GameChannel, this); } client.GameChannel = this; } else { if (client.PartyChannel != null) { Logger.Warn("Client {0} in party channel {1}, but joining party channel {2}.", client, client.PartyChannel, this); } client.PartyChannel = this; } client.CurrentChannel = this; // set clients current channel to one he just joined. if (this.Members.Count < 2) { return; } // other members should recieve a NotifyJoin. var joinNotification = bnet.protocol.channel.JoinNotification.CreateBuilder() .SetMember(addedMember.BnetMember).Build(); foreach (var pair in this.Members.Where(pair => pair.Value != addedMember)) // only send this to previous members of the channel. { pair.Key.MakeTargetedRPC(this, () => bnet.protocol.channel.ChannelSubscriber.CreateStub(pair.Key).NotifyJoin(null, joinNotification, callback => { })); } }