void OnAddUser(UserData data)
        {
            AgentPrivate agent = ScenePrivate.FindAgent(data.User);

            if (agent == null || !agent.IsValid)
            {
                return;
            }

            Sansar.Simulation.Quest quest = null;
            AgentInfo agentInfo           = null;

            try
            {
                agentInfo = agent.AgentInfo;

                var questData = WaitFor(QuestDefinition.GetQuest, agentInfo.SessionId) as QuestDefinition.GetQuestData;
                if (questData.Success)
                {
                    quest = questData.Quest;
                }
            }
            catch
            {
                Log.Write(LogLevel.Error, "Failed to get agent info, user may have left experience.");
                return;
            }

            if (quest != null)
            {
                OnAgentJoinExperience(agentInfo, quest);

                switch (quest.GetState())
                {
                case QuestState.None:
                    OnAgentQuestAvailable(agentInfo, quest);
                    break;

                case QuestState.Offered:
                    OnAgentOfferedQuest(agentInfo, quest);
                    break;

                case QuestState.Active:
                    OnAgentStartedQuest(agentInfo, quest);
                    break;

                case QuestState.Completed:
                    OnAgentCompletedQuest(agentInfo, quest);
                    break;
                }

                quest.Subscribe(QuestState.Offered, (QuestData d) =>
                {
                    OnAgentOfferedQuest(agentInfo, quest);
                });

                quest.Subscribe(QuestState.Active, (QuestData d) =>
                {
                    OnAgentStartedQuest(agentInfo, quest);
                });

                quest.Subscribe(QuestState.Completed, (QuestData d) =>
                {
                    OnAgentCompletedQuest(agentInfo, quest);
                });

                foreach (var objective in quest.Objectives)
                {
                    objective.Subscribe(ObjectiveState.Active, (ObjectiveData d) => ChatLogQuest(agentInfo.SessionId, quest));
                    objective.Subscribe(ObjectiveState.Locked, (ObjectiveData d) => ChatLogQuest(agentInfo.SessionId, quest));
                    objective.Subscribe(ObjectiveState.Completed, (ObjectiveData d) => ChatLogQuest(agentInfo.SessionId, quest));
                }

                if (OfferOnSceneEnter && (quest.GetState() == QuestState.None || quest.GetState() == QuestState.Offered))
                {
                    OfferToAgent(agentInfo.SessionId);
                }
            }
        }
 protected virtual void OnAgentJoinExperience(AgentInfo agentInfo, Sansar.Simulation.Quest quest)
 {
     ChatLog(agentInfo.SessionId, $"agent: {agentInfo.Name} joined experience.  quest: {quest.Definition.Title} state: {quest.GetState()}");
 }