Example #1
0
        /// <summary>
        /// Remove an object with the specified unique identifier.
        /// </summary>

        public bool DestroyObject(uint objID)
        {
            if (objID < 32768)
            {
                // Static objects have ID below 32768
                if (!destroyed.Contains(objID))
                {
                    destroyed.Add(objID);
                    DestroyObjectRFCs(objID);
                    return(true);
                }
            }
            else if (mCreatedObjectDictionary.Remove(objID))
            {
                // Dynamic objects are always a part of the 'created' array and the lookup table
                for (int i = 0; i < created.size; ++i)
                {
                    Channel.CreatedObject obj = created[i];

                    if (obj.objectID == objID)
                    {
                        if (obj.buffer != null)
                        {
                            obj.buffer.Recycle();
                        }
                        created.RemoveAt(i);
                        DestroyObjectRFCs(objID);
                        return(true);
                    }
                }
            }
            return(false);
        }
Example #2
0
        /// <summary>
        /// Remove an object with the specified unique identifier.
        /// </summary>

        public bool DestroyObject(uint uniqueID)
        {
            if (!destroyed.Contains(uniqueID))
            {
                for (int i = 0; i < created.size; ++i)
                {
                    Channel.CreatedObject obj = created[i];

                    if (obj.uniqueID == uniqueID)
                    {
                        if (obj.buffer != null)
                        {
                            obj.buffer.Recycle();
                        }
                        created.RemoveAt(i);
                        DestroyObjectRFCs(uniqueID);
                        return(true);
                    }
                }
                destroyed.Add(uniqueID);
                DestroyObjectRFCs(uniqueID);
                return(true);
            }
            return(false);
        }
Example #3
0
        /// <summary>
        /// Remove the specified player from the channel.
        /// </summary>

        public void RemovePlayer(TcpPlayer p, List <uint> destroyedObjects)
        {
            destroyedObjects.Clear();

            if (players.Remove(p))
            {
                // When the host leaves, clear the host (it gets changed in SendLeaveChannel)
                if (p == host)
                {
                    host = null;
                }

                // Remove all of the non-persistent objects that were created by this player
                for (int i = created.size; i > 0;)
                {
                    Channel.CreatedObject obj = created[--i];

                    if (obj.playerID == p.id)
                    {
                        if (obj.type == 2)
                        {
                            if (obj.buffer != null)
                            {
                                obj.buffer.Recycle();
                            }
                            uint objID = obj.objectID;
                            created.RemoveAt(i);
                            destroyedObjects.Add(objID);
                            if (objID >= 32768)
                            {
                                mCreatedObjectDictionary.Remove(objID);
                            }
                            DestroyObjectRFCs(objID);
                        }
                        else if (players.size != 0)
                        {
                            // The same operation happens on the client as well
                            obj.playerID = players[0].id;
                        }
                    }
                }

                // Close the channel if it wasn't persistent
                if ((!persistent || playerLimit < 1) && players.size == 0)
                {
                    closed = true;

                    for (int i = 0; i < rfcs.size; ++i)
                    {
                        RFC r = rfcs[i];
                        if (r.data != null)
                        {
                            r.data.Recycle();
                        }
                    }
                    rfcs.Clear();
                }
            }
        }
Example #4
0
        /// <summary>
        /// Remove the specified player from the channel.
        /// </summary>

        public void RemovePlayer(TcpPlayer p, List <uint> destroyedObjects)
        {
            destroyedObjects.Clear();

            if (p == host)
            {
                host = null;
            }

            if (players.Remove(p))
            {
                // Remove all of the non-persistent objects that were created by this player
                for (int i = created.size; i > 0;)
                {
                    Channel.CreatedObject obj = created[--i];

                    if (obj.type == 2 && obj.playerID == p.id)
                    {
                        if (obj.buffer != null)
                        {
                            obj.buffer.Recycle();
                        }
                        created.RemoveAt(i);
                        destroyedObjects.Add(obj.uniqueID);
                        DestroyObjectRFCs(obj.uniqueID);
                    }
                }

                // Close the channel if it wasn't persistent
                if ((!persistent || playerLimit < 1) && players.size == 0)
                {
                    closed = true;

                    for (int i = 0; i < rfcs.size; ++i)
                    {
                        RFC r = rfcs[i];
                        if (r.buffer != null)
                        {
                            r.buffer.Recycle();
                        }
                    }
                    rfcs.Clear();
                }
            }
        }
        /// <summary>
        /// Channel joining process involves multiple steps. It's faster to perform them all at once.
        /// </summary>

        public void FinishJoiningChannel()
        {
            Buffer buffer = Buffer.Create();

            // Step 2: Tell the player who else is in the channel
            BinaryWriter writer = buffer.BeginPacket(Packet.ResponseJoiningChannel);
            {
                writer.Write(channel.id);
                writer.Write((short)channel.players.size);

                for (int i = 0; i < channel.players.size; ++i)
                {
                    TcpPlayer tp = channel.players[i];
                    writer.Write(tp.id);
                    writer.Write(string.IsNullOrEmpty(tp.name) ? "Guest" : tp.name);
                }
            }

            // End the first packet, but remember where it ended
            int offset = buffer.EndPacket();

            // Step 3: Inform the player of who is hosting
            if (channel.host == null)
            {
                channel.host = this;
            }
            buffer.BeginPacket(Packet.ResponseSetHost, offset);
            writer.Write(channel.host.id);
            offset = buffer.EndTcpPacketStartingAt(offset);

            // Step 4: Send the channel's data
            if (!string.IsNullOrEmpty(channel.data))
            {
                buffer.BeginPacket(Packet.ResponseSetChannelData, offset);
                writer.Write(channel.data);
                offset = buffer.EndTcpPacketStartingAt(offset);
            }

            // Step 5: Inform the player of what level we're on
            buffer.BeginPacket(Packet.ResponseLoadLevel, offset);
            writer.Write(string.IsNullOrEmpty(channel.level) ? "" : channel.level);
            offset = buffer.EndTcpPacketStartingAt(offset);

            // Step 6: Send the list of objects that have been created
            for (int i = 0; i < channel.created.size; ++i)
            {
                Channel.CreatedObject obj = channel.created.buffer[i];
                buffer.BeginPacket(Packet.ResponseCreate, offset);
                writer.Write(obj.playerID);
                writer.Write(obj.objectID);
                writer.Write(obj.uniqueID);
                writer.Write(obj.buffer.buffer, obj.buffer.position, obj.buffer.size);
                offset = buffer.EndTcpPacketStartingAt(offset);
            }

            // Step 7: Send the list of objects that have been destroyed
            if (channel.destroyed.size != 0)
            {
                buffer.BeginPacket(Packet.ResponseDestroy, offset);
                writer.Write((ushort)channel.destroyed.size);
                for (int i = 0; i < channel.destroyed.size; ++i)
                {
                    writer.Write(channel.destroyed.buffer[i]);
                }
                offset = buffer.EndTcpPacketStartingAt(offset);
            }

            // Step 8: Send all buffered RFCs to the new player
            for (int i = 0; i < channel.rfcs.size; ++i)
            {
                Buffer rfcBuff = channel.rfcs[i].buffer;
                rfcBuff.BeginReading();
                buffer.BeginWriting(offset);
                writer.Write(rfcBuff.buffer, rfcBuff.position, rfcBuff.size);
                offset = buffer.EndWriting();
            }

            // Step 9: The join process is now complete
            buffer.BeginPacket(Packet.ResponseJoinChannel, offset);
            writer.Write(true);
            offset = buffer.EndTcpPacketStartingAt(offset);

            // Send the entire buffer
            SendTcpPacket(buffer);
            buffer.Recycle();
        }
Example #6
0
        /// <summary>
        /// Channel joining process involves multiple steps. It's faster to perform them all at once.
        /// </summary>

        public void FinishJoiningChannel()
        {
            Buffer buffer = Buffer.Create();

            // Step 2: Tell the player who else is in the channel
            BinaryWriter writer = buffer.BeginPacket(Packet.ResponseJoiningChannel);
            {
                writer.Write(channel.id);
                writer.Write((short)channel.players.size);

                for (int i = 0; i < channel.players.size; ++i)
                {
                    TcpPlayer tp = channel.players[i];
                    writer.Write(tp.id);
                    writer.Write(string.IsNullOrEmpty(tp.name) ? "Guest" : tp.name);
#if STANDALONE
                    if (tp.data == null)
                    {
                        writer.Write((byte)0);
                    }
                    else
                    {
                        writer.Write((byte[])tp.data);
                    }
#else
                    writer.WriteObject(tp.data);
#endif
                }
            }

            // End the first packet, but remember where it ended
            int offset = buffer.EndPacket();

            // Step 3: Inform the player of who is hosting
            if (channel.host == null)
            {
                channel.host = this;
            }
            buffer.BeginPacket(Packet.ResponseSetHost, offset);
            writer.Write(channel.host.id);
            offset = buffer.EndTcpPacketStartingAt(offset);

            // Step 4: Send the channel's data
            if (!string.IsNullOrEmpty(channel.data))
            {
                buffer.BeginPacket(Packet.ResponseSetChannelData, offset);
                writer.Write(channel.data);
                offset = buffer.EndTcpPacketStartingAt(offset);
            }

            // Step 5: Inform the player of what level we're on
            buffer.BeginPacket(Packet.ResponseLoadLevel, offset);
            writer.Write(string.IsNullOrEmpty(channel.level) ? "" : channel.level);
            offset = buffer.EndTcpPacketStartingAt(offset);

            // Step 6: Send the list of objects that have been created
            for (int i = 0; i < channel.created.size; ++i)
            {
                Channel.CreatedObject obj = channel.created.buffer[i];

                bool isPresent = false;

                for (int b = 0; b < channel.players.size; ++b)
                {
                    if (channel.players[b].id == obj.playerID)
                    {
                        isPresent = true;
                        break;
                    }
                }

                // If the previous owner is not present, transfer ownership to the host
                if (!isPresent)
                {
                    obj.playerID = channel.host.id;
                }

                buffer.BeginPacket(Packet.ResponseCreate, offset);
                writer.Write(obj.playerID);
                writer.Write(obj.objectIndex);
                writer.Write(obj.objectID);
                writer.Write(obj.buffer.buffer, obj.buffer.position, obj.buffer.size);
                offset = buffer.EndTcpPacketStartingAt(offset);
            }

            // Step 7: Send the list of objects that have been destroyed
            if (channel.destroyed.size != 0)
            {
                buffer.BeginPacket(Packet.ResponseDestroy, offset);
                writer.Write((ushort)channel.destroyed.size);
                for (int i = 0; i < channel.destroyed.size; ++i)
                {
                    writer.Write(channel.destroyed.buffer[i]);
                }
                offset = buffer.EndTcpPacketStartingAt(offset);
            }

            // Step 8: Send all buffered RFCs to the new player
            for (int i = 0; i < channel.rfcs.size; ++i)
            {
                Channel.RFC rfc = channel.rfcs[i];
                buffer.BeginWriting(offset);
                writer.Write(rfc.buffer.buffer, 0, rfc.buffer.size);
                offset = buffer.EndWriting();
            }

            // Step 9: The join process is now complete
            buffer.BeginPacket(Packet.ResponseJoinChannel, offset);
            writer.Write(true);
            offset = buffer.EndTcpPacketStartingAt(offset);

            // Send the entire buffer
            SendTcpPacket(buffer);
            buffer.Recycle();
        }
        /// <summary>
        /// Process a packet from the player.
        /// </summary>

        void ProcessChannelPacket(TcpPlayer player, Buffer buffer, BinaryReader reader, Packet request)
        {
            switch (request)
            {
            case Packet.RequestCreate:
            {
                // Create a new object
                ushort objectIndex = reader.ReadUInt16();
                byte   type        = reader.ReadByte();
                uint   uniqueID    = 0;

                if (type != 0)
                {
                    uniqueID = --player.channel.objectCounter;

                    // 1-32767 is reserved for existing scene objects.
                    // 32768 - 16777215 is for dynamically created objects.
                    if (uniqueID < 32768)
                    {
                        player.channel.objectCounter = 0xFFFFFF;
                        uniqueID = 0xFFFFFF;
                    }

                    Channel.CreatedObject obj = new Channel.CreatedObject();
                    obj.playerID = player.id;
                    obj.objectID = objectIndex;
                    obj.uniqueID = uniqueID;
                    obj.type     = type;

                    if (buffer.size > 0)
                    {
                        obj.buffer = buffer;
                        buffer.MarkAsUsed();
                    }
                    player.channel.created.Add(obj);
                }

                // Inform the channel
                BinaryWriter writer = BeginSend(Packet.ResponseCreate);
                writer.Write(player.id);
                writer.Write(objectIndex);
                writer.Write(uniqueID);
                if (buffer.size > 0)
                {
                    writer.Write(buffer.buffer, buffer.position, buffer.size);
                }
                EndSend(true, player.channel, null);
                break;
            }

            case Packet.RequestDestroy:
            {
                // Destroy the specified network object
                uint uniqueID = reader.ReadUInt32();

                // Remove this object
                if (player.channel.DestroyObject(uniqueID))
                {
                    // Inform all players in the channel that the object should be destroyed
                    BinaryWriter writer = BeginSend(Packet.ResponseDestroy);
                    writer.Write((ushort)1);
                    writer.Write(uniqueID);
                    EndSend(true, player.channel, null);
                }
                break;
            }

            case Packet.RequestLoadLevel:
            {
                // Change the currently loaded level
                if (player.channel.host == player)
                {
                    player.channel.Reset();
                    player.channel.level = reader.ReadString();

                    BinaryWriter writer = BeginSend(Packet.ResponseLoadLevel);
                    writer.Write(string.IsNullOrEmpty(player.channel.level) ? "" : player.channel.level);
                    EndSend(true, player.channel, null);
                }
                break;
            }

            case Packet.RequestSetHost:
            {
                // Transfer the host state from one player to another
                if (player.channel.host == player)
                {
                    TcpPlayer newHost = GetPlayer(reader.ReadInt32());
                    if (newHost != null && newHost.channel == player.channel)
                    {
                        SendSetHost(newHost);
                    }
                }
                break;
            }

            case Packet.RequestLeaveChannel:
            {
                SendLeaveChannel(player, true);
                break;
            }

            case Packet.RequestCloseChannel:
            {
                player.channel.persistent = false;
                player.channel.closed     = true;
                break;
            }

            case Packet.RequestSetPlayerLimit:
            {
                player.channel.playerLimit = reader.ReadUInt16();
                break;
            }

            case Packet.RequestRemoveRFC:
            {
                uint   id       = reader.ReadUInt32();
                string funcName = ((id & 0xFF) == 0) ? reader.ReadString() : null;
                player.channel.DeleteRFC(id, funcName);
                break;
            }

            case Packet.RequestSetChannelData:
            {
                player.channel.data = reader.ReadString();
                BinaryWriter writer = BeginSend(Packet.ResponseSetChannelData);
                writer.Write(player.channel.data);
                EndSend(true, player.channel, null);
                break;
            }
            }
        }
Example #8
0
        /// <summary>
        /// Process a packet from the player.
        /// </summary>
        void ProcessChannelPacket(TcpPlayer player, Buffer buffer, BinaryReader reader, Packet request)
        {
            switch (request)
            {
            case Packet.RequestCreate:
            {
                // Create a new object
                ushort objectIndex = reader.ReadUInt16();
                byte type = reader.ReadByte();
                uint uniqueID = 0;

                if (type != 0)
                {
                    uniqueID = --player.channel.objectCounter;

                    // 1-32767 is reserved for existing scene objects.
                    // 32768 - 16777215 is for dynamically created objects.
                    if (uniqueID < 32768)
                    {
                        player.channel.objectCounter = 0xFFFFFF;
                        uniqueID = 0xFFFFFF;
                    }

                    Channel.CreatedObject obj = new Channel.CreatedObject();
                    obj.playerID = player.id;
                    obj.objectID = objectIndex;
                    obj.uniqueID = uniqueID;
                    obj.type = type;

                    if (buffer.size > 0)
                    {
                        obj.buffer = buffer;
                        buffer.MarkAsUsed();
                    }
                    player.channel.created.Add(obj);
                }

                // Inform the channel
                BinaryWriter writer = BeginSend(Packet.ResponseCreate);
                writer.Write(player.id);
                writer.Write(objectIndex);
                writer.Write(uniqueID);
                if (buffer.size > 0) writer.Write(buffer.buffer, buffer.position, buffer.size);
                EndSend(true, player.channel, null);
                break;
            }
            case Packet.RequestDestroy:
            {
                // Destroy the specified network object
                uint uniqueID = reader.ReadUInt32();

                // Remove this object
                if (player.channel.DestroyObject(uniqueID))
                {
                    // Inform all players in the channel that the object should be destroyed
                    BinaryWriter writer = BeginSend(Packet.ResponseDestroy);
                    writer.Write((ushort)1);
                    writer.Write(uniqueID);
                    EndSend(true, player.channel, null);
                }
                break;
            }
            case Packet.RequestLoadLevel:
            {
                // Change the currently loaded level
                if (player.channel.host == player)
                {
                    player.channel.Reset();
                    player.channel.level = reader.ReadString();

                    BinaryWriter writer = BeginSend(Packet.ResponseLoadLevel);
                    writer.Write(string.IsNullOrEmpty(player.channel.level) ? "" : player.channel.level);
                    EndSend(true, player.channel, null);
                }
                break;
            }
            case Packet.RequestSetHost:
            {
                // Transfer the host state from one player to another
                if (player.channel.host == player)
                {
                    TcpPlayer newHost = GetPlayer(reader.ReadInt32());
                    if (newHost != null && newHost.channel == player.channel) SendSetHost(newHost);
                }
                break;
            }
            case Packet.RequestLeaveChannel:
            {
                SendLeaveChannel(player, true);
                break;
            }
            case Packet.RequestCloseChannel:
            {
                player.channel.persistent = false;
                player.channel.closed = true;
                break;
            }
            case Packet.RequestSetPlayerLimit:
            {
                player.channel.playerLimit = reader.ReadUInt16();
                break;
            }
            case Packet.RequestRemoveRFC:
            {
                uint id = reader.ReadUInt32();
                string funcName = ((id & 0xFF) == 0) ? reader.ReadString() : null;
                player.channel.DeleteRFC(id, funcName);
                break;
            }
            case Packet.RequestSetChannelData:
            {
                player.channel.data = reader.ReadString();
                BinaryWriter writer = BeginSend(Packet.ResponseSetChannelData);
                writer.Write(player.channel.data);
                EndSend(true, player.channel, null);
                break;
            }
            }
        }