Example #1
0
 // ================================================
 // API
 // ================================================
 /// <summary>
 /// Starts the server using the given address.
 /// </summary>
 public void StartServer(string address)
 {
     if (CurrentMode == Mode.Idle)
     {
         tmpAddress = address;
         network.StartServer(address);
     }
     else if (CurrentMode == Mode.Server)
     {
         var e = new Exception($"Already hosting address {Address}");
         OnServerStartFailure?.Invoke(e);
     }
     else
     {
         var e = new Exception($"Already connected to addr {Address}");
         OnServerStartFailure?.Invoke(e);
     }
 }
Example #2
0
        void ProcessNetworkEvent(NetworkEvent e)
        {
            switch (e.Type)
            {
            case NetEventType.ServerInitialized:
                OnServerStartSuccess?.Invoke(e);
                break;

            case NetEventType.ServerInitFailed:
                OnServerStartFailure?.Invoke(e);
                break;

            // Received after network.StopServer
            case NetEventType.ServerClosed:
                OnServerStopped?.Invoke(e);
                break;


            case NetEventType.NewConnection:
                OnNewConnection?.Invoke(e);
                break;

            case NetEventType.ConnectionFailed:
                OnConnectionFailed?.Invoke(e);
                break;

            case NetEventType.Disconnected:
                OnDisconnection?.Invoke(e);
                break;


            case NetEventType.ReliableMessageReceived:
                OnMessageReceived?.Invoke(e, true);
                break;

            case NetEventType.UnreliableMessageReceived:
                OnMessageReceived?.Invoke(e, false);
                break;
            }
        }
Example #3
0
        /// <summary>
        /// Sends a byte array to several recipient peers
        /// </summary>
        /// <param name="recipients">A list of the recipient peer IDs</param>
        /// <param name="bytes">The byte array to send</param>
        /// <param name="reliable">Whether data is sent UDP/TCP style</param>
        public void SendRaw
            (List <short> recipients, byte[] bytes, bool reliable = false)
        {
            if (recipients == null || recipients.Count == 0)
            {
                recipients = new List <short> {
                    1
                }
            }
            ;

            var message = new Message {
                sender     = ID,
                recipients = recipients.ToArray(),
                bytes      = bytes
            };
            var bytesToSend = message.Serialize();

            // If we're a client, we only send to the server.
            // The server will pass on the message to clients in recipient list
            if (CurrentMode == Mode.Client)
            {
                network.SendData(
                    id: serverCID,
                    data: bytesToSend,
                    offset: 0,
                    len: bytesToSend.Length,
                    reliable: reliable
                    );
            }
            // If we're the server, we send to all the recipients
            else if (CurrentMode == Mode.Server)
            {
                foreach (var recipient in recipients)
                {
                    if (recipient != ID)
                    {
                        network.SendData(
                            id: new ConnectionId(recipient),
                            data: bytesToSend,
                            offset: 0,
                            len: bytesToSend.Length,
                            reliable: reliable
                            );
                    }
                }
            }
        }

        // ================================================
        // NETWORK HANDLERS
        // ================================================
        void Network_OnServerStartSuccess(NetworkEvent e)
        {
            ID          = 0; // server ID is 0
            CurrentMode = Mode.Server;
            Address     = tmpAddress;
            OnServerStartSuccess?.Invoke();
            OnReceiveID?.Invoke(ID);
        }

        void Network_OnServerStartFailure(NetworkEvent e)
        {
            Reset();
            OnServerStartFailure?.Invoke(
                new Exception(e.GetDataAsString() + e.Info)
                );
        }

        // This is called only on the server, not on the client side
        void Network_OnServerStopped(NetworkEvent e)
        {
            // Using a reserved packet tag,
            // we let all the clients know that we have closed the server
            if (CurrentMode == Mode.Server)
            {
                SendPacket(
                    Peers,
                    new Packet().WithTag(Packet.ReservedTags.ServerClosed),
                    true
                    );
                Reset();
                OnServerStop?.Invoke();
            }
        }

        void Network_OnNewConnection(NetworkEvent e)
        {
            if (CurrentMode == Mode.Server)
            {
                var theNewID = e.ConnectionId.id;

                // Notify a new client of its ID is using a reserved tag packet
                var tag    = Packet.ReservedTags.ClientSetID;
                var packet = new Packet().With(tag, theNewID.GetBytes());
                SendPacket(theNewID, packet, true);

                // Using reserved tag packets, let the new client know about
                // all the old clients and the old clients about the new client
                foreach (var anOldID in Peers)
                {
                    tag    = Packet.ReservedTags.ClientJoined;
                    packet = new Packet().With(tag, anOldID.GetBytes());
                    SendPacket(theNewID, packet, true);

                    tag    = Packet.ReservedTags.ClientJoined;
                    packet = new Packet().With(tag, theNewID.GetBytes());
                    SendPacket(anOldID, packet, true);
                }

                Peers.Add(theNewID);
                OnClientJoined?.Invoke(theNewID);
            }
            else if (CurrentMode == Mode.Idle)
            {
                serverCID   = e.ConnectionId;
                CurrentMode = Mode.Client;
                // Add the server as a peer. To the client, server ID is 0
                Peers.Add(0);
                Address = tmpAddress;
                OnConnected?.Invoke();
            }
        }

        void Network_OnConnectionFailed(NetworkEvent e)
        {
            Reset();
            var ex = new Exception(e.GetDataAsString() + e.Info);

            OnConnectionFailed?.Invoke(ex);
        }

        void Network_OnDisconnection(NetworkEvent e)
        {
            if (CurrentMode == Mode.Server)
            {
                Peers.Remove(e.ConnectionId.id);

                // Using a reserved tag, we let all the other clients know
                // that a client has left
                var tag    = Packet.ReservedTags.ClientLeft;
                var packet = new Packet().WithTag(tag)
                             .WithPayload(e.ConnectionId.id.GetBytes());
                SendPacket(Peers, packet, true);

                OnClientLeft?.Invoke(e.ConnectionId.id);
            }
            else if (CurrentMode == Mode.Client)
            {
                Reset();
                OnDisconnected?.Invoke();
            }
        }

        void Network_OnMessageReceived(NetworkEvent e, bool reliable)
        {
            var data = e.GetDataAsByteArray();

            var message = Message.Deserialize(data);
            var packet  = Packet.Deserialize(message.bytes);

            // Try to look for reserved keywords
            if (packet != null && packet.Tag.StartsWith("reserved"))
            {
                switch (packet.Tag)
                {
                case Packet.ReservedTags.ClientJoined:
                    if (CurrentMode == Mode.Client)
                    {
                        var cid = packet.Payload.ToShort();
                        Peers.Add(cid);
                        OnClientJoined?.Invoke(cid);
                    }
                    break;

                case Packet.ReservedTags.ClientLeft:
                    if (CurrentMode == Mode.Client)
                    {
                        var cid = packet.Payload.ToShort();
                        Peers.Remove(cid);
                        OnClientLeft?.Invoke(cid);
                    }
                    break;

                case Packet.ReservedTags.ClientSetID:
                    if (CurrentMode == Mode.Client)
                    {
                        ID = packet.Payload.ToShort();
                        OnReceiveID?.Invoke(ID);
                    }
                    break;

                case Packet.ReservedTags.ServerClosed:
                    Reset();
                    OnRemoteServerClosed?.Invoke();
                    break;
                }
                return;
            }

            // If we were an intended recipient
            if (message.recipients.Contains(ID))
            {
                if (packet != null)
                {
                    OnPacketReceived?.Invoke(message.sender, packet);
                }
                else
                {
                    OnBytesReceived?.Invoke(message.sender, message.bytes);
                }
            }

            // If we're a server, forward the message to the intended
            // recipients, except ourselves
            if (CurrentMode == Mode.Server)
            {
                foreach (var recipient in message.recipients)
                {
                    if (recipient != 0)
                    {
                        if (packet == null)
                        {
                            packet = new Packet();
                            packet.WithPayload(message.bytes);
                        }
                        var m = new Message {
                            sender     = message.sender,
                            recipients = new short[] { recipient },
                            bytes      = packet.Serialize()
                        };
                        network.SendData(
                            id: new ConnectionId(recipient),
                            data: m.Serialize(),
                            offset: 0,
                            len: m.Serialize().Length,
                            reliable: reliable
                            );
                    }
                }
            }
        }

        void Reset()
        {
            ID          = -1;
            CurrentMode = Mode.Idle;
            foreach (var peer in Peers)
            {
                OnClientLeft?.Invoke(peer);
            }
            Peers.Clear();
            Address = null;
        }