/// <summary>
        /// Same as RsetUnreliable except it checks if the network is activate first
        /// </summary>
        /// <param name="PeerId">The peer to send to</param>
        /// <param name="Property">The property to set</param>
        /// <param name="Value">The value</param>
        public static void MDRsetUnreliableId(this Node Instance, int PeerId, string Property, object Value)
        {
            if (!MDStatics.IsNetworkActive() && !MDStatics.IsServer())
            {
                return;
            }

            MDStatics.GetReplicator().SendClockedRset(PeerId, MDReliability.Unreliable, Instance, Property, Value);
        }
        /// <summary>
        /// Same as RpcUnreliableId except it checks if the network is activate first and takes game clock into account
        /// </summary>
        /// <param name="PeerId">The id of the peer to send to</param>
        /// <param name="Method">The method to call</param>
        /// <param name="Args">Arguments</param>
        public static void MDRpcUnreliableId(this Node Instance, int PeerId, string Method, params object[] Args)
        {
            if (!MDStatics.IsNetworkActive() && !MDStatics.IsServer())
            {
                return;
            }

            // Send through replicator
            MDStatics.GetReplicator().SendClockedRpc(PeerId, MDReliability.Unreliable, Instance, Method, Args);
        }
Example #3
0
 /// <summary>
 /// Notifies the server that initialization for this player has completed
 /// </summary>
 protected void MarkPlayerInitializationCompleted()
 {
     if (MDStatics.IsServer())
     {
         ServerMarkPlayerInitializationCompleted();
     }
     else
     {
         RpcId(MDStatics.GetServerId(), nameof(ServerMarkPlayerInitializationCompleted));
     }
 }
Example #4
0
        /// <summary>
        /// Sends a clocked rset to another client
        /// </summary>
        /// <param name="PeerId">The peer to send to</param>
        /// <param name="Reliability">Reliability to send at</param>
        /// <param name="Target">The node that is the target of our rpc call</param>
        /// <param name="MemberName">The name of the member to set</param>
        /// <param name="Value">The value to set</param>
        public void SendClockedRset(int PeerId, MDReliability Reliability, Node Target, string MemberName, object Value)
        {
            if (PeerId == MDStatics.GetPeerId() || (MDStatics.IsServer() && !MDStatics.IsNetworkActive() && PeerId == MDStatics.GetServerId()))
            {
                // This is to ourselves so just set
                Target.SetMemberValue(MemberName, Value);
                return;
            }
            MDRemoteMode     Mode      = MDStatics.GetMemberRpcType(Target, MemberName);
            MemberInfo       info      = MDStatics.GetMemberInfo(Target, MemberName);
            IMDDataConverter Converter = MDStatics.GetConverterForType(info.GetUnderlyingType());

            switch (Mode)
            {
            case MDRemoteMode.Master:
                if (!Target.IsNetworkMaster())
                {
                    // Remote invoke master only
                    SendClockedCall(PeerId, ClockedRemoteCall.TypeOfCall.RSET, Reliability, Target.GetPath(),
                                    MemberName, Mode, Converter.ConvertForSending(Value, true));
                }

                break;

            case MDRemoteMode.MasterSync:
                if (!Target.IsNetworkMaster())
                {
                    // Remote invoke master only
                    SendClockedCall(PeerId, ClockedRemoteCall.TypeOfCall.RSET, Reliability, Target.GetPath(),
                                    MemberName, Mode, Converter.ConvertForSending(Value, true));
                }

                Target.SetMemberValue(MemberName, Value);
                break;

            case MDRemoteMode.Puppet:
            case MDRemoteMode.Remote:
                // Remote invoke
                SendClockedCall(PeerId, ClockedRemoteCall.TypeOfCall.RSET, Reliability, Target.GetPath(),
                                MemberName, Mode, Converter.ConvertForSending(Value, true));
                break;

            case MDRemoteMode.PuppetSync:
            case MDRemoteMode.RemoteSync:
                // Remote invoke and local invoke
                SendClockedCall(PeerId, ClockedRemoteCall.TypeOfCall.RSET, Reliability, Target.GetPath(),
                                MemberName, Mode, Converter.ConvertForSending(Value, true));
                Target.SetMemberValue(MemberName, Value);
                break;
            }
        }
Example #5
0
        protected virtual void OnServerRequestedInitialization()
        {
            MDLog.Debug(LOG_CAT, $"Initializing PeerId [{PeerId}] from owner");
            string PlaceholderName = "Player_" + PeerId;

            if (MDStatics.IsServer())
            {
                OnClientSentPlayerName(PlaceholderName);
            }
            else
            {
                RpcId(MDStatics.GetServerId(), nameof(OnClientSentPlayerName), PlaceholderName);
            }
        }
Example #6
0
        /// <summary>
        /// Change the network master of a node. This only works on the server.
        /// </summary>
        /// <param name="Node">The node to change network master of</param>
        /// <param name="NewNetworkMaster">The new network master</param>
        /// <returns>True if network master was changed, false if not</returns>
        public bool ChangeNetworkMaster(Node Node, int NewNetworkMaster)
        {
            if (!GetAllPeerIds().Contains(NewNetworkMaster))
            {
                // Invalid network master
                return(false);
            }

            // Only server can change network master
            if (MDStatics.IsNetworkActive() && MDStatics.IsServer())
            {
                Node.SetNetworkMaster(NewNetworkMaster);
                Rpc(nameof(ChangeNetworkMasterOnClients), Node.GetPath(), NewNetworkMaster);
                return(true);
            }

            return(false);
        }
Example #7
0
        private void OnPlayerJoined(int PeerId)
        {
            // Skip local player
            if (PeerId == MDStatics.GetPeerId())
            {
                return;
            }

            MDLog.Debug(LOG_CAT, $"Registered JIPPlayer with Id: {PeerId}");
            JIPPlayers.Enqueue(new NewPlayer(PeerId, OS.GetTicksMsec()));
            if (MDStatics.IsServer())
            {
                List <object> networkIdUpdates = new List <object>();
                foreach (uint key in NetworkIdKeyMap.GetKeys())
                {
                    networkIdUpdates.Add(key);
                    networkIdUpdates.Add(NetworkIdKeyMap.GetValue(key));
                }

                RpcId(PeerId, nameof(UpdateNetworkIdMap), networkIdUpdates);
            }
        }
Example #8
0
        /// <summary>
        /// Registers the given instance's fields marked with [MDReplicated()]
        /// </summary>
        /// <param name="Instance">The node to register</param>
        public void RegisterReplication(Node Instance)
        {
            List <MemberInfo>         Members     = MDStatics.GetTypeMemberInfos(Instance);
            List <MDReplicatedMember> NodeMembers = new List <MDReplicatedMember>();

            foreach (MemberInfo Member in Members)
            {
                MDReplicated RepAttribute = Member.GetCustomAttribute(typeof(MDReplicated)) as MDReplicated;
                if (RepAttribute == null)
                {
                    continue;
                }

                MDReplicatedSetting[] Settings   = GetSettings(Member);
                MDReplicatedMember    NodeMember = CreateReplicatedMember(Member, RepAttribute, Instance, Settings);

                NodeMembers.Add(NodeMember);

                ProcessSettingsForMember(NodeMember, ParseParameters(typeof(Settings), Settings));

                GroupManager.AddReplicatedMember(NodeMember);

                MDLog.Debug(LOG_CAT, $"Adding Replicated Node {Instance.Name} Member {Member.Name}");

                if (HasRPCModeSet(Member) == false)
                {
                    Instance.RsetConfig(Member.Name, MultiplayerAPI.RPCMode.Puppet);
                }
            }

            if (NodeMembers.Count > 0)
            {
                NodeList.Add(new ReplicatedNode(Instance, NodeMembers));
                List <object> networkIdUpdates = new List <object>();
                foreach (MDReplicatedMember member in NodeMembers)
                {
                    string MemberUniqueKey = member.GetUniqueKey();
                    KeyToMemberMap.Add(MemberUniqueKey, member);

                    // Check if we have a buffer waiting for this member
                    if (NetworkIdKeyMap.ContainsKey(MemberUniqueKey))
                    {
                        NetworkIdKeyMap.CheckBuffer(NetworkIdKeyMap.GetValue(MemberUniqueKey), member);
                    }

                    if (MDStatics.IsServer())
                    {
                        if (!NetworkIdKeyMap.ContainsKey(member.GetUniqueKey()))
                        {
                            uint networkid = GetReplicationId();
                            MDLog.Trace(LOG_CAT, $"Adding NetworkIdKeyMap key [{member.GetUniqueKey()}] with id [{networkid}]");
                            NetworkIdKeyMap.AddNetworkKeyIdPair(networkid, member.GetUniqueKey());
                            NetworkIdKeyMap.CheckBuffer(networkid, member);
                            networkIdUpdates.Add(networkid);
                            networkIdUpdates.Add(member.GetUniqueKey());
                        }
                    }
                }

                if (MDStatics.IsNetworkActive() && networkIdUpdates.Count > 0)
                {
                    Rpc(nameof(UpdateNetworkIdMap), networkIdUpdates);
                }
            }
        }
Example #9
0
        /// <summary>
        /// Sends a clocked RPC call to another client
        /// </summary>
        /// <param name="PeerId">The peer to send to</param>
        /// <param name="Reliability">Reliability to send at</param>
        /// <param name="Target">The node that is the target of our rpc call</param>
        /// <param name="Method">The method we want to invoke on the node</param>
        /// <param name="Parameters">Parameters for the call</param>
        public void SendClockedRpc(int PeerId, MDReliability Reliability, Node Target, string Method,
                                   params object[] Parameters)
        {
            if (PeerId == MDStatics.GetPeerId() || (MDStatics.IsServer() && !MDStatics.IsNetworkActive() && PeerId == MDStatics.GetServerId()))
            {
                // This is to ourselves so just invoke
                RpcSenderId = PeerId;
                Target.Invoke(Method, Parameters);
                RpcSenderId = -1;
                return;
            }
            MDRemoteMode Mode         = MDStatics.GetMethodRpcType(Target, Method, Parameters);
            int          MethodNumber = MDStatics.GetMethodNumber(Target, Method, Parameters);

            if (MethodNumber == -1)
            {
                // Abort
                MDLog.Fatal(LOG_CAT, $"Could not find method number for {Target.GetType().ToString()}#{Method}({MDStatics.GetParametersAsString(Parameters)})");
                return;
            }
            MethodInfo MethodInfo = MDStatics.GetMethodInfo(Target, MethodNumber);

            object[] SendingParams = MDStatics.ConvertParametersForSending(MethodInfo, Parameters);
            switch (Mode)
            {
            case MDRemoteMode.Master:
                if (!Target.IsNetworkMaster())
                {
                    // Remote invoke master only
                    SendClockedCall(PeerId, ClockedRemoteCall.TypeOfCall.RPC, Reliability, Target.GetPath(), MethodNumber.ToString(),
                                    Mode, SendingParams);
                }

                break;

            case MDRemoteMode.MasterSync:
                if (!Target.IsNetworkMaster())
                {
                    // Remote invoke master only
                    SendClockedCall(PeerId, ClockedRemoteCall.TypeOfCall.RPC, Reliability, Target.GetPath(), MethodNumber.ToString(),
                                    Mode, SendingParams);
                }

                Target.Invoke(Method, Parameters);
                break;

            case MDRemoteMode.Puppet:
            case MDRemoteMode.Remote:
                // Remote invoke
                SendClockedCall(PeerId, ClockedRemoteCall.TypeOfCall.RPC, Reliability, Target.GetPath(), MethodNumber.ToString(),
                                Mode, SendingParams);
                break;

            case MDRemoteMode.PuppetSync:
            case MDRemoteMode.RemoteSync:
                // Remote invoke and local invoke
                SendClockedCall(PeerId, ClockedRemoteCall.TypeOfCall.RPC, Reliability, Target.GetPath(), MethodNumber.ToString(),
                                Mode, SendingParams);
                Target.Invoke(Method, Parameters);
                break;
            }
        }