ChatChannel.cs 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. // ----------------------------------------------------------------------------------------------------------------------
  2. // <summary>The Photon Chat Api enables clients to connect to a chat server and communicate with other clients.</summary>
  3. // <remarks>ChatClient is the main class of this api.</remarks>
  4. // <copyright company="Exit Games GmbH">Photon Chat Api - Copyright (C) 2014 Exit Games GmbH</copyright>
  5. // ----------------------------------------------------------------------------------------------------------------------
  6. #if UNITY_4_7 || UNITY_5 || UNITY_5_3_OR_NEWER
  7. #define SUPPORTED_UNITY
  8. #endif
  9. namespace Photon.Chat
  10. {
  11. using System.Collections.Generic;
  12. using System.Text;
  13. #if SUPPORTED_UNITY || NETFX_CORE
  14. using Hashtable = ExitGames.Client.Photon.Hashtable;
  15. using SupportClass = ExitGames.Client.Photon.SupportClass;
  16. #endif
  17. /// <summary>
  18. /// A channel of communication in Photon Chat, updated by ChatClient and provided as READ ONLY.
  19. /// </summary>
  20. /// <remarks>
  21. /// Contains messages and senders to use (read!) and display by your GUI.
  22. /// Access these by:
  23. /// ChatClient.PublicChannels
  24. /// ChatClient.PrivateChannels
  25. /// </remarks>
  26. public class ChatChannel
  27. {
  28. /// <summary>Name of the channel (used to subscribe and unsubscribe).</summary>
  29. public readonly string Name;
  30. /// <summary>Senders of messages in chronological order. Senders and Messages refer to each other by index. Senders[x] is the sender of Messages[x].</summary>
  31. public readonly List<string> Senders = new List<string>();
  32. /// <summary>Messages in chronological order. Senders and Messages refer to each other by index. Senders[x] is the sender of Messages[x].</summary>
  33. public readonly List<object> Messages = new List<object>();
  34. /// <summary>If greater than 0, this channel will limit the number of messages, that it caches locally.</summary>
  35. public int MessageLimit;
  36. /// <summary>Unique channel ID.</summary>
  37. public int ChannelID;
  38. /// <summary>Is this a private 1:1 channel?</summary>
  39. public bool IsPrivate { get; protected internal set; }
  40. /// <summary>Count of messages this client still buffers/knows for this channel.</summary>
  41. public int MessageCount { get { return this.Messages.Count; } }
  42. /// <summary>
  43. /// ID of the last message received.
  44. /// </summary>
  45. public int LastMsgId { get; protected set; }
  46. private Dictionary<object, object> properties;
  47. /// <summary>Whether or not this channel keeps track of the list of its subscribers.</summary>
  48. public bool PublishSubscribers { get; protected set; }
  49. /// <summary>Maximum number of channel subscribers. 0 means infinite.</summary>
  50. public int MaxSubscribers { get; protected set; }
  51. /// <summary>Subscribed users.</summary>
  52. public readonly HashSet<string> Subscribers = new HashSet<string>();
  53. /// <summary> Properties of subscribers </summary>
  54. private Dictionary<string, Dictionary<object, object>> usersProperties;
  55. /// <summary>Used internally to create new channels. This does NOT create a channel on the server! Use ChatClient.Subscribe.</summary>
  56. public ChatChannel(string name)
  57. {
  58. this.Name = name;
  59. }
  60. /// <summary>Used internally to add messages to this channel.</summary>
  61. public void Add(string sender, object message, int msgId)
  62. {
  63. this.Senders.Add(sender);
  64. this.Messages.Add(message);
  65. this.LastMsgId = msgId;
  66. this.TruncateMessages();
  67. }
  68. /// <summary>Used internally to add messages to this channel.</summary>
  69. public void Add(string[] senders, object[] messages, int lastMsgId)
  70. {
  71. this.Senders.AddRange(senders);
  72. this.Messages.AddRange(messages);
  73. this.LastMsgId = lastMsgId;
  74. this.TruncateMessages();
  75. }
  76. /// <summary>Reduces the number of locally cached messages in this channel to the MessageLimit (if set).</summary>
  77. public void TruncateMessages()
  78. {
  79. if (this.MessageLimit <= 0 || this.Messages.Count <= this.MessageLimit)
  80. {
  81. return;
  82. }
  83. int excessCount = this.Messages.Count - this.MessageLimit;
  84. this.Senders.RemoveRange(0, excessCount);
  85. this.Messages.RemoveRange(0, excessCount);
  86. }
  87. /// <summary>Clear the local cache of messages currently stored. This frees memory but doesn't affect the server.</summary>
  88. public void ClearMessages()
  89. {
  90. this.Senders.Clear();
  91. this.Messages.Clear();
  92. }
  93. /// <summary>Provides a string-representation of all messages in this channel.</summary>
  94. /// <returns>All known messages in format "Sender: Message", line by line.</returns>
  95. public string ToStringMessages()
  96. {
  97. StringBuilder txt = new StringBuilder();
  98. for (int i = 0; i < this.Messages.Count; i++)
  99. {
  100. txt.AppendLine(string.Format("{0}: {1}", this.Senders[i], this.Messages[i]));
  101. }
  102. return txt.ToString();
  103. }
  104. internal void ReadChannelProperties(Dictionary<object, object> newProperties)
  105. {
  106. if (newProperties != null && newProperties.Count > 0)
  107. {
  108. if (this.properties == null)
  109. {
  110. this.properties = new Dictionary<object, object>(newProperties.Count);
  111. }
  112. foreach (var pair in newProperties)
  113. {
  114. if (pair.Value == null)
  115. {
  116. this.properties.Remove(pair.Key);
  117. }
  118. else
  119. {
  120. this.properties[pair.Key] = pair.Value;
  121. }
  122. }
  123. object temp;
  124. if (this.properties.TryGetValue(ChannelWellKnownProperties.PublishSubscribers, out temp))
  125. {
  126. this.PublishSubscribers = (bool)temp;
  127. }
  128. if (this.properties.TryGetValue(ChannelWellKnownProperties.MaxSubscribers, out temp))
  129. {
  130. this.MaxSubscribers = (int)temp;
  131. }
  132. }
  133. }
  134. internal bool AddSubscribers(string[] users)
  135. {
  136. if (users == null)
  137. {
  138. return false;
  139. }
  140. bool result = true;
  141. for (int i = 0; i < users.Length; i++)
  142. {
  143. if (!this.Subscribers.Add(users[i]))
  144. {
  145. result = false;
  146. }
  147. }
  148. return result;
  149. }
  150. internal bool AddSubscriber(string userId)
  151. {
  152. return this.Subscribers.Add(userId);
  153. }
  154. internal bool RemoveSubscriber(string userId)
  155. {
  156. if (this.usersProperties != null)
  157. {
  158. this.usersProperties.Remove(userId);
  159. }
  160. return this.Subscribers.Remove(userId);
  161. }
  162. #if CHAT_EXTENDED
  163. internal void ReadUserProperties(string userId, Dictionary<object, object> changedProperties)
  164. {
  165. if (this.usersProperties == null)
  166. {
  167. this.usersProperties = new Dictionary<string, Dictionary<object, object>>();
  168. }
  169. Dictionary<object, object> userProperties;
  170. if (!this.usersProperties.TryGetValue(userId, out userProperties))
  171. {
  172. userProperties = new Dictionary<object, object>();
  173. this.usersProperties.Add(userId, userProperties);
  174. }
  175. foreach (var property in changedProperties)
  176. {
  177. //UnityEngine.Debug.LogFormat("User {0} property {1} = {2}", userId, property.Key, property.Value);
  178. if (property.Value == null)
  179. {
  180. userProperties.Remove(property.Key);
  181. }
  182. else
  183. {
  184. userProperties[property.Key] = property.Value;
  185. }
  186. }
  187. }
  188. internal bool TryGetChannelProperty<T>(object propertyKey, out T propertyValue)
  189. {
  190. propertyValue = default;
  191. object temp;
  192. if (properties != null && properties.TryGetValue(propertyKey, out temp) && temp is T)
  193. {
  194. propertyValue = (T)temp;
  195. return true;
  196. }
  197. return false;
  198. }
  199. internal bool TryGetUserProperty<T>(string userId, object propertyKey, out T propertyValue)
  200. {
  201. propertyValue = default;
  202. object temp;
  203. Dictionary<object, object> userProperties;
  204. if (this.usersProperties != null && usersProperties.TryGetValue(userId, out userProperties) && userProperties.TryGetValue(propertyKey, out temp) && temp is T)
  205. {
  206. propertyValue = (T)temp;
  207. return true;
  208. }
  209. return false;
  210. }
  211. public bool TryGetCustomChannelProperty<T>(string propertyKey, out T propertyValue)
  212. {
  213. return this.TryGetChannelProperty(propertyKey, out propertyValue);
  214. }
  215. public bool TryGetCustomUserProperty<T>(string userId, string propertyKey, out T propertyValue)
  216. {
  217. return this.TryGetUserProperty(userId, propertyKey, out propertyValue);
  218. }
  219. #endif
  220. }
  221. }