예제 #1
0
        public void JoinRoom(string roomToJoin, string userName)
        {
            Debug.Assert(!string.IsNullOrEmpty(userName), "Username cannot be null or empty");
            RoomName      = roomToJoin;
            localUserName = userName;

            if (NeuraCore.Instance.socket == null || !NeuraCore.Instance.socket.isConnected)
            {
                print("Not connected, trying to auto connect");
                OnConnected += AutoJoinRoom;
                Connect();
                return;
            }
            if (inRoom)
            {
                print("Cannot join room when already in one");
                return;
            }
            globalState                  = new RoomStateGen();
            requestedSiteDrive           = "";
            requestedPoi                 = new TargetPlacementObject();
            requestedAnnotation          = new AnnotationObject();
            requestedAnnotationDeletions = new List <AnnotationObject>();
            NeuraCore.Instance.JoinRoom(roomToJoin, userName);
        }
예제 #2
0
 public void CleanState()
 {
     NeuraCore.Instance.ForceClosed();
     foreach (KeyValuePair <int, ITrackable> trackable in trackers)
     {
         if (trackable.Value != null)
         {
             Destroy(((MonoBehaviour)trackable.Value).gameObject);
         }
     }
     trackers    = new Dictionary <int, ITrackable>();
     globalState = new RoomStateGen();
 }
예제 #3
0
        public IEnumerator Start()
        {
            globalState = new RoomStateGen();
            WaitForEndOfFrame w = new WaitForEndOfFrame();

            NeuraCore.Instance.OnError   += ErrorHandler;
            NeuraCore.Instance.OnClose   += CloseHandler;
            NeuraCore.Instance.OnOpen    += OpenHandler;
            NeuraCore.Instance.OnMessage += MessageHandler;
            InvokeRepeating("RefreshRoomList", 0.1f, 2f);
            while (NeuraCore.Instance.socket == null)
            {
                yield return(w);
            }
            updateTime = 1f / NeuraCore.Instance.config.UpdateHz;
        }
예제 #4
0
        public void JoinRoom(string roomToJoin, string userName)
        {
            Debug.Assert(!string.IsNullOrEmpty(userName), "Username cannot be null or empty");
            RoomName      = roomToJoin;
            localUserName = userName;

            if (NeuraCore.Instance.socket == null || !NeuraCore.Instance.socket.isConnected)
            {
                print("Not connected, trying to auto connect");
                OnConnected += AutoJoinRoom;
                Connect();
                return;
            }
            if (inRoom)
            {
                print("Cannot join room when already in one");
                return;
            }
            globalState = new RoomStateGen();
            NeuraCore.Instance.JoinRoom(roomToJoin, userName);
        }
예제 #5
0
        /// <summary>
        /// Creates a local copy of a remote object
        /// </summary>
        /// <param name="newObj"></param>
        private void CreateObject(RoomObjectObj newObj, RoomStateGen state)
        {
            print("Creating object " + newObj.name);
            ITrackable tracker;
            GameObject go;

            if (prefabNames.Contains(newObj.prefab))
            {
                go      = Instantiate <GameObject>(prefabs[prefabNames.IndexOf(newObj.prefab)]);
                tracker = go.GetComponent <ITrackable>();
            }
            else
            {
                go      = new GameObject("Prefab " + newObj.prefab + " not found");
                tracker = go.AddComponent <NStateTracker>();
            }
            tracker.id     = newObj.id;
            tracker.prefab = newObj.prefab;
            trackers.Add(tracker.id, tracker);
            state.objects.Add(newObj);
            roomCreatedObjects.Add(go);
            tracker.UpdateFromRoomObject(newObj);
        }
예제 #6
0
        private void MessageHandler(object sender, MessageEventArgs e)
        {
            var bb = new ByteBuffer(e.RawData);

            ServerMessage msg = ServerMessage.GetRootAsServerMessage(bb);

            switch (msg.Type)
            {
            case msgType.RoomStateUpdate:
                //handle message
                if (msg.Data <StateUpdate>() == null)
                {
                    print("empty state update. this should not happen");
                    return;
                }
                StateUpdate?stateUpdate = msg.Data <StateUpdate>();
                if (stateUpdate != null)
                {
                    StateUpdate sup =
                        stateUpdate.Value;
                    UpdateLocalState(sup);
                }
                break;

            case msgType.SocketReady:
                print("connected to server");
                StringData?stringData = msg.Data <StringData>();
                if (stringData != null)
                {
                    OnConnectedArgs connectedEventArgs = new OnConnectedArgs
                    {
                        sid = stringData.Value.Data,
                    };
                    NeuraCore.Instance.sid = connectedEventArgs.sid;
                }
                if (OnConnected != null)
                {
                    OnConnected.Invoke(this, new EventArgs());
                }
                break;

            case msgType.SocketRoomJoined:
            {
                print("Joined room ");
                inRoom = true;
                UsersInRoom.Add(localUserName);
                NeuraCore.Instance.connectionState = ConnectionState.Connected;
                if (msg.DataType != Transport.FlatBuffers.msg.StateUpdate)
                {
                    return;
                }
                if (msg.Data <StateUpdate>().HasValue)
                {
                    var initStateSUP = msg.Data <StateUpdate>().Value;
                    UpdateLocalState(initStateSUP);
                }
                if (OnRoomJoined != null)
                {
                    OnRoomJoined.Invoke(this, RoomName);
                }
            }
            break;

            case msgType.RoomCreated:
                StringData?createMsg = msg.Data <StringData>();
                if (createMsg != null)
                {
                    //var rmName = createMsg.Value.Data;
                    //RoomName = rmName;
                    print("room " + RoomName + " has been created");
                    if (OnRoomCreated != null)
                    {
                        OnRoomCreated.Invoke(this, RoomName);
                    }
                    if (string.IsNullOrEmpty((globalState ?? (globalState = new RoomStateGen())).siteDrive))
                    {
                        //Handle things like critical room state here to make sure that the initial state sent has the required information
                        //For onsight the site drive is of critical importance so we are setting it below
                        //globalState.siteDrive = string.IsNullOrEmpty(requestedSiteDrive)
                        //    ? MultiUserConnectionManager.Instance.CurrentSiteDriveJSON
                        //    : requestedSiteDrive;
                    }
                    Debug.Assert(!string.IsNullOrEmpty(globalState.siteDrive));

                    NeuraCore.Instance.SendInitialState(ServerMessageFactory.BuildMessage(globalState));
                }
                break;

            case msgType.RoomUserOnjoined:
                StringData?joinedMsg = msg.Data <StringData>();
                if (joinedMsg != null)
                {
                    var user = joinedMsg.Value.Data;
                    print(user + " has joined the room");
                    UsersInRoom.Add(user);
                    if (OnUserJoined != null)
                    {
                        OnUserJoined.Invoke(this, new UserJoinedEventArgs
                        {
                            username = user
                        });
                    }
                }
                break;

            case msgType.RoomUserOnLeft:
                StringData?leftMsg = msg.Data <StringData>();
                if (leftMsg != null)
                {
                    var user = leftMsg.Value.Data;
                    print(user + " has left the room");
                    if (UsersInRoom.Contains(user))
                    {
                        UsersInRoom.Remove(user);
                    }
                    if (OnUserLeft != null)
                    {
                        OnUserLeft.Invoke(this, new UserLeftEventArgs
                        {
                            username = user
                        });
                    }
                }
                break;
            }
        }
예제 #7
0
        /// <summary>
        /// Upload any changes in objects owned by the local player, in scene properties, or scene objects
        /// </summary>
        private void UploadGlobalState()
        {
            lastUpdate = Time.realtimeSinceStartup;
            if (!inRoom)
            {
                return;
            }

            List <RoomObjectObj> localObjectsUpdate = new List <RoomObjectObj>();

            StateUpdateObject diffState = null;

            #region Object Updates

            if (globalState.objects != null)
            {
                foreach (RoomObjectObj obj in globalState.objects)
                {
                    if (!trackers[obj.id].isLocal)
                    {
                        continue;
                    }
                    if (!CompareObjects(obj, trackers[obj.id].ToRoomObject()))
                    {
                        localObjectsUpdate.Add(trackers[obj.id].ToRoomObject());
                    }
                }

                //update the local copy of the global state with the new values for player controlled and scene objects
                for (int i = 0; i < localObjectsUpdate.Count; i++)
                {
                    globalState.objects[globalState.objects.IndexOf(localObjectsUpdate[i])] = localObjectsUpdate[i];
                }

                if (localObjectsUpdate.Count != 0 || newRoomObjects.Count != 0)
                {
                    diffState = new StateUpdateObject {
                        update = localObjectsUpdate
                    };
                    if (newRoomObjects.Count > 0)
                    {
                        diffState.create = newRoomObjects;
                    }


                    newRoomObjects = new List <RoomObjectObj>();
                }
            }
            else
            {
                print("globalState has no objects");
            }


            #endregion

            #region Property Updates

            if (!string.IsNullOrEmpty(requestedSiteDrive)) //update scene
            {
                print("site drive changed in global");
                var mutState = diffState ?? (diffState = new StateUpdateObject());
                mutState.siteDrive = requestedSiteDrive;
                requestedSiteDrive = "";
                oldSiteDrive       = "";
            }

            if (requestedPoi.isValid)
            {
                print("Setting requested poi");
                var mutState = diffState ?? (diffState = new StateUpdateObject());
                mutState.PlacePoi(requestedPoi);
                requestedPoi.isValid = false;
            }

            if (requestedAnnotation.isValid)
            {
                print("Adding requested annotation");
                var mutState = diffState ?? (diffState = new StateUpdateObject());
                mutState.AddAnnotation(requestedAnnotation);
                requestedAnnotation.isValid = false;
            }
            if (requestedAnnotationDeletions != null)
            {
                var mutState = diffState ?? (diffState = new StateUpdateObject());
                for (int i = 0; i < requestedAnnotationDeletions.Count; i++)
                {
                    var del = requestedAnnotationDeletions[i];
                    del.positions = new UnityEngine.Vector3[0];
                    del.isValid   = true;
                    mutState.AddAnnotation(del);
                }
                requestedAnnotationDeletions = null;
            }

            #endregion

            if (diffState != null
                ) //Serialize the updates to json and pass them to the NeuraCore to be sent to the server
            {
                NeuraCore.Instance.SetUpdate(ServerMessageFactory.BuildMessage(diffState));
            }
            //Find all local owned and scene objects that have changed since the last tick
            oldStateGen = new RoomStateGen(globalState);
        }
예제 #8
0
        /// <summary>
        /// Updates the local copy of the global state via server delta
        /// </summary>
        /// <param name="serverUpdate">changes to the global state since last server tick</param>
        private void UpdateLocalState(StateUpdate serverUpdate)
        {
            RoomStateGen newRoomState = new RoomStateGen(globalState);

            #region properties update

            bool propsChanged  = false;
            bool isSceneUpdate = false;
            if (!string.IsNullOrEmpty(serverUpdate.SiteDrive))
            {
                propsChanged  = true;
                isSceneUpdate = true;
            }
            else
            {
                if (serverUpdate.AnnotationsLength > 0)
                {
                    propsChanged = true;
                }
                if (serverUpdate.Poi.HasValue)
                {
                    propsChanged = true;
                }
            }
            if (propsChanged)
            {
                if (isSceneUpdate)
                {
                    if (OnPropertiesChanged != null)
                    {
                        OnPropertiesChanged.Invoke(this, serverUpdate);
                    }
                }
                else
                {
                    serverUpdate.Debounce(this, props =>
                    {
                        if (OnPropertiesChanged != null)
                        {
                            OnPropertiesChanged.Invoke(this, props);
                        }
                    }, isSceneUpdate);
                }
            }

            #endregion

            if (serverUpdate.DeleteLength > 0) //delete these object ids from the global state
            {
                print("Deleting " + serverUpdate.DeleteLength + " objects");
                for (int i = 0; i < serverUpdate.DeleteLength; i++)
                {
                    if (newRoomState.objects.All(tr => tr.id != serverUpdate.Delete(i)))
                    {
                        print("object to delete not found in global state " + serverUpdate.Delete(i));
                        continue;
                    }
                    newRoomState.objects.Remove(globalState.objects.Single(o => o.id == serverUpdate.Delete(i)));
                    if (trackers.ContainsKey(serverUpdate.Delete(i)) && trackers[serverUpdate.Delete(i)] != null)
                    {
                        Destroy(((MonoBehaviour)trackers[serverUpdate.Delete(i)]).gameObject);
                    }
                    else
                    {
                        print("Could not find game object to destroy" + serverUpdate.Delete(i));
                    }
                }
            }
            if (serverUpdate.CreateLength > 0) //create these objects and add them to the global state
            {
                for (int i = 0; i < serverUpdate.CreateLength; i++)
                {
                    if (!serverUpdate.Create(i).HasValue)
                    {
                        print("Malformed create message");
                        continue;
                    }
                    if (!trackers.ContainsKey(serverUpdate.Create(i).Value.Id))
                    {
                        CreateObject(serverUpdate.Create(i).Value, newRoomState);

                        //if (newRoomState.objects.Contains(serverUpdate.Create(i).Value))
                        //continue;
                    }
                    else
                    {
                        print("Object " + serverUpdate.Create(i).Value.Id + " already exists");
                    }
                    //else
                    //{
                    //  if (newRoomState.objects.Any(tr => tr.id == serverUpdate.Create(i).Value.Id))
                    //    newRoomState.objects.Remove(newRoomState.objects.Single(o => o.id == serverUpdate.Create(i).Value.Id));
                    //  var oldObj = (MonoBehaviour) trackers[serverUpdate.Create(i).Value.Id];
                    //  if (oldObj) Destroy(oldObj.gameObject);
                    //  trackers.Remove(serverUpdate.Create(i).Value.Id);
                    //}
                    //CreateObject(serverUpdate.Create(i).Value, newRoomState);
                }
            }
            if (serverUpdate.UpdateLength > 0)
            {
                for (int i = 0; i < serverUpdate.UpdateLength; i++)
                {
                    if (!serverUpdate.Update(i).HasValue)
                    {
                        continue;
                    }
                    if (!trackers.ContainsKey(serverUpdate.Update(i).Value.Id))
                    {
                        Debug.Log("Object created from update. please use the create function instead");
                        //CreateObject(serverUpdate.Update(i).Value, newRoomState);
                        continue;
                    }
                    trackers[serverUpdate.Update(i).Value.Id].UpdateFromRoomObject(serverUpdate.Update(i).Value);
                }
            }
            oldStateGen = new RoomStateGen(globalState);
            globalState = newRoomState;
        }
예제 #9
0
        /// <summary>
        /// Upload any changes in objects owned by the local player, in scene properties, or scene objects
        /// </summary>
        private void UploadGlobalState()
        {
            lastUpdate = Time.realtimeSinceStartup;
            if (!inRoom)
            {
                return;
            }

            List <RoomObjectObj> localObjectsUpdate = new List <RoomObjectObj>();

            StateUpdateObject diffState = null;

            #region Object Updates

            if (globalState.objects != null)
            {
                foreach (RoomObjectObj obj in globalState.objects)
                {
                    if (!trackers[obj.id].isLocal)
                    {
                        continue;
                    }
                    if (!CompareObjects(obj, trackers[obj.id].ToRoomObject()))
                    {
                        localObjectsUpdate.Add(trackers[obj.id].ToRoomObject());
                    }
                }

                //update the local copy of the global state with the new values for player controlled and scene objects
                for (int i = 0; i < localObjectsUpdate.Count; i++)
                {
                    globalState.objects[globalState.objects.IndexOf(localObjectsUpdate[i])] = localObjectsUpdate[i];
                }

                if (localObjectsUpdate.Count != 0 || newRoomObjects.Count != 0)
                {
                    diffState = new StateUpdateObject {
                        update = localObjectsUpdate
                    };
                    if (newRoomObjects.Count > 0)
                    {
                        diffState.create = newRoomObjects;
                    }


                    newRoomObjects = new List <RoomObjectObj>();
                }
            }
            else
            {
                print("globalState has no objects");
            }


            #endregion

            #region Property Updates

            #endregion

            if (diffState != null
                ) //Serialize the updates to json and pass them to the NeuraCore to be sent to the server
            {
                NeuraCore.Instance.SetUpdate(ServerMessageFactory.BuildMessage(diffState));
            }
            //Find all local owned and scene objects that have changed since the last tick
            oldStateGen = new RoomStateGen(globalState);
        }
예제 #10
0
        /// <summary>
        /// Updates the local copy of the global state via server delta
        /// </summary>
        /// <param name="serverUpdate">changes to the global state since last server tick</param>
        private void UpdateLocalState(StateUpdate serverUpdate)
        {
            RoomStateGen newRoomState = new RoomStateGen(globalState);

            #region properties update

            bool propsChanged = false;
            if (propsChanged)
            {
            }

            #endregion

            if (serverUpdate.DeleteLength > 0) //delete these object ids from the global state
            {
                print("Deleting " + serverUpdate.DeleteLength + " objects");
                for (int i = 0; i < serverUpdate.DeleteLength; i++)
                {
                    if (newRoomState.objects.All(tr => tr.id != serverUpdate.Delete(i)))
                    {
                        print("object to delete not found in global state " + serverUpdate.Delete(i));
                        continue;
                    }
                    newRoomState.objects.Remove(globalState.objects.Single(o => o.id == serverUpdate.Delete(i)));
                    if (trackers.ContainsKey(serverUpdate.Delete(i)) && trackers[serverUpdate.Delete(i)] != null)
                    {
                        Destroy(((MonoBehaviour)trackers[serverUpdate.Delete(i)]).gameObject);
                    }
                    else
                    {
                        print("Could not find game object to destroy" + serverUpdate.Delete(i));
                    }
                }
            }
            if (serverUpdate.CreateLength > 0) //create these objects and add them to the global state
            {
                for (int i = 0; i < serverUpdate.CreateLength; i++)
                {
                    if (!serverUpdate.Create(i).HasValue)
                    {
                        print("Malformed create message");
                        continue;
                    }
                    if (!trackers.ContainsKey(serverUpdate.Create(i).Value.Id))
                    {
                        CreateObject(serverUpdate.Create(i).Value, newRoomState);

                        //if (newRoomState.objects.Contains(serverUpdate.Create(i).Value))
                        //continue;
                    }
                    else
                    {
                        print("Object " + serverUpdate.Create(i).Value.Id + " already exists");
                    }
                }
            }
            if (serverUpdate.UpdateLength > 0)
            {
                for (int i = 0; i < serverUpdate.UpdateLength; i++)
                {
                    if (!serverUpdate.Update(i).HasValue)
                    {
                        continue;
                    }
                    if (!trackers.ContainsKey(serverUpdate.Update(i).Value.Id))
                    {
                        Debug.Log("Object created from update. please use the create function instead");
                        //CreateObject(serverUpdate.Update(i).Value, newRoomState);
                        continue;
                    }
                    trackers[serverUpdate.Update(i).Value.Id].UpdateFromRoomObject(serverUpdate.Update(i).Value);
                }
            }
            oldStateGen = new RoomStateGen(globalState);
            globalState = newRoomState;
        }