#if ENABLE_UNET using System; using System.Collections.Generic; namespace UnityEngine.Networking { sealed class LocalClient : NetworkClient { const int k_InitialFreeMessagePoolSize = 64; struct InternalMsg { internal byte[] buffer; internal int channelId; } List m_InternalMsgs = new List(); List m_InternalMsgs2 = new List(); Stack m_FreeMessages; NetworkServer m_LocalServer; bool m_Connected; NetworkMessage s_InternalMessage = new NetworkMessage(); public override void Disconnect() { ClientScene.HandleClientDisconnect(m_Connection); if (m_Connected) { PostInternalMessage(MsgType.Disconnect); m_Connected = false; } m_AsyncConnect = ConnectState.Disconnected; m_LocalServer.RemoveLocalClient(m_Connection); } internal void InternalConnectLocalServer(bool generateConnectMsg) { if (m_FreeMessages == null) { m_FreeMessages = new Stack(); for (int i = 0; i < k_InitialFreeMessagePoolSize; i++) { InternalMsg msg = new InternalMsg(); m_FreeMessages.Push(msg); } } m_LocalServer = NetworkServer.instance; m_Connection = new ULocalConnectionToServer(m_LocalServer); SetHandlers(m_Connection); m_Connection.connectionId = m_LocalServer.AddLocalClient(this); m_AsyncConnect = ConnectState.Connected; SetActive(true); RegisterSystemHandlers(true); if (generateConnectMsg) { PostInternalMessage(MsgType.Connect); } m_Connected = true; } internal override void Update() { ProcessInternalMessages(); } // Called by the server to set the LocalClient's LocalPlayer object during NetworkServer.AddPlayer() internal void AddLocalPlayer(PlayerController localPlayer) { if (LogFilter.logDev) Debug.Log("Local client AddLocalPlayer " + localPlayer.gameObject.name + " conn=" + m_Connection.connectionId); m_Connection.isReady = true; m_Connection.SetPlayerController(localPlayer); var uv = localPlayer.unetView; if (uv != null) { ClientScene.SetLocalObject(uv.netId, localPlayer.gameObject); uv.SetConnectionToServer(m_Connection); } // there is no SystemOwnerMessage for local client. add to ClientScene here instead ClientScene.InternalAddPlayer(uv, localPlayer.playerControllerId); } private void PostInternalMessage(byte[] buffer, int channelId) { InternalMsg msg; if (m_FreeMessages.Count == 0) { msg = new InternalMsg(); // grow forever? } else { msg = m_FreeMessages.Pop(); } msg.buffer = buffer; msg.channelId = channelId; m_InternalMsgs.Add(msg); } private void PostInternalMessage(short msgType) { NetworkWriter writer = new NetworkWriter(); writer.StartMessage(msgType); writer.FinishMessage(); PostInternalMessage(writer.AsArray(), 0); } private void ProcessInternalMessages() { if (m_InternalMsgs.Count == 0) { return; } // new msgs will get put in m_InternalMsgs2 List tmp = m_InternalMsgs; m_InternalMsgs = m_InternalMsgs2; // iterate through existing set for (int i = 0; i < tmp.Count; i++) { var msg = tmp[i]; if (s_InternalMessage.reader == null) { s_InternalMessage.reader = new NetworkReader(msg.buffer); } else { s_InternalMessage.reader.Replace(msg.buffer); } s_InternalMessage.reader.ReadInt16(); //size s_InternalMessage.channelId = msg.channelId; s_InternalMessage.conn = connection; s_InternalMessage.msgType = s_InternalMessage.reader.ReadInt16(); m_Connection.InvokeHandler(s_InternalMessage); m_FreeMessages.Push(msg); connection.lastMessageTime = Time.time; } // put m_InternalMsgs back and clear it m_InternalMsgs = tmp; m_InternalMsgs.Clear(); // add any newly generated msgs in m_InternalMsgs2 and clear it for (int ii = 0; ii < m_InternalMsgs2.Count; ii++) { m_InternalMsgs.Add(m_InternalMsgs2[ii]); } m_InternalMsgs2.Clear(); } // called by the server, to bypass network internal void InvokeHandlerOnClient(short msgType, MessageBase msg, int channelId) { // write the message to a local buffer NetworkWriter writer = new NetworkWriter(); writer.StartMessage(msgType); msg.Serialize(writer); writer.FinishMessage(); InvokeBytesOnClient(writer.AsArray(), channelId); } // called by the server, to bypass network internal void InvokeBytesOnClient(byte[] buffer, int channelId) { PostInternalMessage(buffer, channelId); } } } #endif //ENABLE_UNET