/// <inheritdoc /> protected override TinyNetConnection CreateTinyNetConnection(NetPeer peer) { TinyNetConnection tinyConn; if (((string)peer.Tag).Equals(TinyNetGameManager.ApplicationGUIDString)) { tinyConn = new TinyNetLocalConnectionToClient(peer); if (TinyNetLogLevel.logDev) { TinyLogger.Log("TinyNetServer::CreateTinyNetConnection created new TinyNetLocalConnectionToClient."); } } else { tinyConn = new TinyNetConnection(peer); if (TinyNetLogLevel.logDev) { TinyLogger.Log("TinyNetServer::CreateTinyNetConnection created new TinyNetConnection."); } } peer.Tag = tinyConn; tinyNetConns.Add(tinyConn); return(tinyConn); }
/// <summary> /// Orders the server to change to the given scene. /// </summary> /// <param name="newSceneName">The name of the scene to change to.</param> public virtual void ServerChangeScene(string newSceneName) { if (string.IsNullOrEmpty(newSceneName)) { if (TinyNetLogLevel.logError) { TinyLogger.LogError("ServerChangeScene empty scene name"); } return; } if (TinyNetLogLevel.logDebug) { TinyLogger.Log("ServerChangeScene " + newSceneName); } serverManager.SetAllClientsNotReady(); networkSceneName = newSceneName; s_LoadingSceneAsync = SceneManager.LoadSceneAsync(newSceneName); TinyNetStringMessage msg = new TinyNetStringMessage(networkSceneName); msg.msgType = TinyNetMsgType.Scene; serverManager.SendMessageByChannelToAllConnections(msg, DeliveryMethod.ReliableOrdered); }
/// <summary> /// Called when a scene has finished loading. /// </summary> public virtual void FinishLoadScene() { if (isClient) { clientManager.ClientFinishLoadScene(); } else { if (TinyNetLogLevel.logDev) { TinyLogger.Log("FinishLoadScene client is null"); } } if (isServer) { serverManager.SpawnAllObjects(); serverManager.OnServerSceneChanged(networkSceneName); } if (isClient && clientManager.isConnected) { clientManager.OnClientSceneChanged(); } }
/// <summary> /// Called when an object is spawned on the client. /// </summary> public void OnStartClient() { if (bStartClientTwiceTest) { if (TinyNetLogLevel.logError) { TinyLogger.LogError("OnStartClient CALLED TWICE FOR: " + gameObject + " netId:" + NetworkID + " localPlayerAuthority: " + _localPlayerAuthority); } } else { bStartClientTwiceTest = true; } for (int i = 0; i < _tinyNetObjects.Length; i++) { if (!isServer) { TinyNetScene.AddTinyNetObjectToList(_tinyNetObjects[i]); } _tinyNetObjects[i].OnStartClient(); } if (TinyNetLogLevel.logDev) { TinyLogger.Log("OnStartClient " + gameObject + " netId:" + NetworkID + " localPlayerAuthority: " + _localPlayerAuthority); } }
/// <summary> /// Registers a handler for a message, it will not check for conflicts, but cannot be used for system messages. /// </summary> /// <param name="msgType">Type of the <see cref="ITinyNetMessage"/>.</param> /// <param name="handler">The delegate.</param> public void RegisterHandler(ushort msgType, TinyNetMessageDelegate handler) { if (handler == null) { if (TinyNetLogLevel.logError) { TinyLogger.LogError("RegisterHandler id:" + msgType + " handler is null"); } return; } if (msgType <= TinyNetMsgType.InternalHighest) { if (TinyNetLogLevel.logError) { TinyLogger.LogError("RegisterHandler: Cannot replace system message handler " + msgType); } return; } if (_msgHandlers.ContainsKey(msgType)) { if (TinyNetLogLevel.logDebug) { TinyLogger.Log("RegisterHandler replacing " + msgType); } _msgHandlers.Remove(msgType); } if (TinyNetLogLevel.logDebug) { TinyLogger.Log("RegisterHandler id:" + msgType + " handler:" + handler.Method.Name); } _msgHandlers.Add(msgType, handler); }
/// <summary> /// Called when the initial spawning of objects have been started and when it finishes. /// </summary> /// <param name="netMsg">A wrapper for a <see cref="TinyNetObjectSpawnFinishedMessage"/>.</param> void OnObjectSpawnFinished(TinyNetMessageReader netMsg) { netMsg.ReadMessage(s_TineNetObjectSpawnFinishedMessage); if (TinyNetLogLevel.logDebug) { TinyLogger.Log("SpawnFinished: " + s_TineNetObjectSpawnFinishedMessage.state); } // when 0, means we already started receiving the spawn messages but we have yet to receive them all. if (s_TineNetObjectSpawnFinishedMessage.state == 0) { PrepareToSpawnSceneObjects(); _isSpawnFinished = false; return; } // when 1, means we have received every single spawn message! foreach (TinyNetIdentity tinyNetId in LocalIdentityObjects.Values) { if (tinyNetId.isClient) { tinyNetId.OnStartClient(); } } _isSpawnFinished = true; }
/// <summary> /// Called when an object is spawned on the client. /// <para> Called on the client when the object is spawned. Called after variables are synced. (Order: 2) </para> /// </summary> public void OnStartClient() { if (bStartClientTwiceTest) { if (TinyNetLogLevel.logError) { TinyLogger.LogError("OnStartClient CALLED TWICE FOR: " + gameObject + " netId:" + TinyInstanceID + " localPlayerAuthority: " + _localPlayerAuthority); } } else { bStartClientTwiceTest = true; } { // Calling OnStartClient on those who registered LinkedList <System.Action> handlers; if (!_registeredEventHandlers.TryGetValue(TinyNetComponentEvents.OnStartClient, out handlers)) { return; } for (LinkedListNode <System.Action> currentNode = handlers.First; currentNode != null; currentNode = currentNode.Next) { currentNode.Value(); } } if (TinyNetLogLevel.logDev) { TinyLogger.Log("OnStartClient " + gameObject + " netId:" + TinyInstanceID + " localPlayerAuthority: " + _localPlayerAuthority); } }
/// <summary> /// Received unconnected message /// </summary> /// <param name="remoteEndPoint">From address (IP and Port)</param> /// <param name="reader">Message data</param> /// <param name="messageType">Message type (simple, discovery request or responce)</param> public virtual void OnNetworkReceiveUnconnected(IPEndPoint remoteEndPoint, NetPacketReader reader, UnconnectedMessageType messageType) { if (TinyNetLogLevel.logDev) { TinyLogger.Log("[" + TYPE + "] Received Unconnected message from: " + remoteEndPoint); } }
/// <summary> /// Prepares to spawn scene objects. /// </summary> void PrepareToSpawnSceneObjects() { //NOTE: what if is there are already objects in this dict?! should we merge with them? _sceneIdentityObjectsToSpawn = new Dictionary <int, TinyNetIdentity>(); foreach (TinyNetIdentity tinyNetId in Resources.FindObjectsOfTypeAll <TinyNetIdentity>()) { if (tinyNetId.gameObject.activeSelf) { // already active, cannot spawn it continue; } if (tinyNetId.gameObject.hideFlags == HideFlags.NotEditable || tinyNetId.gameObject.hideFlags == HideFlags.HideAndDontSave) { continue; } if (tinyNetId.sceneID == 0) { continue; } _sceneIdentityObjectsToSpawn[tinyNetId.sceneID] = tinyNetId; if (TinyNetLogLevel.logDebug) { TinyLogger.Log("TinyNetClient::PrepareSpawnObjects sceneId: " + tinyNetId.sceneID); } } }
//=== /// <summary> /// Readies this instance. /// </summary> /// <returns></returns> public virtual bool Ready() { if (!isConnected) { if (TinyNetLogLevel.logError) { TinyLogger.LogError("TinyNetClient::Ready() called but we are not connected to anything."); } return(false); } // The first connection should always be to the host. //TinyNetConnection conn = _tinyNetConns[0]; if (connToHost.isReady) { //if (TinyNetLogLevel.logError) { TinyLogger.LogError("A connection has already been set as ready. There can only be one."); } return(false); } if (TinyNetLogLevel.logDebug) { TinyLogger.Log("TinyNetClient::Ready() called with connection [" + connToHost + "]"); } var msg = new TinyNetReadyMessage(); SendMessageByChannelToTargetConnection(msg, DeliveryMethod.ReliableOrdered, connToHost); connToHost.isReady = true; TinyNetGameManager.instance.OnClientReady(); return(true); }
/// <summary> /// Orders the client to change to the given scene. /// </summary> /// <param name="newSceneName">Name of the new scene.</param> /// <param name="forceReload">if set to <c>true</c>, force reload.</param> public virtual void ClientChangeScene(string newSceneName, bool forceReload) { if (string.IsNullOrEmpty(newSceneName)) { if (TinyNetLogLevel.logError) { TinyLogger.LogError("ClientChangeScene empty scene name"); } return; } if (TinyNetLogLevel.logDebug) { TinyLogger.Log("ClientChangeScene newSceneName:" + newSceneName + " networkSceneName:" + networkSceneName); } if (newSceneName == networkSceneName) { if (!forceReload) { FinishLoadScene(); return; } } s_LoadingSceneAsync = SceneManager.LoadSceneAsync(newSceneName); networkSceneName = newSceneName; }
/// <summary> /// Latency information updated /// </summary> /// <param name="peer">Peer with updated latency</param> /// <param name="latency">latency value in milliseconds</param> public virtual void OnNetworkLatencyUpdate(NetPeer peer, int latency) { if (TinyNetLogLevel.logDev) { TinyLogger.Log("[" + TYPE + "] Latency update for peer: " + peer.EndPoint + " " + latency + "ms"); } }
/// <summary> /// Received some data /// </summary> /// <param name="peer">From peer</param> /// <param name="reader">DataReader containing all received data</param> /// <param name="deliveryMethod">Type of received packet</param> public virtual void OnNetworkReceive(NetPeer peer, NetDataReader reader, DeliveryMethod deliveryMethod) { if (TinyNetLogLevel.logDev) { TinyLogger.Log("[" + TYPE + "] received message " + TinyNetMsgType.MsgTypeToString(ReadMessageAndCallDelegate(reader, peer)) + " from: " + peer.EndPoint + " method: " + deliveryMethod.ToString()); } }
//============ Scenes Methods =======================// /// <summary> /// Checks if a scene load was requested and if it finished. /// </summary> protected virtual void CheckForSceneLoad() { if (instance == null) { return; } if (s_LoadingSceneAsync == null) { return; } if (!s_LoadingSceneAsync.isDone) { return; } if (TinyNetLogLevel.logDebug) { TinyLogger.Log("CheckForSceneLoad done"); } FinishLoadScene(); s_LoadingSceneAsync.allowSceneActivation = true; s_LoadingSceneAsync = null; }
/// <summary> /// Registers a handler for a message, if another handler is already registered it will log an error. /// </summary> /// <param name="msgType">Type of the <see cref="ITinyNetMessage"/>.</param> /// <param name="handler">The delegate.</param> internal void RegisterHandlerSafe(ushort msgType, TinyNetMessageDelegate handler) { if (handler == null) { if (TinyNetLogLevel.logError) { TinyLogger.LogError("RegisterHandlerSafe id:" + msgType + " handler is null"); } return; } if (TinyNetLogLevel.logDebug) { TinyLogger.Log("RegisterHandlerSafe id:" + msgType + " handler:" + handler.Method.Name); } if (_msgHandlers.ContainsKey(msgType)) { if (TinyNetLogLevel.logError) { TinyLogger.LogError("RegisterHandlerSafe id:" + msgType + " handler:" + handler.Method.Name + " conflict"); } return; } _msgHandlers.Add(msgType, handler); }
/*public virtual void OnNetworkReceive(NetPeer peer, NetDataReader reader) { * TinyLogger.Log("[" + TYPE + "] On network receive from: " + peer.EndPoint); * }*/ /// <summary> /// Called when a discovery request is received. /// </summary> /// <param name="remoteEndPoint">The remote end point.</param> /// <param name="reader">The reader.</param> protected virtual void OnDiscoveryRequestReceived(NetEndPoint remoteEndPoint, NetDataReader reader) { if (TinyNetLogLevel.logDev) { TinyLogger.Log("[" + TYPE + "] Received discovery request. Send discovery response"); } _netManager.SendDiscoveryResponse(new byte[] { 1 }, remoteEndPoint); }
/// <summary> /// Called when a scene change finishes. /// </summary> public virtual void OnClientSceneChanged() { if (TinyNetLogLevel.logDev) { TinyLogger.Log("TinyNetClient::OnClientSceneChanged() called"); } Ready(); }
/// <summary> /// Called when clientManager.isConnected is <c>true</c>, this is another ready check if we only finished connecting after the scene change. /// </summary> public virtual void OnClientFinishedConnecting() { if (TinyNetLogLevel.logDev) { TinyLogger.Log("TinyNetClient::OnClientFinishedConnecting() called"); } Ready(); }
/* * public virtual void SendStateUpdateToAllConnections(TinyNetBehaviour netBehaviour, DeliveryMethod sendOptions) { * recycleWriter.Reset(); * * recycleWriter.Put(TinyNetMsgType.StateUpdate); * recycleWriter.Put(netBehaviour.NetworkID); * * netBehaviour.TinySerialize(recycleWriter, false); * * for (int i = 0; i < tinyNetConns.Count; i++) { * tinyNetConns[i].Send(recycleWriter, sendOptions); * } * }*/ //============ TinyNetMessages Handlers =============// // default ready handler. /// <summary> /// Called when we receive a client ready message. /// </summary> /// <param name="netMsg">The net MSG.</param> void OnClientReadyMessage(TinyNetMessageReader netMsg) { if (TinyNetLogLevel.logDev) { TinyLogger.Log("Default handler for ready message from " + netMsg.tinyNetConn); } SetClientReady(netMsg.tinyNetConn); }
/// <summary> /// Received some data /// </summary> /// <param name="peer">From peer</param> /// <param name="reader">DataReader containing all received data</param> /// <param name="deliveryMethod">Type of received packet</param> public virtual void OnNetworkReceive(NetPeer peer, NetPacketReader reader, DeliveryMethod deliveryMethod) { string msgType = TinyNetMsgType.MsgTypeToString(ReadMessageAndCallDelegate(reader, peer, deliveryMethod)); if (TinyNetLogLevel.logDev) { TinyLogger.Log("[" + TYPE + "] received message " + msgType + " from: " + peer.EndPoint + " channel: " + deliveryMethod.ToString()); } }
/// <summary> /// Called when an object is spawned on the server. /// </summary> /// <param name="allowNonZeroNetId">If the object already have a NetworkId, it was probably recycled.</param> public void OnStartServer(bool allowNonZeroNetId) { if (_localPlayerAuthority) { // local player on server has NO authority _hasAuthority = false; } else { // enemy on server has authority _hasAuthority = true; } // If the instance/net ID is invalid here then this is an object instantiated from a prefab and the server should assign a valid ID if (NetworkID == 0) { NetworkID = TinyNetGameManager.instance.NextNetworkID; for (int i = 0; i < _tinyNetObjects.Length; i++) { _tinyNetObjects[i].ReceiveNetworkID(TinyNetGameManager.instance.NextNetworkID); } } else { if (allowNonZeroNetId) { //allowed } else { if (TinyNetLogLevel.logError) { TinyLogger.LogError("Object has non-zero netId " + NetworkID + " for " + gameObject); } return; } } for (int i = 0; i < _tinyNetObjects.Length; i++) { TinyNetScene.AddTinyNetObjectToList(_tinyNetObjects[i]); _tinyNetObjects[i].OnStartServer(); } if (TinyNetLogLevel.logDev) { TinyLogger.Log("OnStartServer " + gameObject + " netId:" + NetworkID); } if (_hasAuthority) { OnStartAuthority(); } }
/// <summary> /// Attempts to connect the client to the given server. /// </summary> /// <param name="hostAddress">The host address.</param> /// <param name="hostPort">The host port.</param> public virtual void ClientConnectTo(string hostAddress, int hostPort) { if (TinyNetLogLevel.logDev) { TinyLogger.Log("[" + TYPE + "] Attempt to connect at adress: " + hostAddress + ":" + hostPort); } WriteConnectionRequest(s_recycleWriter); _netManager.Connect(hostAddress, hostPort, s_recycleWriter); }
/// <summary> /// New remote peer connected to host, or client connected to remote host /// </summary> /// <param name="peer">Connected peer object</param> public virtual void OnPeerConnected(NetPeer peer) { if (TinyNetLogLevel.logDev) { TinyLogger.Log("[" + TYPE + "] We have new peer: " + peer.EndPoint + " connectId: " + peer.ConnectId); } TinyNetConnection nConn = CreateTinyNetConnection(peer); OnConnectionCreated(nConn); }
/// <summary> /// Received unconnected message /// </summary> /// <param name="remoteEndPoint">From address (IP and Port)</param> /// <param name="reader">Message data</param> /// <param name="messageType">Message type (simple, discovery request or responce)</param> public virtual void OnNetworkReceiveUnconnected(NetEndPoint remoteEndPoint, NetDataReader reader, UnconnectedMessageType messageType) { if (TinyNetLogLevel.logDev) { TinyLogger.Log("[" + TYPE + "] Received Unconnected message from: " + remoteEndPoint); } if (messageType == UnconnectedMessageType.DiscoveryRequest) { OnDiscoveryRequestReceived(remoteEndPoint, reader); } }
/// <summary> /// Peer disconnected /// </summary> /// <param name="peer">disconnected peer</param> /// <param name="disconnectInfo">additional info about reason, errorCode or data received with disconnect message</param> public virtual void OnPeerDisconnected(NetPeer peer, DisconnectInfo disconnectInfo) { if (TinyNetLogLevel.logDev) { TinyLogger.Log("[" + TYPE + "] disconnected from: " + peer.EndPoint + " because " + disconnectInfo.Reason); } TinyNetConnection nConn = GetTinyNetConnection(peer); OnDisconnect(nConn); RemoveTinyNetConnection(nConn); }
//============ INetEventListener methods ============// /// <inheritdoc /> public override void OnNetworkReceiveUnconnected(IPEndPoint remoteEndPoint, NetPacketReader reader, UnconnectedMessageType messageType) { base.OnNetworkReceiveUnconnected(remoteEndPoint, reader, messageType); if (messageType == UnconnectedMessageType.DiscoveryRequest) { if (TinyNetLogLevel.logDev) { TinyLogger.Log("[" + TYPE + "] Received discovery request. Send discovery response"); } _netManager.SendDiscoveryResponse(new byte[] { 1 }, remoteEndPoint); } }
/// <summary> /// Attempts to connect the client to the given server. /// </summary> /// <param name="hostAddress">The host address.</param> /// <param name="hostPort">The host port.</param> public virtual void ClientConnectTo(string hostAddress, int hostPort) { if (TinyNetLogLevel.logDev) { TinyLogger.Log("[CLIENT] Attempt to connect at adress: " + hostAddress + ":" + hostPort); } recycleWriter.Reset(); recycleWriter.Put(TinyNetGameManager.instance.multiplayerConnectKey); recycleWriter.Put(TinyNetGameManager.ApplicationGUIDString); _netManager.Connect(hostAddress, hostPort, recycleWriter); }
//============ Scenes Methods =======================// /// <summary> /// Handler for a scene change message. /// </summary> /// <param name="netMsg">A wrapper for a <see cref="TinyNetStringMessage"/> containing the scene name.</param> protected virtual void OnClientChangeSceneMessage(TinyNetMessageReader netMsg) { if (TinyNetLogLevel.logDebug) { TinyLogger.Log("TinyNetClient:OnClientChangeSceneMessage"); } string newSceneName = netMsg.reader.GetString(); if (isConnected && !TinyNetGameManager.instance.isServer) { TinyNetGameManager.instance.ClientChangeScene(newSceneName, true); } }
/// <summary> /// Sets the client as not ready. /// </summary> /// <param name="conn">The connection.</param> void SetClientNotReady(TinyNetConnection conn) { if (conn.isReady) { if (TinyNetLogLevel.logDebug) { TinyLogger.Log("PlayerNotReady " + conn); } conn.isReady = false; TinyNetNotReadyMessage msg = new TinyNetNotReadyMessage(); SendMessageByChannelToTargetConnection(msg, DeliveryMethod.ReliableOrdered, conn); } }
//============ INetEventListener methods ============// /// <inheritdoc /> public override void OnNetworkReceiveUnconnected(IPEndPoint remoteEndPoint, NetPacketReader reader, UnconnectedMessageType messageType) { base.OnNetworkReceiveUnconnected(remoteEndPoint, reader, messageType); if (messageType == UnconnectedMessageType.DiscoveryResponse && _netManager.PeersCount == 0) { if (TinyNetLogLevel.logDev) { TinyLogger.Log("[" + TYPE + "] Received discovery response. Connecting to: " + remoteEndPoint); } WriteConnectionRequest(s_recycleWriter); _netManager.Connect(remoteEndPoint, s_recycleWriter); } }