Ejemplo n.º 1
0
        private void OnReceiveGameState(NetworkedGameState receivedGameState)
        {
            if (!ShouldApplyStateSnapshots)
            {
                return;
            }

            if (OsFps.Instance.IsRemoteClient)
            {
                Profiler.BeginSample("Client Get Current Networked Game State");
                var oldComponentInfoLists = NetLib.GetComponentInfosToSynchronize(
                    receivedGameState.NetworkedComponentTypeInfos
                    );
                Profiler.EndSample();

                Profiler.BeginSample("Client Apply Networked Game State");
                for (var i = 0; i < receivedGameState.NetworkedComponentInfoLists.Count; i++)
                {
                    var componentInfos             = receivedGameState.NetworkedComponentInfoLists[i];
                    var networkedComponentTypeInfo = receivedGameState.NetworkedComponentTypeInfos[i];
                    var componentType     = networkedComponentTypeInfo.StateType;
                    var oldComponentInfos = oldComponentInfoLists[i];

                    NetLib.ApplyState(
                        networkedComponentTypeInfo, oldComponentInfos, componentInfos, createGameObjectFromState
                        );
                }
                Profiler.EndSample();
            }
        }
Ejemplo n.º 2
0
        public static void SerializeNetworkedGameState(
            BinaryWriter writer, NetworkedGameState networkedGameState, NetworkedGameState oldNetworkedGameState
            )
        {
            for (var i = 0; i < networkedGameState.NetworkedComponentInfoLists.Count; i++)
            {
                var networkedComponentTypeInfo = networkedGameState.NetworkedComponentTypeInfos[i];
                var componentInfos             = networkedGameState.NetworkedComponentInfoLists[i];
                var oldComponentInfos          = oldNetworkedGameState.NetworkedComponentInfoLists[i];

                Serialize(writer, componentInfos, (binaryWriter, componentInfo, index) =>
                {
                    var componentStateId = NetLib.GetIdFromState(networkedComponentTypeInfo, componentInfo.ComponentState);
                    binaryWriter.Write(componentStateId);

                    var oldComponentInfoIndex = oldComponentInfos
                                                .FindIndex(oci =>
                                                           NetLib.GetIdFromState(networkedComponentTypeInfo, oci.ComponentState) == componentStateId
                                                           );
                    var oldComponentState = (oldComponentInfoIndex >= 0)
                        ? oldComponentInfos[oldComponentInfoIndex].ComponentState
                        : null;

                    var changeMask = GetChangeMask(networkedComponentTypeInfo, componentInfo.ComponentState, oldComponentState);
                    binaryWriter.Write(changeMask);

                    SerializeGivenChangeMask(
                        binaryWriter, networkedComponentTypeInfo, componentInfo.ComponentState, changeMask
                        );
                });
            }
        }
Ejemplo n.º 3
0
        private void OnReceiveDataFromServer(int channelId, byte[] bytesReceived, int numBytesReceived)
        {
            Profiler.BeginSample("OnReceiveDataFromServer");
            using (var memoryStream = new MemoryStream(bytesReceived, 0, numBytesReceived))
            {
                using (var reader = new BinaryReader(memoryStream))
                {
                    var     messageTypeAsByte = reader.ReadByte();
                    RpcInfo rpcInfo;

                    if (messageTypeAsByte == NetLib.StateSynchronizationMessageId)
                    {
                        OnReceiveDeltaGameStateFromServer(reader, bytesReceived, numBytesReceived);
                    }
                    else if (NetLib.rpcInfoById.TryGetValue(messageTypeAsByte, out rpcInfo))
                    {
                        Profiler.BeginSample("Deserialize & Execute RPC");
                        var rpcArguments = NetworkSerializationUtils.DeserializeRpcCallArguments(rpcInfo, reader);
                        NetLib.ExecuteRpc(rpcInfo.Id, null, ObjectContainingRpcs, rpcArguments);
                        Profiler.EndSample();
                    }
                    else
                    {
                        throw new NotImplementedException("Unknown message type: " + messageTypeAsByte);
                    }
                }
            }
            Profiler.EndSample();
        }
Ejemplo n.º 4
0
        public static NetworkedGameState DeserializeNetworkedGameState(
            BinaryReader reader, uint sequenceNumber, NetworkedGameState networkedGameStateRelativeTo
            )
        {
            var networkedComponentTypeInfos = networkedGameStateRelativeTo.NetworkedComponentTypeInfos;
            var networkedComponentInfoLists = networkedComponentTypeInfos
                                              .Select((networkedComponentTypeInfo, networkedComponentTypeInfosIndex) =>
            {
                var oldComponentInfos = networkedGameStateRelativeTo
                                        .NetworkedComponentInfoLists[networkedComponentTypeInfosIndex];
                var componentInfos = new List <NetworkedComponentInfo>();

                Deserialize(reader, componentInfos, (binaryReader, componentInfoIndex) =>
                {
                    var componentStateId = reader.ReadUInt32();

                    var oldComponentInfoIndex = oldComponentInfos
                                                .FindIndex(oci =>
                                                           NetLib.GetIdFromState(networkedComponentTypeInfo, oci.ComponentState) == componentStateId
                                                           );
                    NetworkedComponentInfo oldComponentInfo;

                    if (oldComponentInfoIndex < 0)
                    {
                        var stateType    = networkedComponentTypeInfo.StateType;
                        oldComponentInfo = new NetworkedComponentInfo
                        {
                            ComponentState = Activator.CreateInstance(stateType)
                        };
                    }
                    else
                    {
                        oldComponentInfo = oldComponentInfos[oldComponentInfoIndex];
                        oldComponentInfo = new NetworkedComponentInfo
                        {
                            ComponentState = ObjectExtensions.DeepCopy(oldComponentInfo.ComponentState)
                        };
                    }

                    DeserializeDelta(
                        binaryReader, networkedComponentTypeInfo, ref oldComponentInfo
                        );
                    return(oldComponentInfo);
                });

                return(componentInfos);
            })
                                              .ToList();

            return(new NetworkedGameState
            {
                SequenceNumber = sequenceNumber,
                NetworkedComponentTypeInfos = networkedComponentTypeInfos,
                NetworkedComponentInfoLists = networkedComponentInfoLists
            });
        }
Ejemplo n.º 5
0
        private NetworkedGameState GetNetworkedGameStateRelativeTo(uint sequenceNumberRelativeTo)
        {
            var indexOfGameStateRelativeTo = cachedReceivedGameStates
                                             .FindIndex(ngs => ngs.SequenceNumber == sequenceNumberRelativeTo);

            Assert.IsTrue((indexOfGameStateRelativeTo >= 0) || (sequenceNumberRelativeTo == 0));

            return((indexOfGameStateRelativeTo >= 0)
                ? cachedReceivedGameStates[indexOfGameStateRelativeTo]
                : NetLib.GetEmptyNetworkedGameStateForDiffing());
        }
Ejemplo n.º 6
0
        public NetworkedGameState GetNetworkedGameStateToDiffAgainst(uint playerId)
        {
            var playersLatestAcknowledgedGameStateSequenceNumber =
                latestAcknowledgedGameStateSequenceNumberByPlayerId.GetValueOrDefault(playerId);
            var indexOfPlayersLatestAcknowledgedGameState = cachedSentGameStates
                                                            .FindIndex(ngs => ngs.SequenceNumber == playersLatestAcknowledgedGameStateSequenceNumber);
            var playersLatestAcknowledgedGameState = (indexOfPlayersLatestAcknowledgedGameState >= 0)
                ? cachedSentGameStates[indexOfPlayersLatestAcknowledgedGameState]
                : NetLib.GetEmptyNetworkedGameStateForDiffing();

            return(playersLatestAcknowledgedGameState);
        }
Ejemplo n.º 7
0
        private void SendGameState()
        {
            // Get the current game state.
            var currentGameState = NetLib.GetCurrentNetworkedGameState(generateSequenceNumber: true);

            // Send the game state deltas.
            foreach (var connectionId in connectionIds)
            {
                var oldGameState = networkedGameStateCache.GetNetworkedGameStateToDiffAgainst((uint)connectionId);
                SendGameStateDiff(connectionId, currentGameState, oldGameState);
            }

            // Cache the game state for future deltas.
            networkedGameStateCache.AddGameState(currentGameState);
        }
Ejemplo n.º 8
0
        public void Start(
            ushort?portNumber, int maxPlayerCount, object objectContainingRpcs, float sendGameStateInterval
            )
        {
            ObjectContainingRpcs          = objectContainingRpcs;
            ShouldSendStateSnapshots      = true;
            sendGameStatePeriodicFunction = new ThrottledAction(SendGameState, sendGameStateInterval);
            this.maxPlayerCount           = maxPlayerCount;

            var connectionConfig = NetLib.CreateConnectionConfig(
                out reliableSequencedChannelId,
                out reliableChannelId,
                out unreliableStateUpdateChannelId,
                out unreliableFragmentedChannelId,
                out unreliableChannelId
                );
            var hostTopology = new HostTopology(connectionConfig, maxPlayerCount);

            Start(portNumber, hostTopology);
        }
Ejemplo n.º 9
0
        public void Start(object objectContainingRpcs, Func <object, UnityEngine.GameObject> createGameObjectFromState)
        {
            Assert.IsTrue(!IsStarted);

            ObjectContainingRpcs           = objectContainingRpcs;
            this.createGameObjectFromState = createGameObjectFromState;
            ShouldApplyStateSnapshots      = true;

            var maxConnectionCount = 1; // The client only connects to the server.
            var connectionConfig   = NetLib.CreateConnectionConfig(
                out reliableSequencedChannelId,
                out reliableChannelId,
                out unreliableStateUpdateChannelId,
                out unreliableFragmentedChannelId,
                out unreliableChannelId
                );
            var hostTopology = new HostTopology(
                connectionConfig, maxConnectionCount
                );

            Start(null, hostTopology);
        }
Ejemplo n.º 10
0
        private void OnReceiveDataFromClient(int connectionId, int channelId, byte[] bytesReceived, int numBytesReceived)
        {
            using (var memoryStream = new MemoryStream(bytesReceived, 0, numBytesReceived))
            {
                using (var reader = new BinaryReader(memoryStream))
                {
                    var messageTypeAsByte = reader.ReadByte();

                    RpcInfo rpcInfo;

                    if (messageTypeAsByte == NetLib.StateSynchronizationMessageId)
                    {
                        throw new System.NotImplementedException("Servers don't support receiving state synchronization messages.");
                    }
                    else if (NetLib.rpcInfoById.TryGetValue(messageTypeAsByte, out rpcInfo))
                    {
                        var rpcArguments = NetworkSerializationUtils.DeserializeRpcCallArguments(rpcInfo, reader);

                        CurrentRpcSenderConnectionId = connectionId;

                        if (rpcInfo.Name != "ServerOnReceiveClientGameStateAck")
                        {
                            NetLib.ExecuteRpc(rpcInfo.Id, ObjectContainingRpcs, null, rpcArguments);
                        }
                        else
                        {
                            NetLib.ExecuteRpc(rpcInfo.Id, this, null, rpcArguments);
                        }
                    }
                    else
                    {
                        throw new System.NotImplementedException("Unknown message type: " + messageTypeAsByte);
                    }
                }
            }
        }
Ejemplo n.º 11
0
        public static object Deserialize(
            BinaryReader reader, Type type,
            bool isNullableIfReferenceType, bool areElementsNullableIfReferenceType
            )
        {
            var nullableUnderlyingType = Nullable.GetUnderlyingType(type);

            if ((nullableUnderlyingType == null) && isNullableIfReferenceType && type.IsClass)
            {
                nullableUnderlyingType = type;
            }

            if (nullableUnderlyingType != null)
            {
                var objHasValue = reader.ReadBoolean();
                return(objHasValue
                    ? Deserialize(
                           reader, nullableUnderlyingType, isNullableIfReferenceType: false,
                           areElementsNullableIfReferenceType: areElementsNullableIfReferenceType
                           ) : null);
            }
            else if (type == typeof(bool))
            {
                return(reader.ReadBoolean());
            }
            else if (type == typeof(sbyte))
            {
                return(reader.ReadSByte());
            }
            else if (type == typeof(byte))
            {
                return(reader.ReadByte());
            }
            else if (type == typeof(ushort))
            {
                return(reader.ReadUInt16());
            }
            else if (type == typeof(short))
            {
                return(reader.ReadInt16());
            }
            else if (type == typeof(uint))
            {
                return(reader.ReadUInt32());
            }
            else if (type == typeof(int))
            {
                return(reader.ReadInt32());
            }
            else if (type == typeof(ulong))
            {
                return(reader.ReadUInt64());
            }
            else if (type == typeof(long))
            {
                return(reader.ReadInt64());
            }
            else if (type == typeof(float))
            {
                return(reader.ReadSingle());
            }
            else if (type == typeof(double))
            {
                return(reader.ReadDouble());
            }
            else if (type == typeof(decimal))
            {
                return(reader.ReadDecimal());
            }
            else if (type == typeof(char))
            {
                return(reader.ReadChar());
            }
            else if (type == typeof(string))
            {
                return(reader.ReadString());
            }
            else if (type == typeof(float2))
            {
                var result = new float2();
                Deserialize(reader, ref result);

                return(result);
            }
            else if (type == typeof(float3))
            {
                var result = new float3();
                Deserialize(reader, ref result);

                return(result);
            }
            else if (type == typeof(float4))
            {
                var result = new float4();
                Deserialize(reader, ref result);

                return(result);
            }
            else if (type == typeof(Vector2))
            {
                var result = new Vector2();
                Deserialize(reader, ref result);

                return(result);
            }
            else if (type == typeof(Vector3))
            {
                var result = new Vector3();
                Deserialize(reader, ref result);

                return(result);
            }
            else if (type == typeof(Vector4))
            {
                var result = new Vector4();
                Deserialize(reader, ref result);

                return(result);
            }
            else if (typeof(INetworkSerializable).IsAssignableFrom(type))
            {
                var result = Activator.CreateInstance(type);
                ((INetworkSerializable)result).Deserialize(reader);

                return(result);
            }
            else if (typeof(IEnumerable).IsAssignableFrom(type))
            {
                if (typeof(Array).IsAssignableFrom(type))
                {
                    var elementType  = type.GetElementType();
                    var elementCount = reader.ReadUInt32();
                    var array        = Array.CreateInstance(elementType, elementCount);

                    for (var i = 0; i < elementCount; i++)
                    {
                        var element = Deserialize(
                            reader, elementType, isNullableIfReferenceType: areElementsNullableIfReferenceType,
                            areElementsNullableIfReferenceType: false
                            );
                        array.SetValue(element, i);
                    }

                    return(array);
                }
                else if (typeof(IList).IsAssignableFrom(type))
                {
                    var list         = (IList)Activator.CreateInstance(type);
                    var elementType  = type.GenericTypeArguments[0];
                    var elementCount = reader.ReadUInt32();

                    for (var i = 0; i < elementCount; i++)
                    {
                        var element = Deserialize(
                            reader, elementType, isNullableIfReferenceType: areElementsNullableIfReferenceType,
                            areElementsNullableIfReferenceType: false
                            );
                        list.Add(element);
                    }

                    return(list);
                }
                else
                {
                    throw new NotImplementedException();
                }
            }
            else
            {
                if (type.IsEnum)
                {
                    var smallestTypeToHoldEnumValues = GetSmallestUIntTypeToHoldEnumValues(type);
                    var enumValueAsInt = Deserialize(
                        reader, smallestTypeToHoldEnumValues, isNullableIfReferenceType: false,
                        areElementsNullableIfReferenceType: false
                        );

                    return(Enum.ToObject(type, enumValueAsInt));
                }
                else if (type.IsClass || type.IsValueType)
                {
                    var result = Activator.CreateInstance(type);

                    var objFields = NetLib.GetFieldInfosToSerialize(type);
                    foreach (var objField in objFields)
                    {
                        var fieldValue = Deserialize(
                            reader, objField.FieldType, isNullableIfReferenceType: false,
                            areElementsNullableIfReferenceType: false
                            );
                        objField.SetValue(result, fieldValue);
                    }

                    var objProperties = NetLib.GetPropertyInfosToSerialize(type);
                    foreach (var objProperty in objProperties)
                    {
                        if (!objProperty.CanRead || !objProperty.CanWrite)
                        {
                            continue;
                        }

                        var propertyValue = Deserialize(
                            reader, objProperty.PropertyType, isNullableIfReferenceType: false,
                            areElementsNullableIfReferenceType: false
                            );
                        objProperty.SetValue(result, propertyValue);
                    }

                    return(result);
                }
                else
                {
                    throw new NotImplementedException($"Cannot deserialize type: {type.AssemblyQualifiedName}");
                }
            }
        }
Ejemplo n.º 12
0
        public static void SerializeObject(
            BinaryWriter writer, object obj, Type overrideType, bool isNullableIfReferenceType,
            bool areElementsNullableIfReferenceType
            )
        {
            Assert.IsTrue(!isNullableIfReferenceType || (overrideType != null));

            var objType = overrideType ?? obj?.GetType();

            Assert.IsNotNull(objType);
            Assert.IsTrue((obj != null) || !objType.IsClass || isNullableIfReferenceType);

            var nullableUnderlyingType = Nullable.GetUnderlyingType(objType);

            if ((nullableUnderlyingType == null) && isNullableIfReferenceType && objType.IsClass)
            {
                nullableUnderlyingType = objType;
            }

            if (nullableUnderlyingType != null)
            {
                writer.Write(obj != null);

                if (obj != null)
                {
                    objType = nullableUnderlyingType;
                }
                else
                {
                    return;
                }
            }

            if (objType == typeof(bool))
            {
                writer.Write((bool)obj);
            }
            else if (objType == typeof(sbyte))
            {
                writer.Write((sbyte)obj);
            }
            else if (objType == typeof(byte))
            {
                writer.Write((byte)obj);
            }
            else if (objType == typeof(ushort))
            {
                writer.Write((ushort)obj);
            }
            else if (objType == typeof(short))
            {
                writer.Write((short)obj);
            }
            else if (objType == typeof(uint))
            {
                writer.Write((uint)obj);
            }
            else if (objType == typeof(int))
            {
                writer.Write((int)obj);
            }
            else if (objType == typeof(ulong))
            {
                writer.Write((ulong)obj);
            }
            else if (objType == typeof(long))
            {
                writer.Write((long)obj);
            }
            else if (objType == typeof(float))
            {
                writer.Write((float)obj);
            }
            else if (objType == typeof(double))
            {
                writer.Write((double)obj);
            }
            else if (objType == typeof(decimal))
            {
                writer.Write((decimal)obj);
            }
            else if (objType == typeof(char))
            {
                writer.Write((char)obj);
            }
            else if (objType == typeof(string))
            {
                writer.Write((string)obj);
            }
            else if (objType == typeof(float2))
            {
                Serialize(writer, (float2)obj);
            }
            else if (objType == typeof(float3))
            {
                Serialize(writer, (float3)obj);
            }
            else if (objType == typeof(float4))
            {
                Serialize(writer, (float4)obj);
            }
            else if (objType == typeof(Vector2))
            {
                Serialize(writer, (Vector2)obj);
            }
            else if (objType == typeof(Vector3))
            {
                Serialize(writer, (Vector3)obj);
            }
            else if (objType == typeof(Vector4))
            {
                Serialize(writer, (Vector4)obj);
            }
            else if (typeof(INetworkSerializable).IsAssignableFrom(obj.GetType()))
            {
                ((INetworkSerializable)obj).Serialize(writer);
            }
            else if (typeof(ICollection).IsAssignableFrom(objType))
            {
                Type elementType;

                if (objType.IsArray)
                {
                    elementType = objType.GetElementType();
                }
                else if (objType.IsGenericType)
                {
                    elementType = objType.GetGenericArguments()[0];
                }
                else
                {
                    throw new NotImplementedException("Non-generic collections aren't supported.");
                }

                var collection = (ICollection)obj;
                writer.Write((uint)collection.Count);

                foreach (var element in collection)
                {
                    SerializeObject(
                        writer, element, overrideType: elementType,
                        isNullableIfReferenceType: areElementsNullableIfReferenceType,
                        areElementsNullableIfReferenceType: false
                        );
                }
            }
            else
            {
                if (objType.IsEnum)
                {
                    var smallestTypeToHoldEnumValues = GetSmallestUIntTypeToHoldEnumValues(objType);
                    var objToSerialize = Convert.ChangeType(obj, smallestTypeToHoldEnumValues);
                    SerializeObject(
                        writer, objToSerialize, overrideType: null, isNullableIfReferenceType: false,
                        areElementsNullableIfReferenceType: false
                        );
                }
                else if (objType.IsClass || objType.IsValueType)
                {
                    var objFields = NetLib.GetFieldInfosToSerialize(objType);
                    foreach (var objField in objFields)
                    {
                        SerializeObject(
                            writer, objField.GetValue(obj), objField.FieldType, isNullableIfReferenceType: false,
                            areElementsNullableIfReferenceType: false
                            );
                    }

                    var objProperties = NetLib.GetPropertyInfosToSerialize(objType);
                    foreach (var objProperty in objProperties)
                    {
                        if (!objProperty.CanRead || !objProperty.CanWrite)
                        {
                            continue;
                        }

                        SerializeObject(
                            writer, objProperty.GetValue(obj), objProperty.PropertyType,
                            isNullableIfReferenceType: false, areElementsNullableIfReferenceType: false
                            );
                    }
                }
                else
                {
                    throw new NotImplementedException($"Cannot serialize type: {objType.AssemblyQualifiedName}");
                }
            }
        }