public unsafe bool GetDelayedPacket(ref NetworkPipelineContext ctx, ref NativeSlice<byte> delayedPacket,
            ref bool needsResume, ref bool needsUpdate, long currentTimestamp)
        {
            needsUpdate = needsResume = false;

            var dataSize = UnsafeUtility.SizeOf<DelayedPacket>();
            byte* processBufferPtr = (byte*) ctx.internalProcessBuffer.GetUnsafePtr();
            var simCtx = (Context*) ctx.internalSharedProcessBuffer.GetUnsafePtr();
            int oldestPacketIndex = -1;
            long oldestTime = long.MaxValue;
            int readyPackets = 0;
            int packetsInQueue = 0;
            for (int i = 0; i < m_PacketCount; i++)
            {
                DelayedPacket* packet = (DelayedPacket*) (processBufferPtr + dataSize * i);
                if ((int) packet->delayUntil == 0) continue;
                packetsInQueue++;

                if (packet->delayUntil > currentTimestamp) continue;
                readyPackets++;

                if (oldestTime <= packet->delayUntil) continue;
                oldestPacketIndex = i;
                oldestTime = packet->delayUntil;
            }

            simCtx->ReadyPackets = readyPackets;
            simCtx->WaitingPackets = packetsInQueue;
            simCtx->NextPacketTime = oldestTime;
            simCtx->StatsTime = currentTimestamp;

            // If more than one item has expired timer we need to resume this pipeline stage
            if (readyPackets > 1)
            {
                needsUpdate = false;
                needsResume = true;
            }
            // If more than one item is present (but doesn't have expired timer) we need to re-run the pipeline
            // in a later update call
            else if (packetsInQueue > 0)
            {
                needsUpdate = true;
                needsResume = false;
            }

            if (oldestPacketIndex >= 0)
            {
                DelayedPacket* packet = (DelayedPacket*) (processBufferPtr + dataSize * oldestPacketIndex);
                packet->delayUntil = 0;

                delayedPacket = new NativeSlice<byte>(ctx.internalProcessBuffer, packet->processBufferOffset,
                    packet->packetSize);
                return true;
            }

            return false;
        }
        public unsafe bool GetEmptyDataSlot(byte* processBufferPtr, ref int packetPayloadOffset,
            ref int packetDataOffset)
        {
            var dataSize = UnsafeUtility.SizeOf<DelayedPacket>();
            var packetPayloadStartOffset = m_PacketCount * dataSize;

            bool foundSlot = false;
            for (int i = 0; i < m_PacketCount; i++)
            {
                packetDataOffset = dataSize * i;
                DelayedPacket* packetData = (DelayedPacket*) (processBufferPtr + packetDataOffset);

                // Check if this slot is empty
                if (packetData->delayUntil == 0)
                {
                    foundSlot = true;
                    packetPayloadOffset = packetPayloadStartOffset + m_MaxPacketSize * i;
                    break;
                }
            }

            return foundSlot;
        }
Esempio n. 3
0
        public unsafe bool GetDelayedPacket(ref NetworkPipelineContext ctx, ref InboundSendBuffer delayedPacket,
                                            ref NetworkPipelineStage.Requests requests, long currentTimestamp)
        {
            requests = NetworkPipelineStage.Requests.None;

            var   dataSize          = UnsafeUtility.SizeOf <DelayedPacket>();
            byte *processBufferPtr  = (byte *)ctx.internalProcessBuffer;
            var   simCtx            = (Context *)ctx.internalSharedProcessBuffer;
            int   oldestPacketIndex = -1;
            long  oldestTime        = long.MaxValue;
            int   readyPackets      = 0;
            int   packetsInQueue    = 0;

            for (int i = 0; i < m_PacketCount; i++)
            {
                DelayedPacket *packet = (DelayedPacket *)(processBufferPtr + dataSize * i);
                if ((int)packet->delayUntil == 0)
                {
                    continue;
                }
                packetsInQueue++;

                if (packet->delayUntil > currentTimestamp)
                {
                    continue;
                }
                readyPackets++;

                if (oldestTime <= packet->delayUntil)
                {
                    continue;
                }
                oldestPacketIndex = i;
                oldestTime        = packet->delayUntil;
            }

            simCtx->ReadyPackets   = readyPackets;
            simCtx->WaitingPackets = packetsInQueue;
            simCtx->NextPacketTime = oldestTime;
            simCtx->StatsTime      = currentTimestamp;

            // If more than one item has expired timer we need to resume this pipeline stage
            if (readyPackets > 1)
            {
                requests |= NetworkPipelineStage.Requests.Resume;
            }
            // If more than one item is present (but doesn't have expired timer) we need to re-run the pipeline
            // in a later update call
            else if (packetsInQueue > 0)
            {
                requests |= NetworkPipelineStage.Requests.Update;
            }

            if (oldestPacketIndex >= 0)
            {
                DelayedPacket *packet = (DelayedPacket *)(processBufferPtr + dataSize * oldestPacketIndex);
                packet->delayUntil = 0;

                delayedPacket.bufferWithHeaders       = ctx.internalProcessBuffer + packet->processBufferOffset;
                delayedPacket.bufferWithHeadersLength = packet->packetSize;
                delayedPacket.headerPadding           = packet->packetHeaderPadding;
                delayedPacket.SetBufferFrombufferWithHeaders();
                return(true);
            }

            return(false);
        }