DoubleDeez / MDFramework

A multiplayer C# game framework for Godot 3.4 Mono.
https://discord.gg/UH49eHK
MIT License
77 stars 13 forks source link

Allow for swapping of network master #38

Closed Beider closed 4 years ago

Beider commented 4 years ago

After my refactoring network master can't be swapped since we buffer this information instead of checking every update.

public virtual bool ShouldReplicate()
{
    // Note this means we don't support nodes swapping network master.
    // If that should be supported then CheckIfShouldReplicate has to be run every update.
    return IsShouldReplicate;
}

It would be good to provide a solution that supports buffering but also allows for switching of network master. Perhaps we can add a node extension along the same line of SpawnNetworkNode() that is called something like ChangeNetworkMaster(int PeerId) which would simply change the network master of any node you call it on.

DoubleDeez commented 4 years ago

I like the idea of ChangeNetworkMaster(int PeerId) but it does add complexity to using the framework since it "breaks" a feature of using Godot. Maybe we can cache the network master in the MDReplicator and if it changes, update as needed?

Beider commented 4 years ago

It would be fairly easy to buffer this and just check if it has changed then run the CheckIfShouldReplicate again. I would suggest we add this to the ReplicatedNode then so we only have to check once for all the members. If it has changed we just run CheckIfShouldReplicate again. I can sneak this fix in with the MDRpc & MDRset fixes later.

Beider commented 4 years ago

There I already added this, this should solve the problem. I pass in the current master so I don't have to do the whole check if the ref is not null and then cast it to a node. Since the ref has already been resolved for replication purposes.

class ReplicatedNode
{
    public ReplicatedNode(Node InInstance, List<MDReplicatedMember> InMembers)
    {
        Instance = Godot.Object.WeakRef(InInstance);
        Members = InMembers;
        NetworkMaster = InInstance.GetNetworkMaster();
    }

    public void CheckIfNetworkMasterChanged(int CurrentMaster)
    {
        if (CurrentMaster != NetworkMaster)
        {
            Members.ForEach(member => member.CheckIfShouldReplicate());
            NetworkMaster = CurrentMaster;
        }
    }

    protected int NetworkMaster;

    public WeakRef Instance;

    public List<MDReplicatedMember> Members;
}

Here are the changes to the TickReplication()

for (int i = NodeList.Count - 1; i >= 0; --i)
            {
                ReplicatedNode RepNode = NodeList[i];
                Node Instance = RepNode.Instance.GetRef() as Node;
                if (Godot.Object.IsInstanceValid(Instance))
                {
                    RepNode.CheckIfNetworkMasterChanged(Instance.GetNetworkMaster());
DoubleDeez commented 4 years ago

Oh sweet, looks good