// --------------------------------------------------------------------------------------------------------------------
//
// Demo code for Photon Chat in Unity.
// developer@exitgames.com
// --------------------------------------------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using Photon.Chat;
using Photon.Realtime;
using AuthenticationValues = Photon.Chat.AuthenticationValues;
#if PHOTON_UNITY_NETWORKING
using Photon.Pun;
#endif
namespace Photon.Chat.Demo
{
///
/// This simple Chat UI demonstrate basics usages of the Chat Api
///
///
/// The ChatClient basically lets you create any number of channels.
///
/// some friends are already set in the Chat demo "DemoChat-Scene", 'Joe', 'Jane' and 'Bob', simply log with them so that you can see the status changes in the Interface
///
/// Workflow:
/// Create ChatClient, Connect to a server with your AppID, Authenticate the user (apply a unique name,)
/// and subscribe to some channels.
/// Subscribe a channel before you publish to that channel!
///
///
/// Note:
/// Don't forget to call ChatClient.Service() on Update to keep the Chatclient operational.
///
public class ChatGui : MonoBehaviour, IChatClientListener
{
public string[] ChannelsToJoinOnConnect; // set in inspector. Demo channels to join automatically.
public string[] FriendsList;
public int HistoryLengthToFetch; // set in inspector. Up to a certain degree, previously sent messages can be fetched for context
public string UserName { get; set; }
private string selectedChannelName; // mainly used for GUI/input
public ChatClient chatClient;
#if !PHOTON_UNITY_NETWORKING
[SerializeField]
#endif
protected internal ChatAppSettings chatAppSettings;
public GameObject missingAppIdErrorPanel;
public GameObject ConnectingLabel;
public RectTransform ChatPanel; // set in inspector (to enable/disable panel)
public GameObject UserIdFormPanel;
public InputField InputFieldChat; // set in inspector
public Text CurrentChannelText; // set in inspector
public Toggle ChannelToggleToInstantiate; // set in inspector
public GameObject FriendListUiItemtoInstantiate;
private readonly Dictionary channelToggles = new Dictionary();
private readonly Dictionary friendListItemLUT = new Dictionary();
public bool ShowState = true;
public GameObject Title;
public Text StateText; // set in inspector
public Text UserIdText; // set in inspector
// private static string WelcomeText = "Welcome to chat. Type \\help to list commands.";
private static string HelpText = "\n -- HELP --\n" +
"To subscribe to channel(s) (channelnames are case sensitive) : \n" +
"\t\\subscribe\n" +
"\tor\n" +
"\t\\s\n" +
"\n" +
"To leave channel(s):\n" +
"\t\\unsubscribe\n" +
"\tor\n" +
"\t\\u\n" +
"\n" +
"To switch the active channel\n" +
"\t\\join\n" +
"\tor\n" +
"\t\\j\n" +
"\n" +
"To send a private message: (username are case sensitive)\n" +
"\t\\msg\n" +
"\n" +
"To change status:\n" +
"\t\\state\n" +
"0 = Offline " +
"1 = Invisible " +
"2 = Online " +
"3 = Away \n" +
"4 = Do not disturb " +
"5 = Looking For Group " +
"6 = Playing" +
"\n\n" +
"To clear the current chat tab (private chats get closed):\n" +
"\t\\clear";
public void Start()
{
DontDestroyOnLoad(this.gameObject);
this.UserIdText.text = "";
this.StateText.text = "";
this.StateText.gameObject.SetActive(true);
this.UserIdText.gameObject.SetActive(true);
this.Title.SetActive(true);
this.ChatPanel.gameObject.SetActive(false);
this.ConnectingLabel.SetActive(false);
if (string.IsNullOrEmpty(this.UserName))
{
this.UserName = "user" + Environment.TickCount%99; //made-up username
}
#if PHOTON_UNITY_NETWORKING
this.chatAppSettings = PhotonNetwork.PhotonServerSettings.AppSettings.GetChatSettings();
#endif
bool appIdPresent = !string.IsNullOrEmpty(this.chatAppSettings.AppIdChat);
this.missingAppIdErrorPanel.SetActive(!appIdPresent);
this.UserIdFormPanel.gameObject.SetActive(appIdPresent);
if (!appIdPresent)
{
Debug.LogError("You need to set the chat app ID in the PhotonServerSettings file in order to continue.");
}
}
public void Connect()
{
this.UserIdFormPanel.gameObject.SetActive(false);
this.chatClient = new ChatClient(this);
#if !UNITY_WEBGL
this.chatClient.UseBackgroundWorkerForSending = true;
#endif
this.chatClient.AuthValues = new AuthenticationValues(this.UserName);
this.chatClient.ConnectUsingSettings(this.chatAppSettings);
this.ChannelToggleToInstantiate.gameObject.SetActive(false);
Debug.Log("Connecting as: " + this.UserName);
this.ConnectingLabel.SetActive(true);
}
/// To avoid that the Editor becomes unresponsive, disconnect all Photon connections in OnDestroy.
public void OnDestroy()
{
if (this.chatClient != null)
{
this.chatClient.Disconnect();
}
}
/// To avoid that the Editor becomes unresponsive, disconnect all Photon connections in OnApplicationQuit.
public void OnApplicationQuit()
{
if (this.chatClient != null)
{
this.chatClient.Disconnect();
}
}
public void Update()
{
if (this.chatClient != null)
{
this.chatClient.Service(); // make sure to call this regularly! it limits effort internally, so calling often is ok!
}
// check if we are missing context, which means we got kicked out to get back to the Photon Demo hub.
if ( this.StateText == null)
{
Destroy(this.gameObject);
return;
}
this.StateText.gameObject.SetActive(this.ShowState); // this could be handled more elegantly, but for the demo it's ok.
}
public void OnEnterSend()
{
if (Input.GetKey(KeyCode.Return) || Input.GetKey(KeyCode.KeypadEnter))
{
this.SendChatMessage(this.InputFieldChat.text);
this.InputFieldChat.text = "";
}
}
public void OnClickSend()
{
if (this.InputFieldChat != null)
{
this.SendChatMessage(this.InputFieldChat.text);
this.InputFieldChat.text = "";
}
}
public int TestLength = 2048;
private byte[] testBytes = new byte[2048];
private void SendChatMessage(string inputLine)
{
if (string.IsNullOrEmpty(inputLine))
{
return;
}
if ("test".Equals(inputLine))
{
if (this.TestLength != this.testBytes.Length)
{
this.testBytes = new byte[this.TestLength];
}
this.chatClient.SendPrivateMessage(this.chatClient.AuthValues.UserId, this.testBytes, true);
}
bool doingPrivateChat = this.chatClient.PrivateChannels.ContainsKey(this.selectedChannelName);
string privateChatTarget = string.Empty;
if (doingPrivateChat)
{
// the channel name for a private conversation is (on the client!!) always composed of both user's IDs: "this:remote"
// so the remote ID is simple to figure out
string[] splitNames = this.selectedChannelName.Split(new char[] { ':' });
privateChatTarget = splitNames[1];
}
//UnityEngine.Debug.Log("selectedChannelName: " + selectedChannelName + " doingPrivateChat: " + doingPrivateChat + " privateChatTarget: " + privateChatTarget);
if (inputLine[0].Equals('\\'))
{
string[] tokens = inputLine.Split(new char[] {' '}, 2);
if (tokens[0].Equals("\\help"))
{
this.PostHelpToCurrentChannel();
}
if (tokens[0].Equals("\\state"))
{
int newState = 0;
List messages = new List();
messages.Add ("i am state " + newState);
string[] subtokens = tokens[1].Split(new char[] {' ', ','});
if (subtokens.Length > 0)
{
newState = int.Parse(subtokens[0]);
}
if (subtokens.Length > 1)
{
messages.Add(subtokens[1]);
}
this.chatClient.SetOnlineStatus(newState,messages.ToArray()); // this is how you set your own state and (any) message
}
else if ((tokens[0].Equals("\\subscribe") || tokens[0].Equals("\\s")) && !string.IsNullOrEmpty(tokens[1]))
{
this.chatClient.Subscribe(tokens[1].Split(new char[] {' ', ','}));
}
else if ((tokens[0].Equals("\\unsubscribe") || tokens[0].Equals("\\u")) && !string.IsNullOrEmpty(tokens[1]))
{
this.chatClient.Unsubscribe(tokens[1].Split(new char[] {' ', ','}));
}
else if (tokens[0].Equals("\\clear"))
{
if (doingPrivateChat)
{
this.chatClient.PrivateChannels.Remove(this.selectedChannelName);
}
else
{
ChatChannel channel;
if (this.chatClient.TryGetChannel(this.selectedChannelName, doingPrivateChat, out channel))
{
channel.ClearMessages();
}
}
}
else if (tokens[0].Equals("\\msg") && !string.IsNullOrEmpty(tokens[1]))
{
string[] subtokens = tokens[1].Split(new char[] {' ', ','}, 2);
if (subtokens.Length < 2) return;
string targetUser = subtokens[0];
string message = subtokens[1];
this.chatClient.SendPrivateMessage(targetUser, message);
}
else if ((tokens[0].Equals("\\join") || tokens[0].Equals("\\j")) && !string.IsNullOrEmpty(tokens[1]))
{
string[] subtokens = tokens[1].Split(new char[] { ' ', ',' }, 2);
// If we are already subscribed to the channel we directly switch to it, otherwise we subscribe to it first and then switch to it implicitly
if (this.channelToggles.ContainsKey(subtokens[0]))
{
this.ShowChannel(subtokens[0]);
}
else
{
this.chatClient.Subscribe(new string[] { subtokens[0] });
}
}
else
{
Debug.Log("The command '" + tokens[0] + "' is invalid.");
}
}
else
{
if (doingPrivateChat)
{
this.chatClient.SendPrivateMessage(privateChatTarget, inputLine);
}
else
{
this.chatClient.PublishMessage(this.selectedChannelName, inputLine);
}
}
}
public void PostHelpToCurrentChannel()
{
this.CurrentChannelText.text += HelpText;
}
public void DebugReturn(ExitGames.Client.Photon.DebugLevel level, string message)
{
if (level == ExitGames.Client.Photon.DebugLevel.ERROR)
{
Debug.LogError(message);
}
else if (level == ExitGames.Client.Photon.DebugLevel.WARNING)
{
Debug.LogWarning(message);
}
else
{
Debug.Log(message);
}
}
public void OnConnected()
{
if (this.ChannelsToJoinOnConnect != null && this.ChannelsToJoinOnConnect.Length > 0)
{
this.chatClient.Subscribe(this.ChannelsToJoinOnConnect, this.HistoryLengthToFetch);
}
this.ConnectingLabel.SetActive(false);
this.UserIdText.text = "Connected as "+ this.UserName;
this.ChatPanel.gameObject.SetActive(true);
if (this.FriendsList!=null && this.FriendsList.Length>0)
{
this.chatClient.AddFriends(this.FriendsList); // Add some users to the server-list to get their status updates
// add to the UI as well
foreach(string _friend in this.FriendsList)
{
if (this.FriendListUiItemtoInstantiate != null && _friend!= this.UserName)
{
this.InstantiateFriendButton(_friend);
}
}
}
if (this.FriendListUiItemtoInstantiate != null)
{
this.FriendListUiItemtoInstantiate.SetActive(false);
}
this.chatClient.SetOnlineStatus(ChatUserStatus.Online); // You can set your online state (without a mesage).
}
public void OnDisconnected()
{
this.ConnectingLabel.SetActive(false);
}
public void OnChatStateChange(ChatState state)
{
// use OnConnected() and OnDisconnected()
// this method might become more useful in the future, when more complex states are being used.
this.StateText.text = state.ToString();
}
public void OnSubscribed(string[] channels, bool[] results)
{
// in this demo, we simply send a message into each channel. This is NOT a must have!
foreach (string channel in channels)
{
this.chatClient.PublishMessage(channel, "says 'hi'."); // you don't HAVE to send a msg on join but you could.
if (this.ChannelToggleToInstantiate != null)
{
this.InstantiateChannelButton(channel);
}
}
Debug.Log("OnSubscribed: " + string.Join(", ", channels));
/*
// select first subscribed channel in alphabetical order
if (this.chatClient.PublicChannels.Count > 0)
{
var l = new List(this.chatClient.PublicChannels.Keys);
l.Sort();
string selected = l[0];
if (this.channelToggles.ContainsKey(selected))
{
ShowChannel(selected);
foreach (var c in this.channelToggles)
{
c.Value.isOn = false;
}
this.channelToggles[selected].isOn = true;
AddMessageToSelectedChannel(WelcomeText);
}
}
*/
// Switch to the first newly created channel
this.ShowChannel(channels[0]);
}
///
public void OnSubscribed(string channel, string[] users, Dictionary