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