//-----------------------------------------------------------------------------
        // server life cycle
        //-----------------------------------------------------------------------------

        public bool StartServer(int clientNum)
        {
            // can only start server when it is inactive
            if (IsServerActive())
            {
                ViveShare_Log.LogWarning(logLevel, "[ViveShare_Server] Server has started already!");
                return(false);
            }

            // try to start server on given port number
            if (!NetworkServer.Listen(portNumber))
            {
                ViveShare_Log.LogError(logLevel, "[ViveShare_Server] Failed to start server on port " + portNumber);
                ViveShare_Event.server_initFailedEvent.Invoke();
                return(false);
            }

            ViveShare_Log.LogInfo(logLevel, "[ViveShare_Server] Server started on port " + portNumber + " , anticipated client = " + clientNum);

            // initialize connection data
            anticipatedClientNum = clientNum;
            connectionDataList   = new List <ConnectionData>();
            connectionDataMap    = new Dictionary <int, ConnectionData>();

            RegisterMessageHandlers();

            // registor event callback types
            ViveShare_Event.RegistorEventEntry();

            ViveShare_Event.server_initSuccessEvent.Invoke();

            state = ViveNetworkState.Wait_Ready;

            return(true);
        }
        //-----------------------------------------------------------------------------
        // client life cycle
        //-----------------------------------------------------------------------------

        public bool StartClient()
        {
            // can only try connection when connection has not been established,
            // and previous attempt has failed
            if ((networkClient != null && networkClient.isConnected) || state != ViveNetworkState.Init)
            {
                ViveShare_Log.LogWarning(logLevel, "[ViveShare_Client] Cannot retry connection when client is busy");
                return(false);
            }

            networkClient = new NetworkClient();

            RegistorMessagHandlers();

            // registor event callback types
            ViveShare_Event.RegistorEventEntry();

            networkClient.Connect(serverAddr, portNumber);

            ViveShare_Log.LogInfo(logLevel, "[ViveShare_Client] Try to connect server (" + serverAddr + ") on port " + portNumber);

            state = ViveNetworkState.Wait_Connect;

            return(true);
        }
        private void DisconnectInternal()
        {
            // detect connection time out
            if (state == ViveNetworkState.Wait_Connect || state == ViveNetworkState.Wait_TrackerRegistry)
            {
                ViveShare_Log.LogError(logLevel, "[ViveShare_Client] Disconnect due to connection timeout");
                ViveShare_Event.client_connectFailedEvent.Invoke();
            }

            ViveShare_Log.LogInfo(logLevel, "[ViveShare_Client] Disconnect");

            // reset and remove resources
            if (needTrackerPose)
            {
                ViveShare_SyncPose syncPose = Camera.main.gameObject.GetComponent <ViveShare_SyncPose>();
                if (syncPose != null)
                {
                    Destroy(syncPose);
                }

                ViveShare_SyncIdentity syncId = Camera.main.gameObject.GetComponent <ViveShare_SyncIdentity>();
                if (syncId != null)
                {
                    Destroy(syncId);
                }
            }

            clientId = -1;

            ViveShare_Event.client_disconnectEvent.Invoke();

            state = ViveNetworkState.Init;
        }
        internal void OnTrackerRegistryFinished(NetworkMessage netMsg)
        {
            // parse message
            ViveTrackerRegistryReturnMsg msg = netMsg.ReadMessage <ViveTrackerRegistryReturnMsg>();

            // assign client id
            clientId = msg.clientId;

            // attach sync pose obj to main camera
            ViveShare_SyncIdentity syncId = Camera.main.gameObject.AddComponent <ViveShare_SyncIdentity>();

            syncId.id           = msg.syncObjName;
            syncId.hasAuthority = false;
            syncId.Register();

            ViveShare_SyncPose syncPose = Camera.main.gameObject.AddComponent <ViveShare_SyncPose>();

            ViveShare_Log.LogInfo(logLevel, "[ViveShare_Client] Client id (" + clientId + ") assigned");
            ViveShare_Log.LogInfo(logLevel, "[ViveShare_Client] Tracker registry (" + msg.syncObjName + ") finished");

            state = ViveNetworkState.Wait_Ready;

            // invoke callbacks --  we only think the connection is established at this moment
            ViveShare_Event.client_connectSuccessEvent.Invoke();
        }
        internal void OnClientReady(NetworkMessage netMsg)
        {
            ViveShare_Log.LogInfo(logLevel, "[ViveShare_Server] Client (" + netMsg.conn.connectionId + ") is ready");

            // set ready state for this connection
            ConnectionData connData;

            if (connectionDataMap.TryGetValue(netMsg.conn.connectionId, out connData))
            {
                connData.isReady = true;

                ViveShare_Event.server_clientReadyEvent.Invoke(netMsg.conn.connectionId);
            }

            // check whether all clients are ready
            if (AllClientsReady())
            {
                ViveShare_Log.LogInfo(logLevel, "[ViveShare_Server] All clients are ready");

                if (state == ViveNetworkState.Wait_Ready)
                {
                    state = ViveNetworkState.Wait_GameStart;
                }

                ViveShare_Event.server_allClientsReadyEvent.Invoke();
            }
        }
    public void OnClientDisconnect(int id)
    {
        gameSettingButton.interactable = false;
        gameSettingButtonText.text     = "Wait Clients...";

        state = ViveNetworkState.Wait_Ready;
    }
        internal void OnGameStarted(NetworkMessage netMsg)
        {
            ViveShare_Log.LogInfo(logLevel, "[ViveShare_Client] Game start");

            ViveShare_Event.gameStartEvent.Invoke();

            state = ViveNetworkState.Gaming;
        }
        internal void OnGameEnd(NetworkMessage netMsg)
        {
            ViveShare_Log.LogInfo(logLevel, "[ViveShare_Client] Game end");

            RemoveSpawnedObjects();

            ViveShare_Event.gameEndEvent.Invoke();

            state = ViveNetworkState.Wait_Shutdown;
        }
    void OnEnable()
    {
        ipInput.text   = ip;
        portInput.text = port.ToString();

        ViveShare_Event.client_connectFailedEvent.Listen(OnClientConnectFailed);
        ViveShare_Event.client_connectSuccessEvent.Listen(OnClientConnected);

        gameSettingButtonText.text = "Connect to Host";
        state = ViveNetworkState.Init;
    }
    public void OnServerStarted()
    {
        //// ++ Unity bug -- GameObject mysteriously destoryed when reload scene
        //gameSettingButton = FindObjectOfType<Button>();
        //gameSettingButtonText = gameSettingButton.GetComponentInChildren<Text>();
        //// -- Unity bug

        gameSettingButton.interactable = false;
        gameSettingButtonText.text     = "Wait Clients...";

        state = ViveNetworkState.Wait_Ready;
    }
    public void OnClientsReady()
    {
        gameSettingButton.interactable = true;

        var colors = gameSettingButton.colors;

        colors.normalColor       = buttonStartGameColor;
        colors.highlightedColor  = buttonStartGameColor;
        gameSettingButton.colors = colors;

        gameSettingButtonText.text = "Start Game";

        state = ViveNetworkState.Wait_GameStart;
    }
    public void OnGameSettingButtonPressed()
    {
        if (state == ViveNetworkState.Init)
        {
            ViveShare_Client.Instance.serverAddr = ip;
            ViveShare_Client.Instance.portNumber = port;
            ViveShare_Client.Instance.SetTrackerPoseRequestParam(true, playerNum);

            if (ViveShare_Client.Instance.StartClient() == true)
            {
                gameSettingButtonText.text = "Connecting...";
                state = ViveNetworkState.Wait_Connect;
            }
        }
    }
        internal void OnConnect(NetworkMessage netMsg)
        {
            ViveShare_Log.LogInfo(logLevel, "[ViveShare_Client] Client connected to server (" + serverAddr + ") on port " + portNumber);

            // send a request for tracker registry to server (even if not needed)
            ViveTrackerRegistryRequestMsg trackerRequestMsg = new ViveTrackerRegistryRequestMsg();

            trackerRequestMsg.needTrackerPose = needTrackerPose;
            trackerRequestMsg.serialNumber    = serialNumber;
            trackerRequestMsg.trackerNumber   = trackerNumber;
            networkClient.Send(ViveShareMsgType.TrackerRegistryRequest, trackerRequestMsg);

            messageSendTimeStamp = Time.time;

            state = ViveNetworkState.Wait_TrackerRegistry;
        }
    public void OnEnable()
    {
        ViveShare_Event.server_initSuccessEvent.Listen(OnServerStarted);
        ViveShare_Event.server_allClientsReadyEvent.Listen(OnClientsReady);
        ViveShare_Event.server_clientDisconnectedEvent.Listen(OnClientDisconnect);

        state = ViveNetworkState.Init;

        gameSettingButton.interactable = true;

        var colors = gameSettingButton.colors;

        colors.normalColor       = buttonNormalColor;
        colors.highlightedColor  = buttonNormalColor;
        gameSettingButton.colors = colors;

        gameSettingButtonText.text = "Start as Host";
    }
        public void SetClientReady()
        {
            // can only set client as ready when client is in Wait_Ready state
            if (state != ViveNetworkState.Wait_Ready)
            {
                ViveShare_Log.LogWarning(logLevel, "[ViveShare_Client] Cannot set ready when client is not in Wait_Ready state");
                return;
            }

            ViveShare_Log.LogInfo(logLevel, "[ViveShare_Client] Client is ready");

            // send ready message
            EmptyMessage msg = new EmptyMessage();

            networkClient.Send(MsgType.Ready, msg);

            ViveShare_Event.client_readyEvent.Invoke();

            state = ViveNetworkState.Wait_GameStart;
        }
        public void StartGame()
        {
            // can only start game when in Wait_GameStart state
            if (state != ViveNetworkState.Wait_GameStart)
            {
                ViveShare_Log.LogWarning(logLevel, "[ViveShare_Server] Cannot start game -- either the game has started or not all clients are ready");
                return;
            }

            ViveShare_Log.LogInfo(logLevel, "[ViveShare_Server] Game start");

            // tell clients to start game
            EmptyMessage msg = new EmptyMessage();

            NetworkServer.SendToAll(ViveShareMsgType.GameStarted, msg);

            ViveShare_Event.gameStartEvent.Invoke();

            state = ViveNetworkState.Gaming;
        }
        internal void OnClientDisconnectFromServer(NetworkMessage netMsg)
        {
            // if this disconnection event is due to rejecting illegal connection, do nothing
            if (GetConnectionData(netMsg.conn.connectionId) == null)
            {
                return;
            }

            ViveShare_Log.LogInfo(logLevel, "[ViveShare_Server] Client (" + netMsg.conn.connectionId + ") disconnected");

            RemoveConnectionData(netMsg.conn.connectionId);

            ViveShare_Event.server_clientDisconnectedEvent.Invoke(netMsg.conn.connectionId);

            // if is in Wait_GameStart state, reset state (since someone left the game before game started)
            if (state == ViveNetworkState.Wait_GameStart)
            {
                ViveShare_Log.LogInfo(logLevel, "[ViveShare_Server] Someone left the game before started, revert to Wait_Ready state");
                state = ViveNetworkState.Wait_Ready;
            }
        }
        public void ShutdownServer()
        {
            // can't shut down server if it has not started
            if (state == ViveNetworkState.Init)
            {
                ViveShare_Log.LogWarning(logLevel, "[ViveShare_Server] Cannot shut down server since it has not been started");
                return;
            }

            // can't shut down server if game is still running
            if (state == ViveNetworkState.Gaming)
            {
                ViveShare_Log.LogWarning(logLevel, "[ViveShare_Server] Cannot shut down server when game is still running");
                return;
            }

            ViveShare_Log.LogInfo(logLevel, "[ViveShare_Server] Server shut down");

            // clear resources
            anticipatedClientNum = 0;

            foreach (NetworkConnection conn in NetworkServer.connections)
            {
                if (conn != null)
                {
                    RemoveConnectionData(conn.connectionId);
                }
            }

            // tell clients to disconnect
            EmptyMessage msg = new EmptyMessage();

            NetworkServer.SendToAll(MsgType.Disconnect, msg);

            NetworkServer.Shutdown();

            ViveShare_Event.server_shutdownEvent.Invoke();

            state = ViveNetworkState.Init;
        }
        public void EndGame()
        {
            // can only start game when game is running
            if (state != ViveNetworkState.Gaming)
            {
                ViveShare_Log.LogWarning(logLevel, "[ViveShare_Server] Cannot stop game if game has not started");
                return;
            }

            ViveShare_Log.LogInfo(logLevel, "[ViveShare_Server] Game end");

            RemoveSpawnedObjects();

            // tell clients to stop game
            EmptyMessage msg = new EmptyMessage();

            NetworkServer.SendToAll(ViveShareMsgType.GameEnd, msg);

            ViveShare_Event.gameEndEvent.Invoke();

            state = ViveNetworkState.Wait_Shutdown;
        }
 public void OnClientConnected()
 {
     ViveShare_Client.Instance.SetClientReady();
     gameSettingButtonText.text = "Preparing Game";
     state = ViveNetworkState.Wait_GameStart;
 }
    public void OnClientConnectFailed()
    {
        gameSettingButtonText.text = "Connect to Host";

        state = ViveNetworkState.Init;
    }