Ejemplo n.º 1
0
 public NetworkReader(byte[] buffer, NetworkSchema schema)
 {
     m_Input          = new ByteInputStream(buffer);
     m_Schema         = schema;
     m_CurrentField   = null;
     m_NextFieldIndex = 0;
 }
Ejemplo n.º 2
0
        public CreateNetworkDialog(NetworkSchema schema)
        {
            InitializeComponent();

            this.m_networkSchema = schema;
            this.cbHiddenLayerNumber.DataSource = new int[] { 0, 1, 2, 3, 4 };
        }
Ejemplo n.º 3
0
        static void TestDelta <TInputStream, TOutputStream>(NetworkSchema schema, List <object> values, List <object> baselineValues)  where TInputStream : NetworkCompression.IInputStream, new()
            where TOutputStream : NetworkCompression.IOutputStream, new()
        {
            var inputBuffer    = new byte[1024 * 64];
            var baselineBuffer = new byte[1024 * 64];
            var deltaBuffer    = new byte[1024 * 64];
            var outputBuffer   = new byte[1024 * 64];

            NetworkTestUtils.WriteValues(values, inputBuffer, schema);

            if (baselineValues != null)
            {
                NetworkTestUtils.WriteValues(baselineValues, baselineBuffer, schema);
            }
            else
            {
                baselineBuffer = new byte[1024 * 64];
            }

            var outputStream = new TOutputStream();

            outputStream.Initialize(NetworkCompressionModel.DefaultModel, deltaBuffer, 0, null);
            uint hash = 0;

            DeltaWriter.Write(ref outputStream, schema, inputBuffer, baselineBuffer, zeroFieldsChanged, 0, ref hash);
            outputStream.Flush();

            var inputStream = new TInputStream();

            inputStream.Initialize(NetworkCompressionModel.DefaultModel, deltaBuffer, 0);
            hash = 0;
            DeltaReader.Read(ref inputStream, schema, outputBuffer, baselineBuffer, zeroFieldsChanged, 0, ref hash);

            NetworkTestUtils.ReadAndAssertValues(values, outputBuffer, schema);
        }
Ejemplo n.º 4
0
        public void Delta_Vector3Compressed <TInputStream, TOutputStream>() where TInputStream : NetworkCompression.IInputStream, new()
            where TOutputStream : NetworkCompression.IOutputStream, new()
        {
            var schema = new NetworkSchema(0);

            schema.AddField(new NetworkSchema.FieldInfo()
            {
                name = "field_0", fieldType = NetworkSchema.FieldType.Vector3, bits = 32, delta = true, precision = 3
            });

            var values = new List <object>()
            {
                new Vector3()
                {
                    x = 0.07870922f, y = 0.0479902327f, z = 0.16897355f
                }
            };
            var baseline = new List <object>()
            {
                new Vector3()
                {
                    x = -122.123f, y = 112.32112f, z = 0.0235f
                }
            };

            TestDelta <TInputStream, TOutputStream>(schema, values, baseline);
        }
Ejemplo n.º 5
0
        //   private NetworkSchema m_networkSchema;

        //---------------------------------------------


        #region Constructor
        public CreateNetworkDialog(NetworkSchema schema)
        {
            InitializeComponent();

            this.m_networkSchema = schema;
            this.cbHiddenLayerNumber.DataSource = new int[] { 0, 1, 2, 3, 4 };
        }
Ejemplo n.º 6
0
        void ReadCommands(ref RawInputStream input)
        {
            counters.commandsIn++;
            var schema = input.ReadRawBits(1) != 0;

            if (schema)
            {
                commandSchema = NetworkSchema.ReadSchema(ref input);    // might be overridden
            }

            // NETTODO Reconstruct the wide sequence
            // NETTODO Rename to commandMessageSequence?
            var sequence = Sequence.FromUInt16((ushort)input.ReadRawBits(16), commandSequenceIn);

            if (sequence > commandSequenceIn)
            {
                commandSequenceIn = sequence;
            }

            CommandInfo previous = defaultCommandInfo;

            while (input.ReadRawBits(1) != 0)
            {
                var command = commandsIn.Acquire(sequence);
                command.time = (int)input.ReadPackedIntDelta(previous.time, NetworkConfig.commandTimeContext);

                uint hash = 0;
                DeltaReader.Read(ref input, commandSchema, command.data, previous.data, zeroFieldsChanged, 0, ref hash);

                previous = command;
                --sequence;
            }
        }
Ejemplo n.º 7
0
 public NetworkReader(uint *buffer, NetworkSchema schema)
 {
     m_Input          = buffer;
     m_Position       = 0;
     m_Schema         = schema;
     m_CurrentField   = null;
     m_NextFieldIndex = 0;
 }
Ejemplo n.º 8
0
 public NetworkWriter(byte[] buffer, NetworkSchema schema, bool generateSchema = false)
 {
     m_Output         = new ByteOutputStream(buffer);
     m_Schema         = schema;
     m_CurrentField   = null;
     m_NextFieldIndex = 0;
     m_GenerateSchema = generateSchema;
     m_FieldMask      = 0;
 }
Ejemplo n.º 9
0
 public NetworkWriter(uint *buffer, int bufferSize, NetworkSchema schema, bool generateSchema = false)
 {
     m_Output         = buffer;
     m_BufferSize     = bufferSize;
     m_Position       = 0;
     m_Schema         = schema;
     m_CurrentField   = null;
     m_NextFieldIndex = 0;
     m_GenerateSchema = generateSchema;
     m_FieldMask      = 0;
 }
Ejemplo n.º 10
0
    public static void CopyFieldsFromBuffer <TOutputStream>(NetworkSchema schema, byte[] inputBuffer, ref TOutputStream output) where TOutputStream : NetworkCompression.IOutputStream
    {
        var input = new ByteInputStream(inputBuffer);

        int fieldIndex = 0;

        for (; fieldIndex < schema.fields.Count; ++fieldIndex)
        {
            var field = schema.fields[fieldIndex];
            switch (field.fieldType)
            {
            case NetworkSchema.FieldType.Bool:
            case NetworkSchema.FieldType.UInt:
            case NetworkSchema.FieldType.Int:
            case NetworkSchema.FieldType.Float:
                output.WriteRawBits(input.ReadBits(field.bits), field.bits);
                break;

            case NetworkSchema.FieldType.Vector2:
                output.WriteRawBits(input.ReadUInt32(), field.bits);
                output.WriteRawBits(input.ReadUInt32(), field.bits);
                break;

            case NetworkSchema.FieldType.Vector3:
                output.WriteRawBits(input.ReadUInt32(), field.bits);
                output.WriteRawBits(input.ReadUInt32(), field.bits);
                output.WriteRawBits(input.ReadUInt32(), field.bits);
                break;

            case NetworkSchema.FieldType.Quaternion:
                output.WriteRawBits(input.ReadUInt32(), field.bits);
                output.WriteRawBits(input.ReadUInt32(), field.bits);
                output.WriteRawBits(input.ReadUInt32(), field.bits);
                output.WriteRawBits(input.ReadUInt32(), field.bits);
                break;

            case NetworkSchema.FieldType.String:
            case NetworkSchema.FieldType.ByteArray:
            {
                byte[] data;
                int    dataIndex;
                int    dataSize;
                input.GetByteArray(out data, out dataIndex, out dataSize, field.arraySize);
                output.WritePackedUInt((uint)dataSize, field.startContext);
                output.WriteRawBytes(data, dataIndex, dataSize);
            }
            break;

            default: GameDebug.Assert(false); break;
            }
        }
    }
Ejemplo n.º 11
0
    unsafe public static void CopyFieldsFromBuffer <TOutputStream>(NetworkSchema schema, uint *inputBuffer, ref TOutputStream output) where TOutputStream : NetworkCompression.IOutputStream
    {
        int index = 0;

        int fieldIndex = 0;

        for (; fieldIndex < schema.fieldsInternal.Count; ++fieldIndex)
        {
            var field = schema.fieldsInternal[fieldIndex];
            switch (field.fieldType)
            {
            case NetworkSchema.FieldType.Bool:
            case NetworkSchema.FieldType.UInt:
            case NetworkSchema.FieldType.Int:
            case NetworkSchema.FieldType.Float:
                output.WritePackedUInt(inputBuffer[index++], NetworkConfig.miscContext);
                break;

            case NetworkSchema.FieldType.Vector2:
                output.WritePackedUInt(inputBuffer[index++], NetworkConfig.miscContext);
                output.WritePackedUInt(inputBuffer[index++], NetworkConfig.miscContext);
                break;

            case NetworkSchema.FieldType.Vector3:
                output.WritePackedUInt(inputBuffer[index++], NetworkConfig.miscContext);
                output.WritePackedUInt(inputBuffer[index++], NetworkConfig.miscContext);
                output.WritePackedUInt(inputBuffer[index++], NetworkConfig.miscContext);
                break;

            case NetworkSchema.FieldType.Quaternion:
                output.WritePackedUInt(inputBuffer[index++], NetworkConfig.miscContext);
                output.WritePackedUInt(inputBuffer[index++], NetworkConfig.miscContext);
                output.WritePackedUInt(inputBuffer[index++], NetworkConfig.miscContext);
                output.WritePackedUInt(inputBuffer[index++], NetworkConfig.miscContext);
                break;

            case NetworkSchema.FieldType.String:
            case NetworkSchema.FieldType.ByteArray:
            {
                uint dataSize = inputBuffer[index++];

                output.WritePackedUInt(dataSize, field.startContext);
                output.WriteRawBytes((byte *)(inputBuffer + index), (int)dataSize);
                index += field.arraySize / 4;
            }
            break;

            default: GameDebug.Assert(false); break;
            }
        }
    }
Ejemplo n.º 12
0
 public static void WriteSchema <TOutputStream>(NetworkSchema schema, ref TOutputStream output) where TOutputStream : NetworkCompression.IOutputStream
 {
     output.WritePackedUInt((uint)schema.fields.Count, NetworkConfig.miscContext);
     output.WritePackedUInt((uint)schema.id, NetworkConfig.miscContext);
     foreach (var field in schema.fields)
     {
         output.WriteRawBits((uint)field.fieldType, 4);
         output.WriteRawBits(field.delta ? 1U : 0, 1);
         output.WriteRawBits((uint)field.bits, 6);
         output.WriteRawBits((uint)field.precision, 2);
         output.WriteRawBits((uint)field.arraySize, 16);
         output.WriteRawBits((uint)field.fieldMask, 8);
     }
 }
Ejemplo n.º 13
0
 public static void WriteSchema <TOutputStream>(NetworkSchema schema, ref TOutputStream output) where TOutputStream : NetworkCompression.IOutputStream
 {
     output.WritePackedUInt((uint)schema.fieldsInternal.Count, NetworkConfig.miscContext);
     output.WritePackedUInt((uint)schema.id, NetworkConfig.miscContext);
     for (int i = 0; i < schema.numFields; ++i)
     {
         var field = schema.fields[i];
         output.WritePackedNibble((uint)field.fieldType, NetworkConfig.miscContext);
         output.WriteRawBits(field.delta ? 1U : 0, 1);
         output.WritePackedUInt((uint)field.bits, NetworkConfig.miscContext);
         output.WritePackedUInt((uint)field.precision, NetworkConfig.miscContext);
         output.WritePackedUInt((uint)field.arraySize, NetworkConfig.miscContext);
         output.WritePackedUInt((uint)field.fieldMask, NetworkConfig.miscContext);
     }
 }
Ejemplo n.º 14
0
        unsafe private void WriteMapInfo(ref RawOutputStream output)
        {
            AddMessageContentFlag(NetworkMessage.MapInfo);

            output.WriteRawBits(_server.m_MapInfo.mapId, 16);

            // Write schema if client haven't acked it
            output.WriteRawBits(mapSchemaAcked ? 0 : 1U, 1);
            if (!mapSchemaAcked)
            {
                NetworkSchema.WriteSchema(_server.m_MapInfo.schema, ref output);
            }

            // Write map data
            NetworkSchema.CopyFieldsFromBuffer(_server.m_MapInfo.schema, _server.m_MapInfo.data, ref output);
        }
Ejemplo n.º 15
0
        public void Delta_FloatCompressedNoBaseline <TInputStream, TOutputStream>() where TInputStream : NetworkCompression.IInputStream, new()
            where TOutputStream : NetworkCompression.IOutputStream, new()
        {
            var schema = new NetworkSchema(0);

            schema.AddField(new NetworkSchema.FieldInfo()
            {
                name = "field_0", fieldType = NetworkSchema.FieldType.Float, bits = 32, delta = true, precision = 3
            });
            var values = new List <object>()
            {
                0.123f
            };

            TestDelta <TInputStream, TOutputStream>(schema, values, null);
        }
Ejemplo n.º 16
0
        public void QueueCommand(int time, DataGenerator generator)
        {
            var generateSchema = (commandSchema == null);

            if (generateSchema)
            {
                commandSchema = new NetworkSchema(NetworkConfig.networkClientQueueCommandSchemaId);
            }

            var info = commandsOut.Acquire(++commandSequence);

            info.time = time;
            var writer = new NetworkWriter(info.data, commandSchema, generateSchema);

            generator(ref writer);
            writer.Flush();
        }
Ejemplo n.º 17
0
    public static void CopyFieldsToBuffer <TInputStream>(NetworkSchema schema, ref TInputStream input, byte[] outputBuffer) where TInputStream : NetworkCompression.IInputStream
    {
        var output = new ByteOutputStream(outputBuffer);

        for (var fieldIndex = 0; fieldIndex < schema.fields.Count; ++fieldIndex)
        {
            var field = schema.fields[fieldIndex];
            switch (field.fieldType)
            {
            case NetworkSchema.FieldType.Bool:
            case NetworkSchema.FieldType.UInt:
            case NetworkSchema.FieldType.Int:
            case NetworkSchema.FieldType.Float:
                output.WriteBits(input.ReadRawBits(field.bits), field.bits);
                break;

            case NetworkSchema.FieldType.Vector2:
                output.WriteUInt32(input.ReadRawBits(field.bits));
                output.WriteUInt32(input.ReadRawBits(field.bits));
                break;

            case NetworkSchema.FieldType.Vector3:
                output.WriteUInt32(input.ReadRawBits(field.bits));
                output.WriteUInt32(input.ReadRawBits(field.bits));
                output.WriteUInt32(input.ReadRawBits(field.bits));
                break;

            case NetworkSchema.FieldType.Quaternion:
                output.WriteUInt32(input.ReadRawBits(field.bits));
                output.WriteUInt32(input.ReadRawBits(field.bits));
                output.WriteUInt32(input.ReadRawBits(field.bits));
                output.WriteUInt32(input.ReadRawBits(field.bits));
                break;

            case NetworkSchema.FieldType.String:
            case NetworkSchema.FieldType.ByteArray:
                output.CopyByteArray(ref input, field.arraySize, field.startContext);
                break;

            default: GameDebug.Assert(false); break;
            }
        }
    }
Ejemplo n.º 18
0
    public static NetworkSchema ReadSchema <TInputStream>(ref TInputStream input) where TInputStream : NetworkCompression.IInputStream
    {
        int count  = (int)input.ReadPackedUInt(NetworkConfig.miscContext);
        int id     = (int)input.ReadPackedUInt(NetworkConfig.miscContext);
        var schema = new NetworkSchema(id);

        for (int i = 0; i < count; ++i)
        {
            var field = new FieldInfo();
            field.fieldType    = (FieldType)input.ReadRawBits(4);
            field.delta        = input.ReadRawBits(1) != 0;
            field.bits         = (int)input.ReadRawBits(6);
            field.precision    = (int)input.ReadRawBits(2);
            field.arraySize    = (int)input.ReadRawBits(16);
            field.startContext = schema.fields.Count * NetworkConfig.maxContextsPerField + schema.id * NetworkConfig.maxContextsPerSchema + NetworkConfig.firstSchemaContext;
            field.fieldMask    = (byte)input.ReadRawBits(8);
            schema.AddField(field);
        }
        return(schema);
    }
Ejemplo n.º 19
0
    public static void SkipFields <TInputStream>(NetworkSchema schema, ref TInputStream input) where TInputStream : NetworkCompression.IInputStream
    {
        for (var fieldIndex = 0; fieldIndex < schema.fieldsInternal.Count; ++fieldIndex)
        {
            var field = schema.fieldsInternal[fieldIndex];
            switch (field.fieldType)
            {
            case NetworkSchema.FieldType.Bool:
            case NetworkSchema.FieldType.UInt:
            case NetworkSchema.FieldType.Int:
            case NetworkSchema.FieldType.Float:
                input.ReadRawBits(field.bits);
                break;

            case NetworkSchema.FieldType.Vector2:
                input.ReadRawBits(field.bits);
                input.ReadRawBits(field.bits);
                break;

            case NetworkSchema.FieldType.Vector3:
                input.ReadRawBits(field.bits);
                input.ReadRawBits(field.bits);
                input.ReadRawBits(field.bits);
                break;

            case NetworkSchema.FieldType.Quaternion:
                input.ReadRawBits(field.bits);
                input.ReadRawBits(field.bits);
                input.ReadRawBits(field.bits);
                input.ReadRawBits(field.bits);
                break;

            case NetworkSchema.FieldType.String:
            case NetworkSchema.FieldType.ByteArray:
                input.SkipRawBytes((int)input.ReadPackedUInt(field.startContext));
                break;

            default: GameDebug.Assert(false); break;
            }
        }
    }
Ejemplo n.º 20
0
    public static NetworkSchema ReadSchema(ref RawInputStream input)
    {
        int count  = (int)input.ReadPackedUInt(NetworkConfig.miscContext);
        int id     = (int)input.ReadPackedUInt(NetworkConfig.miscContext);
        var schema = new NetworkSchema(id);

        for (int i = 0; i < count; ++i)
        {
            var field = new FieldInfo();
            field.fieldType    = (FieldType)input.ReadPackedNibble(NetworkConfig.miscContext);
            field.delta        = input.ReadRawBits(1) != 0;
            field.bits         = (int)input.ReadPackedUInt(NetworkConfig.miscContext);
            field.precision    = (int)input.ReadPackedUInt(NetworkConfig.miscContext);
            field.arraySize    = (int)input.ReadPackedUInt(NetworkConfig.miscContext);
            field.startContext = schema.fieldsInternal.Count * NetworkConfig.maxContextsPerField + schema.id * NetworkConfig.maxContextsPerSchema + NetworkConfig.firstSchemaContext;
            field.fieldMask    = (byte)input.ReadPackedUInt(NetworkConfig.miscContext);
            schema.AddField(field);
        }
        schema.Finalize();
        return(schema);
    }
Ejemplo n.º 21
0
    public static void WriteEvents <TOutputStream>(List <NetworkEvent> events, List <NetworkEventType> knownEventTypes, ref TOutputStream output) where TOutputStream : NetworkCompression.IOutputStream
    {
        output.WritePackedUInt((uint)events.Count, NetworkConfig.eventCountContext);
        foreach (var info in events)
        {
            // Write event schema if the client haven't acked this event type
            output.WritePackedUInt(info.type.typeId, NetworkConfig.eventCountContext);
            if (!knownEventTypes.Contains(info.type))
            {
                output.WriteRawBits(1, 1);
                NetworkSchema.WriteSchema(info.type.schema, ref output);
            }
            else
            {
                output.WriteRawBits(0, 1);
            }

            // Write event data
            NetworkSchema.CopyFieldsFromBuffer(info.type.schema, info.data, ref output);
        }
    }
Ejemplo n.º 22
0
        public void Delta_FloatCompressed <TInputStream, TOutputStream>() where TInputStream : NetworkCompression.IInputStream, new()
            where TOutputStream : NetworkCompression.IOutputStream, new()
        {
            var schema = new NetworkSchema(0);

            schema.AddField(new NetworkSchema.FieldInfo()
            {
                name = "field_0", fieldType = NetworkSchema.FieldType.Float, bits = 32, delta = true, precision = 3
            });
            schema.Finalize();

            var values = new List <object>()
            {
                0.637160838f
            };
            var baseline = new List <object>()
            {
                0.538469732f
            };

            TestDelta <TInputStream, TOutputStream>(schema, values, baseline);
        }
Ejemplo n.º 23
0
    unsafe public static void WriteEvents(List <NetworkEvent> events, List <NetworkEventType> knownEventTypes, ref RawOutputStream output)
    {
        output.WritePackedUInt((uint)events.Count, NetworkConfig.eventCountContext);
        foreach (var info in events)
        {
            // Write event schema if the client haven't acked this event type
            output.WritePackedUInt(info.type.typeId, NetworkConfig.eventCountContext);
            if (!knownEventTypes.Contains(info.type))
            {
                output.WriteRawBits(1, 1);
                NetworkSchema.WriteSchema(info.type.schema, ref output);
            }
            else
                output.WriteRawBits(0, 1);

            // Write event data
            fixed(uint *data = info.data)
            {
                NetworkSchema.CopyFieldsFromBuffer(info.type.schema, data, ref output);
            }
        }
    }
Ejemplo n.º 24
0
        void ReadMapInfo(ref RawInputStream input)
        {
            //input.SetStatsType(NetworkCompressionReader.Type.MapInfo);
            var mapSequence    = (ushort)input.ReadRawBits(16);
            var schemaIncluded = input.ReadRawBits(1) != 0;

            if (schemaIncluded)
            {
                mapInfo.schema = NetworkSchema.ReadSchema(ref input);   // might override previous definition
            }

            if (mapSequence > mapInfo.mapSequence)
            {
                mapInfo.mapSequence = mapSequence;
                mapInfo.ackSequence = inSequence;
                mapInfo.processed   = false;
                NetworkSchema.CopyFieldsToBuffer(mapInfo.schema, ref input, mapInfo.data);
            }
            else
            {
                NetworkSchema.SkipFields(mapInfo.schema, ref input);
            }
        }
Ejemplo n.º 25
0
        public void Delta_FloatCompressedNoDrift <TInputStream, TOutputStream>() where TInputStream : NetworkCompression.IInputStream, new()
            where TOutputStream : NetworkCompression.IOutputStream, new()
        {
            var schema = new NetworkSchema(0);

            schema.AddField(new NetworkSchema.FieldInfo()
            {
                name = "field_0", fieldType = NetworkSchema.FieldType.Float, bits = 32, delta = true, precision = 3
            });

            var values   = new List <object>(1);
            var baseline = new List <object>(1);

            values.Add(0.0f);
            baseline.Add(0.0f);

            for (int i = 0; i < 1024; ++i)
            {
                values[0] = (float)Math.Sin(i / 1024.0f * Math.PI);
                TestDelta <TInputStream, TOutputStream>(schema, values, baseline);
                baseline[0] = values[0];
            }
        }
Ejemplo n.º 26
0
    public static int ReadEvents <TInputStream>(Dictionary <ushort, NetworkEventType> eventTypesIn, int connectionId, ref TInputStream input, INetworkCallbacks networkConsumer) where TInputStream : NetworkCompression.IInputStream
    {
        var eventCount = input.ReadPackedUInt(NetworkConfig.eventCountContext);

        for (var eventCounter = 0; eventCounter < eventCount; ++eventCounter)
        {
            var typeId         = (ushort)input.ReadPackedUInt(NetworkConfig.eventTypeIdContext);
            var schemaIncluded = input.ReadRawBits(1) != 0;
            if (schemaIncluded)
            {
                var eventType = new NetworkEventType()
                {
                    typeId = typeId
                };
                eventType.schema = NetworkSchema.ReadSchema(ref input);

                if (!eventTypesIn.ContainsKey(typeId))
                {
                    eventTypesIn.Add(typeId, eventType);
                }
            }

            // TODO (petera) do we need to Create an info (as we are just releasing it right after?)
            var type = eventTypesIn[typeId];
            var info = Create(type);
            NetworkSchema.CopyFieldsToBuffer(type.schema, ref input, info.data);
            if (NetworkConfig.netDebug.IntValue > 0)
            {
                GameDebug.Log("Received event " + ((GameNetworkEvents.EventType)info.type.typeId + ":" + info.sequence));
            }

            networkConsumer.OnEvent(connectionId, info);

            info.Release();
        }
        return((int)eventCount);
    }
Ejemplo n.º 27
0
        void WriteCommands <TOutputStream>(ClientPackageInfo packageInfo, ref TOutputStream output) where TOutputStream : NetworkCompression.IOutputStream
        {
            AddMessage(NetworkMessage.Commands);
            counters.commandsOut++;

            var includeSchema = commandSequenceAck == 0;

            output.WriteRawBits(includeSchema ? 1U : 0, 1);
            if (includeSchema)
            {
                NetworkSchema.WriteSchema(commandSchema, ref output);
            }

            var sequence = commandSequence;

            output.WriteRawBits(Sequence.ToUInt16(commandSequence), 16);

            packageInfo.commandSequence = commandSequence;
            packageInfo.commandTime     = commandsOut[commandSequence].time;

            CommandInfo previous = defaultCommandInfo;
            CommandInfo command;

            while (commandsOut.TryGetValue(sequence, out command))
            {
                // 1 bit to tell there is a command
                output.WriteRawBits(1, 1);
                output.WritePackedIntDelta(command.time, previous.time, NetworkConfig.commandTimeContext);
                uint hash = 0;
                DeltaWriter.Write(ref output, commandSchema, command.data, previous.data, zeroFieldsChanged, 0, ref hash);

                previous = command;
                --sequence;
            }
            output.WriteRawBits(0, 1);
        }
Ejemplo n.º 28
0
        unsafe void ReadSnapshot <TInputStream>(int sequence, ref TInputStream input, ISnapshotConsumer consumer) where TInputStream : NetworkCompression.IInputStream
        {
            //input.SetStatsType(NetworkCompressionReader.Type.SnapshotSchema);
            counters.snapshotsIn++;

            // Snapshot may be delta compressed against one or more baselines
            // Baselines are indicated by sequence number of the package it was in
            var haveBaseline = input.ReadRawBits(1) == 1;
            var baseSequence = (int)input.ReadPackedIntDelta(sequence - 1, NetworkConfig.baseSequenceContext);

            bool enableNetworkPrediction = input.ReadRawBits(1) != 0;
            bool enableHashing           = input.ReadRawBits(1) != 0;

            int baseSequence1 = 0;
            int baseSequence2 = 0;

            if (enableNetworkPrediction)
            {
                baseSequence1 = (int)input.ReadPackedIntDelta(baseSequence - 1, NetworkConfig.baseSequence1Context);
                baseSequence2 = (int)input.ReadPackedIntDelta(baseSequence1 - 1, NetworkConfig.baseSequence2Context);
            }

            if (clientDebug.IntValue > 2)
            {
                if (enableNetworkPrediction)
                {
                    GameDebug.Log((haveBaseline ? "Snap [BL]" : "Snap [  ]") + "(" + sequence + ")  " + baseSequence + " - " + baseSequence1 + " - " + baseSequence2);
                }
                else
                {
                    GameDebug.Log((haveBaseline ? "Snap [BL]" : "Snap [  ]") + "(" + sequence + ")  " + baseSequence);
                }
            }

            if (!haveBaseline)
            {
                counters.fullSnapshotsIn++;
            }

            GameDebug.Assert(!haveBaseline ||
                             (sequence > baseSequence && sequence - baseSequence < NetworkConfig.snapshotDeltaCacheSize), "Attempting snapshot encoding with invalid baseline: {0}:{1}", sequence, baseSequence);

            var snapshotInfo = snapshots.Acquire(sequence);

            snapshotInfo.serverTime = (int)input.ReadPackedIntDelta(haveBaseline ? snapshots[baseSequence].serverTime : 0, NetworkConfig.serverTimeContext);

            var temp = (int)input.ReadRawBits(8);

            serverSimTime = temp * 0.1f;

            // Only update time if received in-order..
            // TODO consider dropping out of order snapshots
            // TODO detecting out-of-order on pack sequences
            if (snapshotInfo.serverTime > serverTime)
            {
                serverTime           = snapshotInfo.serverTime;
                snapshotReceivedTime = NetworkUtils.stopwatch.ElapsedMilliseconds;
            }
            else
            {
                GameDebug.Log(string.Format("NetworkClient. Dropping out of order snaphot. Server time:{0} snapshot time:{1}", serverTime, snapshotInfo.serverTime));
            }

            counters.AddSectionStats("snapShotHeader", input.GetBitPosition2(), new Color(0.5f, 0.5f, 0.5f));

            // Used by thinclient that wants to very cheaply just do minimal handling of
            // snapshots
            if (m_DropSnapshots)
            {
                return;
            }

            // Read schemas
            var schemaCount = input.ReadPackedUInt(NetworkConfig.schemaCountContext);

            for (int schemaIndex = 0; schemaIndex < schemaCount; ++schemaIndex)
            {
                var typeId = (ushort)input.ReadPackedUInt(NetworkConfig.schemaTypeIdContext);

                var entityType = new EntityTypeInfo()
                {
                    typeId = typeId
                };
                entityType.schema = NetworkSchema.ReadSchema(ref input);
                counters.AddSectionStats("snapShotSchemas", input.GetBitPosition2(), new Color(0.0f, (schemaIndex & 1) == 1 ? 0.5f : 1.0f, 1.0f));
                entityType.baseline = new uint[NetworkConfig.maxEntitySnapshotDataSize];
                NetworkSchema.CopyFieldsToBuffer(entityType.schema, ref input, entityType.baseline);

                if (!entityTypes.ContainsKey(typeId))
                {
                    entityTypes.Add(typeId, entityType);
                }

                counters.AddSectionStats("snapShotSchemas", input.GetBitPosition2(), new Color(1.0f, (schemaIndex & 1) == 1 ? 0.5f : 1.0f, 1.0f));
            }

            // Remove any despawning entities that belong to older base sequences
            for (int i = 0; i < entities.Count; i++)
            {
                var e = entities[i];
                if (e.type == null)
                {
                    continue;
                }
                if (e.despawnSequence > 0 && e.despawnSequence <= baseSequence)
                {
                    e.Reset();
                }
            }

            // Read new spawns
            m_TempSpawnList.Clear();
            var previousId = 1;
            var spawnCount = input.ReadPackedUInt(NetworkConfig.spawnCountContext);

            for (var spawnIndex = 0; spawnIndex < spawnCount; ++spawnIndex)
            {
                var id = (int)input.ReadPackedIntDelta(previousId, NetworkConfig.idContext);
                previousId = id;

                // Register the entity
                var typeId = (ushort)input.ReadPackedUInt(NetworkConfig.spawnTypeIdContext);    //TODO: use another encoding
                GameDebug.Assert(entityTypes.ContainsKey(typeId), "Spawn request with unknown type id {0}", typeId);

                byte fieldMask = (byte)input.ReadRawBits(8);

                // TODO (petera) need an max entity id for safety
                while (id >= entities.Count)
                {
                    entities.Add(new EntityInfo());
                }

                // Incoming spawn of different type than what we have for this id, so immediately nuke
                // the one we have to make room for the incoming
                if (entities[id].type != null && entities[id].type.typeId != typeId)
                {
                    // This should only ever happen in case of no baseline as normally the server will
                    // not reuse an id before all clients have acknowledged its despawn.
                    GameDebug.Assert(haveBaseline == false, "Spawning entity but we already have with different type?");
                    GameDebug.Log("REPLACING old entity: " + id + " because snapshot gave us new type for this id");
                    despawns.Add(id);
                    entities[id].Reset();
                }

                // We can receive spawn information in several snapshots before our ack
                // has reached the server. Only pass on spawn to game layer once
                if (entities[id].type == null)
                {
                    var e = entities[id];
                    e.type      = entityTypes[typeId];
                    e.fieldMask = fieldMask;
                    spawns.Add(id);
                }

                m_TempSpawnList.Add(id);
            }

            counters.AddSectionStats("snapShotSpawns", input.GetBitPosition2(), new Color(0, 0.58f, 0));

            // Read despawns
            var despawnCount = input.ReadPackedUInt(NetworkConfig.despawnCountContext);

            // If we have no baseline, we need to clear all entities that are not being spawned
            if (!haveBaseline)
            {
                GameDebug.Assert(despawnCount == 0, "There should not be any despawns in a non-baseline snapshot");
                for (int i = 0, c = entities.Count; i < c; ++i)
                {
                    var e = entities[i];
                    if (e.type == null)
                    {
                        continue;
                    }
                    if (m_TempSpawnList.Contains(i))
                    {
                        continue;
                    }
                    GameDebug.Log("NO BL SO PRUNING Stale entity: " + i);
                    despawns.Add(i);
                    e.Reset();
                }
            }

            for (var despawnIndex = 0; despawnIndex < despawnCount; ++despawnIndex)
            {
                var id = (int)input.ReadPackedIntDelta(previousId, NetworkConfig.idContext);
                previousId = id;

                // we may see despawns many times, only handle if we still have the entity
                GameDebug.Assert(id < entities.Count, "Getting despawn for id {0} but we only know about entities up to {1}", id, entities.Count);
                if (entities[id].type == null)
                {
                    continue;
                }

                var entity = entities[id];

                // Already in the process of being despawned. This happens with same-snapshot spawn/despawn cases
                if (entity.despawnSequence > 0)
                {
                    continue;
                }

                // If we are spawning and despawning in same snapshot, delay actual deletion of
                // entity as we need it around to be able to read the update part of the snapshot
                if (m_TempSpawnList.Contains(id))
                {
                    entity.despawnSequence = sequence; // keep until baseSequence >= despawnSequence
                }
                else
                {
                    entity.Reset(); // otherwise remove right away; no further updates coming, not even in this snap
                }
                // Add to despawns list so we can request despawn from game later
                GameDebug.Assert(!despawns.Contains(id), "Double despawn in same snaphot? {0}", id);
                despawns.Add(id);
            }

            counters.AddSectionStats("snapShotDespawns", input.GetBitPosition2(), new Color(0.49f, 0, 0));

            // Predict all active entities
            for (var id = 0; id < entities.Count; id++)
            {
                var info = entities[id];
                if (info.type == null)
                {
                    continue;
                }

                // NOTE : As long as the server haven't gotten the spawn acked, it will keep sending
                // delta relative to 0, so we need to check if the entity was in the spawn list to determine
                // if the delta is relative to the last update or not

                int baseline0Time = 0;

                uint[] baseline0 = info.type.baseline;
                GameDebug.Assert(baseline0 != null, "Unable to find schema baseline for type {0}", info.type.typeId);

                if (haveBaseline && !m_TempSpawnList.Contains(id))
                {
                    baseline0 = info.baselines.FindMax(baseSequence);
                    GameDebug.Assert(baseline0 != null, "Unable to find baseline for seq {0} for id {1}", baseSequence, id);
                    baseline0Time = snapshots[baseSequence].serverTime;
                }

                if (enableNetworkPrediction)
                {
                    uint num_baselines = 1; // 1 because either we have schema baseline or we have a real baseline
                    int  baseline1Time = 0;
                    int  baseline2Time = 0;

                    uint[] baseline1 = null;
                    uint[] baseline2 = null;
                    if (baseSequence1 != baseSequence)
                    {
                        baseline1 = info.baselines.FindMax(baseSequence1);
                        if (baseline1 != null)
                        {
                            num_baselines = 2;
                            baseline1Time = snapshots[baseSequence1].serverTime;
                        }
                        if (baseSequence2 != baseSequence1)
                        {
                            baseline2 = info.baselines.FindMax(baseSequence2);
                            if (baseline2 != null)
                            {
                                num_baselines = 3;
                                baseline2Time = snapshots[baseSequence2].serverTime;
                            }
                        }
                    }

                    // TODO (petera) are these clears needed?
                    for (int i = 0, c = info.fieldsChangedPrediction.Length; i < c; ++i)
                    {
                        info.fieldsChangedPrediction[i] = 0;
                    }
                    for (int i = 0; i < NetworkConfig.maxEntitySnapshotDataSize; i++)
                    {
                        info.prediction[i] = 0;

                        fixed(uint *prediction = info.prediction, baseline0p = baseline0, baseline1p = baseline1, baseline2p = baseline2)
                        {
                            NetworkPrediction.PredictSnapshot(prediction, info.fieldsChangedPrediction, info.type.schema, num_baselines, (uint)baseline0Time, baseline0p, (uint)baseline1Time, baseline1p, (uint)baseline2Time, baseline2p, (uint)snapshotInfo.serverTime, info.fieldMask);
                        }
                }
                else
                {
                    var f = info.fieldsChangedPrediction;
                    for (var i = 0; i < f.Length; ++i)
                    {
                        f[i] = 0;
                    }
                    for (int i = 0, c = info.type.schema.GetByteSize() / 4; i < c; ++i)
                    {
                        info.prediction[i] = baseline0[i];
                    }
                }
            }

            // Read updates
            var updateCount = input.ReadPackedUInt(NetworkConfig.updateCountContext);

            for (var updateIndex = 0; updateIndex < updateCount; ++updateIndex)
            {
                var id = (int)input.ReadPackedIntDelta(previousId, NetworkConfig.idContext);
                previousId = id;

                var info = entities[id];

                uint hash = 0;
                // Copy prediction to temp buffer as we now overwrite info.prediction with fully unpacked
                // state by applying incoming delta to prediction.
                for (int i = 0, c = info.type.schema.GetByteSize() / 4; i < c; ++i)
                {
                    tempSnapshotBuffer[i] = info.prediction[i];
                }

                DeltaReader.Read(ref input, info.type.schema, info.prediction, tempSnapshotBuffer, info.fieldsChangedPrediction, info.fieldMask, ref hash);
                if (enableHashing)
                {
                    uint hashCheck = input.ReadRawBits(32);

                    if (hash != hashCheck)
                    {
                        GameDebug.Log("Hash check fail for entity " + id);
                        if (enableNetworkPrediction)
                        {
                            GameDebug.Assert(false, "Snapshot (" + snapshotInfo.serverTime + ") " + (haveBaseline ? "Snap [BL]" : "Snap [  ]") + "  " + baseSequence + " - " + baseSequence1 + " - " + baseSequence2 + ". Sche: " + schemaCount + " Spwns: " + spawnCount + " Desp: " + despawnCount + " Upd: " + updateCount);
                        }
                        else
                        {
                            GameDebug.Assert(false, "Snapshot (" + snapshotInfo.serverTime + ") " + (haveBaseline ? "Snap [BL]" : "Snap [  ]") + "  " + baseSequence + ". Sche: " + schemaCount + " Spwns: " + spawnCount + " Desp: " + despawnCount + " Upd: " + updateCount);
                        }
                    }
                }
            }

            if (enableNetworkPrediction)
            {
                counters.AddSectionStats("snapShotUpdatesPredict", input.GetBitPosition2(), haveBaseline ? new Color(0.09f, 0.38f, 0.93f) : Color.cyan);
            }
            else
            {
                counters.AddSectionStats("snapShotUpdatesNoPredict", input.GetBitPosition2(), haveBaseline ? new Color(0.09f, 0.38f, 0.93f) : Color.cyan);
            }

            uint snapshotHash = 0; // sum of hash for all (updated or not) entity snapshots
            uint numEnts      = 0;

            for (int id = 0; id < entities.Count; id++)
            {
                var info = entities[id];
                if (info.type == null)
                {
                    continue;
                }

                // Skip despawned that have not also been spawned in this snapshot
                if (info.despawnSequence > 0 && !spawns.Contains(id))
                {
                    continue;
                }

                // If just spawned or if new snapshot is different from the last we deserialized,
                // we need to deserialize. Otherwise just ignore; no reason to deserialize the same
                // values again
                int schemaSize = info.type.schema.GetByteSize();
                if (info.baselines.GetSize() == 0 || NetworkUtils.MemCmp(info.prediction, 0, info.lastUpdate, 0, schemaSize) != 0)
                {
                    var data = info.baselines.Insert(sequence);
                    for (int i = 0; i < schemaSize / 4; ++i)
                        data[i] = info.prediction[i]; }
                    if (sequence > info.lastUpdateSequence)
                    {
                        if (!updates.Contains(id))
                        {
                            updates.Add(id);
                        }

                        for (int i = 0; i < schemaSize / 4; ++i)
                        {
                            info.lastUpdate[i] = info.prediction[i];
                        }
                        info.lastUpdateSequence = sequence;
                    }
                }

                if (enableHashing && info.despawnSequence == 0)
                {
                    snapshotHash += NetworkUtils.SimpleHash(info.prediction, schemaSize);
                    numEnts++;
                }
            }
Ejemplo n.º 29
0
    unsafe public static int Read <TInputStream>(ref TInputStream input, NetworkSchema schema, uint[] outputData, uint[] baselineData, byte[] fieldsChangedPrediction, byte fieldMask, ref uint hash) where TInputStream : NetworkCompression.IInputStream
    {
        GameDebug.Assert(baselineData != null);

        var index = 0;

        int numFields = schema.numFields;

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

        for (int i = 0; i * 8 < numFields; i++)
        {
            uint value = input.ReadPackedNibble(skipContext + 2 * i + 0);
            value |= input.ReadPackedNibble(skipContext + 2 * i + 1) << 4;
            fieldsNotPredicted[i] = (byte)(value ^ fieldsChangedPrediction[i]);
        }

        for (int i = 0; i < numFields; ++i)
        {
            var field = schema.fields[i];

            GameDebug.Assert(field.byteOffset == index * 4);
            int fieldStartContext = field.startContext;


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

            bool skip   = (fieldsNotPredicted[fieldByteOffset] & (1 << fieldBitOffset)) == 0;
            bool masked = ((field.fieldMask & fieldMask) != 0);

            skip = skip || masked;

            switch (field.fieldType)
            {
            case NetworkSchema.FieldType.Bool:
            {
                uint value = baselineData[index];
                if (!skip)
                {
                    value = input.ReadRawBits(1);
                }

                if (!masked)
                {
                    hash = NetworkUtils.SimpleHashStreaming(hash, value);
                }

                outputData[index] = value;
                index++;
                break;
            }

            case NetworkSchema.FieldType.UInt:
            case NetworkSchema.FieldType.Int:
            case NetworkSchema.FieldType.Float:
            {
                uint baseline = (uint)baselineData[index];

                uint value = baseline;
                if (!skip)
                {
                    if (field.delta)
                    {
                        value = input.ReadPackedUIntDelta(baseline, fieldStartContext);
                    }
                    else
                    {
                        value = input.ReadRawBits(field.bits);
                    }
                }

                if (!masked)
                {
                    hash = NetworkUtils.SimpleHashStreaming(hash, value);
                }

                outputData[index] = value;
                index++;
                break;
            }

            case NetworkSchema.FieldType.Vector2:
            {
                uint bx = baselineData[index];
                uint by = baselineData[index + 1];

                uint vx = bx;
                uint vy = by;
                if (!skip)
                {
                    if (field.delta)
                    {
                        vx = input.ReadPackedUIntDelta(bx, fieldStartContext + 0);
                        vy = input.ReadPackedUIntDelta(by, fieldStartContext + 1);
                    }
                    else
                    {
                        vx = input.ReadRawBits(field.bits);
                        vy = input.ReadRawBits(field.bits);
                    }
                }

                if (!masked)
                {
                    hash = NetworkUtils.SimpleHashStreaming(hash, vx);
                    hash = NetworkUtils.SimpleHashStreaming(hash, vy);
                }

                outputData[index]     = vx;
                outputData[index + 1] = vy;
                index += 2;

                break;
            }

            case NetworkSchema.FieldType.Vector3:
            {
                uint bx = baselineData[index];
                uint by = baselineData[index + 1];
                uint bz = baselineData[index + 2];

                uint vx = bx;
                uint vy = by;
                uint vz = bz;

                if (!skip)
                {
                    if (field.delta)
                    {
                        vx = input.ReadPackedUIntDelta(bx, fieldStartContext + 0);
                        vy = input.ReadPackedUIntDelta(by, fieldStartContext + 1);
                        vz = input.ReadPackedUIntDelta(bz, fieldStartContext + 2);
                    }
                    else
                    {
                        vx = input.ReadRawBits(field.bits);
                        vy = input.ReadRawBits(field.bits);
                        vz = input.ReadRawBits(field.bits);
                    }
                }

                if (!masked)
                {
                    hash = NetworkUtils.SimpleHashStreaming(hash, vx);
                    hash = NetworkUtils.SimpleHashStreaming(hash, vy);
                    hash = NetworkUtils.SimpleHashStreaming(hash, vz);
                }

                outputData[index]     = vx;
                outputData[index + 1] = vy;
                outputData[index + 2] = vz;
                index += 3;
                break;
            }

            case NetworkSchema.FieldType.Quaternion:
            {
                uint bx = baselineData[index];
                uint by = baselineData[index + 1];
                uint bz = baselineData[index + 2];
                uint bw = baselineData[index + 3];

                uint vx = bx;
                uint vy = by;
                uint vz = bz;
                uint vw = bw;

                if (!skip)
                {
                    if (field.delta)
                    {
                        vx = input.ReadPackedUIntDelta(bx, fieldStartContext + 0);
                        vy = input.ReadPackedUIntDelta(by, fieldStartContext + 1);
                        vz = input.ReadPackedUIntDelta(bz, fieldStartContext + 2);
                        vw = input.ReadPackedUIntDelta(bw, fieldStartContext + 3);
                        //RUTODO: normalize
                    }
                    else
                    {
                        vx = input.ReadRawBits(field.bits);
                        vy = input.ReadRawBits(field.bits);
                        vz = input.ReadRawBits(field.bits);
                        vw = input.ReadRawBits(field.bits);
                    }
                }

                if (!masked)
                {
                    hash = NetworkUtils.SimpleHashStreaming(hash, vx);
                    hash = NetworkUtils.SimpleHashStreaming(hash, vy);
                    hash = NetworkUtils.SimpleHashStreaming(hash, vz);
                    hash = NetworkUtils.SimpleHashStreaming(hash, vw);
                }

                outputData[index]     = vx;
                outputData[index + 1] = vy;
                outputData[index + 2] = vz;
                outputData[index + 3] = vw;
                index += 4;
                break;
            }

            case NetworkSchema.FieldType.String:
            case NetworkSchema.FieldType.ByteArray:
            {
                // TODO : Do a better job with deltaing strings and buffers
                if (!skip)
                {
                    uint count = input.ReadPackedUInt(fieldStartContext);
                    outputData[index] = count;
                    index++;
                    fixed(uint *buf = outputData)
                    {
                        byte *dst = (byte *)(buf + index);
                        int   idx = 0;

                        for (; idx < count; ++idx)
                        {
                            *dst++ = (byte)input.ReadRawBits(8);
                        }
                        for (; idx < field.arraySize / 4; ++idx)
                        {
                            *dst++ = 0;
                        }
                    }

                    index += field.arraySize / 4;
                }
                else
                {
                    for (int idx = 0, c = field.arraySize / 4; idx < c; ++idx)
                    {
                        outputData[index + idx] = baselineData[index + idx];
                    }
                    index += field.arraySize / 4 + 1;
                }

                if (!masked)
                {
                    hash += 0;         // TODO (hash strings and bytearrays as well)
                }
            }
            break;
            }
        }
        return(index * 4);
    }
Ejemplo n.º 30
0
    unsafe public static void CopyFieldsToBuffer <TInputStream>(NetworkSchema schema, ref TInputStream input, uint[] outputBuffer) where TInputStream : NetworkCompression.IInputStream
    {
        var index = 0;

        for (var fieldIndex = 0; fieldIndex < schema.fieldsInternal.Count; ++fieldIndex)
        {
            var field = schema.fieldsInternal[fieldIndex];
            switch (field.fieldType)
            {
            case NetworkSchema.FieldType.Bool:
            case NetworkSchema.FieldType.UInt:
            case NetworkSchema.FieldType.Int:
            case NetworkSchema.FieldType.Float:
                outputBuffer[index++] = input.ReadPackedUInt(NetworkConfig.miscContext);
                break;

            case NetworkSchema.FieldType.Vector2:
                outputBuffer[index++] = (input.ReadPackedUInt(NetworkConfig.miscContext));
                outputBuffer[index++] = (input.ReadPackedUInt(NetworkConfig.miscContext));
                break;

            case NetworkSchema.FieldType.Vector3:
                outputBuffer[index++] = (input.ReadPackedUInt(NetworkConfig.miscContext));
                outputBuffer[index++] = (input.ReadPackedUInt(NetworkConfig.miscContext));
                outputBuffer[index++] = (input.ReadPackedUInt(NetworkConfig.miscContext));
                break;

            case NetworkSchema.FieldType.Quaternion:
                outputBuffer[index++] = (input.ReadPackedUInt(NetworkConfig.miscContext));
                outputBuffer[index++] = (input.ReadPackedUInt(NetworkConfig.miscContext));
                outputBuffer[index++] = (input.ReadPackedUInt(NetworkConfig.miscContext));
                outputBuffer[index++] = (input.ReadPackedUInt(NetworkConfig.miscContext));
                break;

            case NetworkSchema.FieldType.String:
            case NetworkSchema.FieldType.ByteArray:
                var dataSize = input.ReadPackedUInt(NetworkConfig.miscContext);
                outputBuffer[index++] = dataSize;

                fixed(uint *buf = outputBuffer)
                {
                    byte *dst = (byte *)(buf + index);
                    int   i   = 0;

                    for (; i < dataSize; i++)
                    {
                        *dst++ = (byte)input.ReadRawBits(8);
                    }
                    for (; i < field.arraySize; i++)
                    {
                        *dst++ = 0;
                    }
                }

                index += field.arraySize / 4;
                break;

            default: GameDebug.Assert(false); break;
            }
        }
    }
Ejemplo n.º 31
0
    unsafe static public void Write <TOutputStream>(ref TOutputStream output, NetworkSchema schema, uint *inputData, uint *baselineData, byte[] fieldsChangedPrediction, byte fieldMask, ref uint entity_hash) where TOutputStream : NetworkCompression.IOutputStream
    {
        GameDebug.Assert(baselineData != null);

        int numFields = schema.numFields;

        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;
        }

        int index = 0;

        // calculate bitmask of fields that need to be encoded
        for (int fieldIndex = 0; fieldIndex < numFields; ++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    = inputData[index];
                uint baseline = baselineData[index];
                index++;

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

                break;
            }

            case NetworkSchema.FieldType.Int:
            {
                uint value    = inputData[index];
                uint baseline = baselineData[index];
                index++;

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

            case NetworkSchema.FieldType.UInt:
            {
                uint value    = inputData[index];
                uint baseline = baselineData[index];
                index++;

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

            case NetworkSchema.FieldType.Float:
            {
                uint value    = inputData[index];
                uint baseline = baselineData[index];
                index++;

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

            case NetworkSchema.FieldType.Vector2:
            {
                uint vx = inputData[index];
                uint bx = baselineData[index];
                index++;

                uint vy = inputData[index];
                uint by = baselineData[index];
                index++;

                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 = inputData[index];
                uint bx = baselineData[index];
                index++;

                uint vy = inputData[index];
                uint by = baselineData[index];
                index++;

                uint vz = inputData[index];
                uint bz = baselineData[index];
                index++;

                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 = inputData[index];
                uint bx = baselineData[index];
                index++;

                uint vy = inputData[index];
                uint by = baselineData[index];
                index++;

                uint vz = inputData[index];
                uint bz = baselineData[index];
                index++;

                uint vw = inputData[index];
                uint bw = baselineData[index];
                index++;



                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:
            {
                if (!masked)
                {
                    entity_hash += 0;         // TODO client side has no easy way to hash strings. enable this when possible: NetworkUtils.SimpleHash(valueBuffer, valueLength);
                    bool same = true;
                    for (int i = 0; i < field.arraySize; i++)
                    {
                        if (inputData[index + i] != baselineData[index + i])
                        {
                            same = false;
                            break;
                        }
                    }
                    if (!same)
                    {
                        fieldsNotPredicted[fieldByteOffset] |= (byte)(1 << fieldBitOffset);
                    }
                }
                index += field.arraySize / 4 + 1;
            }
            break;
            }
        }

        index = 0;

        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 = inputData[index];
                index++;

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

            case NetworkSchema.FieldType.Int:
            {
                uint value    = inputData[index];
                uint baseline = baselineData[index];
                index++;

                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    = inputData[index];
                uint baseline = baselineData[index];
                index++;

                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    = inputData[index];
                uint baseline = baselineData[index];
                index++;

                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 = inputData[index];
                uint bx = baselineData[index];
                index++;

                uint vy = inputData[index];
                uint by = baselineData[index];
                index++;

                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 = inputData[index];
                uint bx = baselineData[index];
                index++;

                uint vy = inputData[index];
                uint by = baselineData[index];
                index++;

                uint vz = inputData[index];
                uint bz = baselineData[index];
                index++;

                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 = inputData[index];
                uint bx = baselineData[index];
                index++;

                uint vy = inputData[index];
                uint by = baselineData[index];
                index++;

                uint vz = inputData[index];
                uint bz = baselineData[index];
                index++;

                uint vw = inputData[index];
                uint bw = baselineData[index];
                index++;

                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:
            {
                uint valueLength = inputData[index];
                index++;

                if (notPredicted)
                {
                    output.WritePackedUInt(valueLength, fieldStartContext);
                    byte *bytes = (byte *)(inputData + index);
                    output.WriteRawBytes(bytes, (int)valueLength);

                    if (field.fieldType == NetworkSchema.FieldType.String)
                    {
                        NetworkSchema.AddStatsToFieldString(field, bytes, (int)valueLength, output.GetBitPosition2() - startBitPosition);
                    }
                    else
                    {
                        NetworkSchema.AddStatsToFieldByteArray(field, bytes, (int)valueLength, output.GetBitPosition2() - startBitPosition);
                    }
                }
                index += field.arraySize / 4;
            }
            break;
            }
        }
    }