コード例 #1
0
        public void Update()
        {
            if (m_Socket.Poll(0, SelectMode.SelectRead))
            {
                int read = m_Socket.ReceiveFrom(m_Buffer, m_Buffer.Length, SocketFlags.None, ref endpoint);
                if (read > 0)
                {
                    var reader = new ByteInputStream(m_Buffer);
                    var header = new SQPHeader();
                    header.FromStream(ref reader);

                    switch (m_State)
                    {
                    case SQPClientState.Idle:
                        break;

                    case SQPClientState.WaitingForChallange:
                        if ((SQPMessageType)header.Type == SQPMessageType.ChallangeResponse)
                        {
                            if (endpoint.Equals(m_Server))
                            {
                                ChallangeId = header.ChallangeId;
                                SendServerInfoQuery();
                            }
                        }
                        break;

                    case SQPClientState.WaitingForResponse:
                        if ((SQPMessageType)header.Type == SQPMessageType.QueryResponse)
                        {
                            reader.Reset();
                            var rsp = new SQP.ServerInfo();
                            rsp.FromStream(ref reader);
                            Debug.Log(string.Format("ServerName: {0}, BuildId: {1}, Current Players: {2}, Max Players: {3}, GameType: {4}, Map: {5}, Port: {6}",
                                                    rsp.ServerInfoData.ServerName,
                                                    rsp.ServerInfoData.BuildId,
                                                    (ushort)rsp.ServerInfoData.CurrentPlayers,
                                                    (ushort)rsp.ServerInfoData.MaxPlayers,
                                                    rsp.ServerInfoData.GameType,
                                                    rsp.ServerInfoData.Map,
                                                    (ushort)rsp.ServerInfoData.Port));
                            m_State   = SQPClientState.Success;
                            StartTime = NetworkUtils.stopwatch.ElapsedMilliseconds;
                        }
                        break;

                    default:
                        break;
                    }
                }
            }
            var now = NetworkUtils.stopwatch.ElapsedMilliseconds;

            if (now - StartTime > 1000000)
            {
                Debug.Log("Failed");
                m_State = SQPClientState.Failure;
            }
        }
コード例 #2
0
    static public unsafe void Write <TOutputStream>(ref TOutputStream output, NetworkSchema schema, byte[] inputData, byte[] baselineData, byte[] fieldsChangedPrediction, byte fieldMask, ref uint entity_hash) where TOutputStream : NetworkCompression.IOutputStream
    {
        GameDebug.Assert(baselineData != null);
        var inputStream    = new ByteInputStream(inputData);
        var baselineStream = new ByteInputStream(baselineData);

        int numFields = schema.fields.Count;

        GameDebug.Assert(fieldsChangedPrediction.Length >= numFields / 8, "Not enough bits in fieldsChangedPrediction for all fields");

        for (int i = 0, l = fieldsNotPredicted.Length; i < l; ++i)
        {
            fieldsNotPredicted[i] = 0;
        }

        // calculate bitmask of fields that need to be encoded
        for (int fieldIndex = 0; fieldIndex < schema.fields.Count; ++fieldIndex)
        {
            var field = schema.fields[fieldIndex];

            // Skip fields that are masked out
            bool masked = (field.fieldMask & fieldMask) != 0;

            byte fieldByteOffset = (byte)((uint)fieldIndex >> 3);
            byte fieldBitOffset  = (byte)((uint)fieldIndex & 0x7);

            switch (field.fieldType)
            {
            case NetworkSchema.FieldType.Bool:
            {
                uint value    = inputStream.ReadBits(1);
                uint baseline = baselineStream.ReadUInt8();

                if (!masked)
                {
                    entity_hash = NetworkUtils.SimpleHashStreaming(entity_hash, value);
                    if (value != baseline)
                    {
                        fieldsNotPredicted[fieldByteOffset] |= (byte)(1 << fieldBitOffset);
                    }
                }

                break;
            }

            case NetworkSchema.FieldType.Int:
            {
                uint value    = inputStream.ReadBits(field.bits);
                uint baseline = (uint)baselineStream.ReadBits(field.bits);

                if (!masked)
                {
                    entity_hash = NetworkUtils.SimpleHashStreaming(entity_hash, value);
                    if (value != baseline)
                    {
                        fieldsNotPredicted[fieldByteOffset] |= (byte)(1 << fieldBitOffset);
                    }
                }
                break;
            }

            case NetworkSchema.FieldType.UInt:
            {
                uint value    = inputStream.ReadBits(field.bits);
                uint baseline = (uint)baselineStream.ReadBits(field.bits);

                if (!masked)
                {
                    entity_hash = NetworkUtils.SimpleHashStreaming(entity_hash, value);
                    if (value != baseline)
                    {
                        fieldsNotPredicted[fieldByteOffset] |= (byte)(1 << fieldBitOffset);
                    }
                }
                break;
            }

            case NetworkSchema.FieldType.Float:
            {
                uint value    = inputStream.ReadBits(field.bits);
                uint baseline = (uint)baselineStream.ReadBits(field.bits);

                if (!masked)
                {
                    entity_hash = NetworkUtils.SimpleHashStreaming(entity_hash, value);
                    if (value != baseline)
                    {
                        fieldsNotPredicted[fieldByteOffset] |= (byte)(1 << fieldBitOffset);
                    }
                }
                break;
            }

            case NetworkSchema.FieldType.Vector2:
            {
                uint vx = inputStream.ReadBits(field.bits);
                uint vy = inputStream.ReadBits(field.bits);

                uint bx = baselineStream.ReadUInt32();
                uint by = baselineStream.ReadUInt32();

                if (!masked)
                {
                    entity_hash = NetworkUtils.SimpleHashStreaming(entity_hash, vx);
                    entity_hash = NetworkUtils.SimpleHashStreaming(entity_hash, vy);
                    if (vx != bx || vy != by)
                    {
                        fieldsNotPredicted[fieldByteOffset] |= (byte)(1 << fieldBitOffset);
                    }
                }
                break;
            }

            case NetworkSchema.FieldType.Vector3:
            {
                uint vx = inputStream.ReadBits(field.bits);
                uint vy = inputStream.ReadBits(field.bits);
                uint vz = inputStream.ReadBits(field.bits);

                uint bx = baselineStream.ReadUInt32();
                uint by = baselineStream.ReadUInt32();
                uint bz = baselineStream.ReadUInt32();

                if (!masked)
                {
                    entity_hash = NetworkUtils.SimpleHashStreaming(entity_hash, vx);
                    entity_hash = NetworkUtils.SimpleHashStreaming(entity_hash, vy);
                    entity_hash = NetworkUtils.SimpleHashStreaming(entity_hash, vz);
                    if (vx != bx || vy != by || vz != bz)
                    {
                        fieldsNotPredicted[fieldByteOffset] |= (byte)(1 << fieldBitOffset);
                    }
                }
                break;
            }


            case NetworkSchema.FieldType.Quaternion:
            {
                uint vx = inputStream.ReadBits(field.bits);
                uint vy = inputStream.ReadBits(field.bits);
                uint vz = inputStream.ReadBits(field.bits);
                uint vw = inputStream.ReadBits(field.bits);

                uint bx = baselineStream.ReadUInt32();
                uint by = baselineStream.ReadUInt32();
                uint bz = baselineStream.ReadUInt32();
                uint bw = baselineStream.ReadUInt32();

                if (!masked)
                {
                    entity_hash = NetworkUtils.SimpleHashStreaming(entity_hash, vx);
                    entity_hash = NetworkUtils.SimpleHashStreaming(entity_hash, vy);
                    entity_hash = NetworkUtils.SimpleHashStreaming(entity_hash, vz);
                    entity_hash = NetworkUtils.SimpleHashStreaming(entity_hash, vw);
                    if (vx != bx || vy != by || vz != bz || vw != bw)
                    {
                        fieldsNotPredicted[fieldByteOffset] |= (byte)(1 << fieldBitOffset);
                    }
                }
                break;
            }


            case NetworkSchema.FieldType.String:
            case NetworkSchema.FieldType.ByteArray:
            {
                // TODO : Do a better job of string and buffer diffs?
                byte[] valueBuffer;
                int    valueOffset;
                int    valueLength;
                inputStream.GetByteArray(out valueBuffer, out valueOffset, out valueLength, field.arraySize);

                byte[] baselineBuffer = null;
                int    baselineOffset = 0;
                int    baselineLength = 0;
                baselineStream.GetByteArray(out baselineBuffer, out baselineOffset, out baselineLength, field.arraySize);

                if (!masked)
                {
                    entity_hash += 0;         // TODO client side has no easy way to hash strings. enable this when possible: NetworkUtils.SimpleHash(valueBuffer, valueLength);
                    if (valueLength != baselineLength || NetworkUtils.MemCmp(valueBuffer, valueOffset, baselineBuffer, baselineOffset, valueLength) != 0)
                    {
                        fieldsNotPredicted[fieldByteOffset] |= (byte)(1 << fieldBitOffset);
                    }
                }
            }
            break;
            }
        }

        inputStream.Reset();
        baselineStream.Reset();

        int skipContext = schema.id * NetworkConfig.maxContextsPerSchema + NetworkConfig.firstSchemaContext;

        // Client needs fieldsNotPredicted. We send the delta between it and fieldsChangedPrediction
        {
            for (int i = 0; i * 8 < numFields; i++)
            {
                byte deltaFields = (byte)(fieldsNotPredicted[i] ^ fieldsChangedPrediction[i]);
                output.WritePackedNibble((uint)(deltaFields & 0xF), skipContext + i * 2);
                output.WritePackedNibble((uint)((deltaFields >> 4) & 0xF), skipContext + i * 2 + 1);
            }
        }

        int startBitPosition = 0;

        for (int fieldIndex = 0; fieldIndex < numFields; ++fieldIndex)
        {
            var field             = schema.fields[fieldIndex];
            int fieldStartContext = field.startContext;
            startBitPosition = output.GetBitPosition2();

            byte fieldByteOffset = (byte)((uint)fieldIndex >> 3);
            byte fieldBitOffset  = (byte)((uint)fieldIndex & 0x7);
            var  notPredicted    = ((fieldsNotPredicted[fieldByteOffset] & (1 << fieldBitOffset)) != 0);

            switch (field.fieldType)
            {
            case NetworkSchema.FieldType.Bool:
            {
                uint value = inputStream.ReadBits(1);
                /*uint unused_baseline = */ baselineStream.ReadUInt8();

                if (notPredicted)
                {
                    output.WriteRawBits(value, 1);
                    NetworkSchema.AddStatsToFieldBool(field, (value != 0), false, output.GetBitPosition2() - startBitPosition);
                }
                break;
            }

            case NetworkSchema.FieldType.Int:
            {
                uint value    = inputStream.ReadBits(field.bits);
                uint baseline = (uint)baselineStream.ReadBits(field.bits);

                if (notPredicted)
                {
                    if (field.delta)
                    {
                        output.WritePackedUIntDelta(value, baseline, fieldStartContext);
                        NetworkSchema.AddStatsToFieldInt(field, (int)value, (int)baseline, output.GetBitPosition2() - startBitPosition);
                    }
                    else
                    {
                        output.WriteRawBits(value, field.bits);
                        NetworkSchema.AddStatsToFieldInt(field, (int)value, 0, output.GetBitPosition2() - startBitPosition);
                    }
                }
                break;
            }

            case NetworkSchema.FieldType.UInt:
            {
                uint value    = inputStream.ReadBits(field.bits);
                uint baseline = (uint)baselineStream.ReadBits(field.bits);

                if (notPredicted)
                {
                    if (field.delta)
                    {
                        output.WritePackedUIntDelta(value, baseline, fieldStartContext);
                        NetworkSchema.AddStatsToFieldUInt(field, value, baseline, output.GetBitPosition2() - startBitPosition);
                    }
                    else
                    {
                        output.WriteRawBits(value, field.bits);
                        NetworkSchema.AddStatsToFieldUInt(field, value, 0, output.GetBitPosition2() - startBitPosition);
                    }
                }
                break;
            }

            case NetworkSchema.FieldType.Float:
            {
                uint value    = inputStream.ReadBits(field.bits);
                uint baseline = (uint)baselineStream.ReadBits(field.bits);

                if (notPredicted)
                {
                    if (field.delta)
                    {
                        output.WritePackedUIntDelta(value, baseline, fieldStartContext);
                        NetworkSchema.AddStatsToFieldFloat(field, value, baseline, output.GetBitPosition2() - startBitPosition);
                    }
                    else
                    {
                        output.WriteRawBits(value, field.bits);
                        NetworkSchema.AddStatsToFieldFloat(field, value, 0, output.GetBitPosition2() - startBitPosition);
                    }
                }
                break;
            }

            case NetworkSchema.FieldType.Vector2:
            {
                uint vx = inputStream.ReadBits(field.bits);
                uint vy = inputStream.ReadBits(field.bits);

                uint bx = baselineStream.ReadUInt32();
                uint by = baselineStream.ReadUInt32();

                if (notPredicted)
                {
                    if (field.delta)
                    {
                        output.WritePackedUIntDelta(vx, bx, fieldStartContext + 0);
                        output.WritePackedUIntDelta(vy, by, fieldStartContext + 1);
                        NetworkSchema.AddStatsToFieldVector2(field, vx, vy, bx, by, output.GetBitPosition2() - startBitPosition);
                    }
                    else
                    {
                        output.WriteRawBits(vx, field.bits);
                        output.WriteRawBits(vy, field.bits);
                        NetworkSchema.AddStatsToFieldVector2(field, vx, vy, 0, 0, output.GetBitPosition2() - startBitPosition);
                    }
                }
                break;
            }

            case NetworkSchema.FieldType.Vector3:
            {
                uint vx = inputStream.ReadBits(field.bits);
                uint vy = inputStream.ReadBits(field.bits);
                uint vz = inputStream.ReadBits(field.bits);

                uint bx = baselineStream.ReadUInt32();
                uint by = baselineStream.ReadUInt32();
                uint bz = baselineStream.ReadUInt32();

                if (notPredicted)
                {
                    if (field.delta)
                    {
                        output.WritePackedUIntDelta(vx, bx, fieldStartContext + 0);
                        output.WritePackedUIntDelta(vy, by, fieldStartContext + 1);
                        output.WritePackedUIntDelta(vz, bz, fieldStartContext + 2);
                        NetworkSchema.AddStatsToFieldVector3(field, vx, vy, vz, bx, by, bz, output.GetBitPosition2() - startBitPosition);
                    }
                    else
                    {
                        output.WriteRawBits(vx, field.bits);
                        output.WriteRawBits(vy, field.bits);
                        output.WriteRawBits(vz, field.bits);
                        NetworkSchema.AddStatsToFieldVector3(field, vx, vy, vz, 0, 0, 0, output.GetBitPosition2() - startBitPosition);
                    }
                }
                break;
            }


            case NetworkSchema.FieldType.Quaternion:
            {
                // TODO : Figure out what to do with quaternions
                uint vx = inputStream.ReadBits(field.bits);
                uint vy = inputStream.ReadBits(field.bits);
                uint vz = inputStream.ReadBits(field.bits);
                uint vw = inputStream.ReadBits(field.bits);

                uint bx = baselineStream.ReadUInt32();
                uint by = baselineStream.ReadUInt32();
                uint bz = baselineStream.ReadUInt32();
                uint bw = baselineStream.ReadUInt32();

                if (notPredicted)
                {
                    if (field.delta)
                    {
                        output.WritePackedUIntDelta(vx, bx, fieldStartContext + 0);
                        output.WritePackedUIntDelta(vy, by, fieldStartContext + 1);
                        output.WritePackedUIntDelta(vz, bz, fieldStartContext + 2);
                        output.WritePackedUIntDelta(vw, bw, fieldStartContext + 3);
                        NetworkSchema.AddStatsToFieldQuaternion(field, vx, vy, vz, vw, bx, by, bz, bw, output.GetBitPosition2() - startBitPosition);
                    }
                    else
                    {
                        output.WriteRawBits(vx, field.bits);
                        output.WriteRawBits(vy, field.bits);
                        output.WriteRawBits(vz, field.bits);
                        output.WriteRawBits(vw, field.bits);
                        NetworkSchema.AddStatsToFieldQuaternion(field, vx, vy, vz, vw, 0, 0, 0, 0, output.GetBitPosition2() - startBitPosition);
                    }
                }
                break;
            }


            case NetworkSchema.FieldType.String:
            case NetworkSchema.FieldType.ByteArray:
            {
                // TODO : Do a better job of string and buffer diffs?
                byte[] valueBuffer;
                int    valueOffset;
                int    valueLength;
                inputStream.GetByteArray(out valueBuffer, out valueOffset, out valueLength, field.arraySize);

                byte[] baselineBuffer = null;
                int    baselineOffset = 0;
                int    baselineLength = 0;
                baselineStream.GetByteArray(out baselineBuffer, out baselineOffset, out baselineLength, field.arraySize);

                if (notPredicted)
                {
                    output.WritePackedUInt((uint)valueLength, fieldStartContext);
                    output.WriteRawBytes(valueBuffer, valueOffset, valueLength);

                    if (field.fieldType == NetworkSchema.FieldType.String)
                    {
                        NetworkSchema.AddStatsToFieldString(field, valueBuffer, valueOffset, valueLength, output.GetBitPosition2() - startBitPosition);
                    }
                    else
                    {
                        NetworkSchema.AddStatsToFieldByteArray(field, valueBuffer, valueOffset, valueLength, output.GetBitPosition2() - startBitPosition);
                    }
                }
            }
            break;
            }
        }
    }
コード例 #3
0
ファイル: SQP.cs プロジェクト: zy199711/FPSSample
        public void Update()
        {
            if (m_Socket.Poll(0, SelectMode.SelectRead))
            {
                int read = m_Socket.ReceiveFrom(m_Buffer, m_Buffer.Length, SocketFlags.None, ref endpoint);
                if (read > 0)
                {
                    var reader = new ByteInputStream(m_Buffer);
                    var header = new SQPHeader();
                    header.FromStream(ref reader);

                    SQPMessageType type = (SQPMessageType)header.Type;

                    switch (type)
                    {
                    case SQPMessageType.ChallangeRequest:
                    {
                        if (!m_OutstandingTokens.ContainsKey(endpoint))
                        {
                            uint token = GetNextToken();
                            //Debug.Log("token generated: " + token);

                            var writer = new ByteOutputStream(m_Buffer);
                            var rsp    = new ChallangeResponse();
                            rsp.Header.ChallangeId = token;
                            rsp.ToStream(ref writer);

                            m_Socket.SendTo(m_Buffer, writer.GetBytePosition(), SocketFlags.None, endpoint);

                            m_OutstandingTokens.Add(endpoint, token);
                        }
                    }
                    break;

                    case SQPMessageType.QueryRequest:
                    {
                        uint token;
                        if (!m_OutstandingTokens.TryGetValue(endpoint, out token))
                        {
                            //Debug.Log("Failed to find token!");
                            return;
                        }
                        m_OutstandingTokens.Remove(endpoint);

                        reader.Reset();
                        var req = new QueryRequest();
                        req.FromStream(ref reader);

                        if ((SQPChunkType)req.RequestedChunks == SQPChunkType.ServerInfo)
                        {
                            var rsp    = m_ServerInfo;
                            var writer = new ByteOutputStream(m_Buffer);
                            rsp.QueryHeader.Header.ChallangeId = token;

                            rsp.ToStream(ref writer);
                            m_Socket.SendTo(m_Buffer, writer.GetBytePosition(), SocketFlags.None, endpoint);
                        }
                    }
                    break;

                    default:
                        break;
                    }
                }
            }
        }
コード例 #4
0
ファイル: SQP.cs プロジェクト: zy199711/FPSSample
        public void Update()
        {
            if (m_Socket.Poll(0, SelectMode.SelectRead))
            {
                int read = m_Socket.ReceiveFrom(m_Buffer, m_Buffer.Length, SocketFlags.None, ref endpoint);
                if (read > 0)
                {
                    var reader = new ByteInputStream(m_Buffer);
                    var header = new SQPHeader();
                    header.FromStream(ref reader);

                    foreach (var q in m_Queries)
                    {
                        if (q.m_Server == null || !endpoint.Equals(q.m_Server))
                        {
                            continue;
                        }

                        switch (q.m_State)
                        {
                        case SQPClientState.Idle:
                            // Just ignore if we get extra data
                            break;

                        case SQPClientState.WaitingForChallange:
                            if ((SQPMessageType)header.Type == SQPMessageType.ChallangeResponse)
                            {
                                q.ChallangeId = header.ChallangeId;
                                q.RTT         = NetworkUtils.stopwatch.ElapsedMilliseconds - q.StartTime;
                                // We restart timer so we can get an RTT that is an average between two measurements
                                q.StartTime = NetworkUtils.stopwatch.ElapsedMilliseconds;
                                SendServerInfoQuery(q);
                            }
                            break;

                        case SQPClientState.WaitingForResponse:
                            if ((SQPMessageType)header.Type == SQPMessageType.QueryResponse)
                            {
                                reader.Reset();
                                q.m_ServerInfo.FromStream(ref reader);

                                // We report the average of two measurements
                                q.RTT = (q.RTT + (NetworkUtils.stopwatch.ElapsedMilliseconds - q.StartTime)) / 2;

                                /*
                                 * GameDebug.Log(string.Format("ServerName: {0}, BuildId: {1}, Current Players: {2}, Max Players: {3}, GameType: {4}, Map: {5}, Port: {6}",
                                 *  m_ServerInfo.ServerInfoData.ServerName,
                                 *  m_ServerInfo.ServerInfoData.BuildId,
                                 *  (ushort)m_ServerInfo.ServerInfoData.CurrentPlayers,
                                 *  (ushort)m_ServerInfo.ServerInfoData.MaxPlayers,
                                 *  m_ServerInfo.ServerInfoData.GameType,
                                 *  m_ServerInfo.ServerInfoData.Map,
                                 *  (ushort)m_ServerInfo.ServerInfoData.Port));
                                 */

                                q.validResult = true;
                                q.m_State     = SQPClientState.Idle;
                            }
                            break;

                        default:
                            break;
                        }
                    }
                }
            }

            foreach (var q in m_Queries)
            {
                // Timeout if stuck in any state but idle for too long
                if (q.m_State != SQPClientState.Idle)
                {
                    var now = NetworkUtils.stopwatch.ElapsedMilliseconds;
                    if (now - q.StartTime > 3000)
                    {
                        q.m_State = SQPClientState.Idle;
                    }
                }
            }
        }