Skip to content
This repository has been archived by the owner on Aug 15, 2022. It is now read-only.

Players will not see already joined players when connecting to lobby system #367

Open
blapaz opened this issue May 29, 2020 · 7 comments
Open

Comments

@blapaz
Copy link

blapaz commented May 29, 2020

Version Number and Operating System(s):

2019.3.6f & Windows 10

Expected behavior:

When implementing the lobby system, all players should show in the lobby no matter if they join first, second, and so on. They should also then be shown for all clients whenever they choose to join the game from the lobby.

Actual behavior:

Currently when implementing the lobby system, players that are in the lobby do not see anyone who joined before them (players do not show in list or receive those players messages). The same occurs with the order of players who then join the game. This does not occur if the lobby system is removed and players load directly into the game.

Eg. When player two joins he will not see player one listed. However, player one will see player two. Messages from player two will show to player one but not vise versa.
This same pattern also occurs then when players join the game from the lobby.

Steps to reproduce:

Create project following the instructions found on the wiki for Getting Started using the Network Manager. Once everything is in place add the Lobby System.

[Optional] Discord Username:

Panda™ #9444

@TonyViT
Copy link

TonyViT commented Jun 26, 2020

This is a very annoying issue. A guy on Discord gave me some scripts that are a workaround on this, but I had to tweak them a bit to make them work. Otherwise, I discovered that a Thread.Sleep in the lobbyservice helps a lot with this problem

blapaz added a commit to blapaz/ForgeNetworkingRemastered that referenced this issue Jun 26, 2020
@blapaz
Copy link
Author

blapaz commented Jun 26, 2020

I added a fix for this issue loosely based on some snippets I received from @Persegan. This could be improved but this does allow the lobby system to work as expected and without the issue.

Pull request: #369

@TonyViT
Copy link

TonyViT commented Jun 27, 2020

Persegan gave me those fixes as well (he's been very kind), but they have issues if you have many players because there are too many messages that get exchanged. Yesterday I tried with 4 players on Android devices and the lobby got crazy.

@blapaz
Copy link
Author

blapaz commented Jun 27, 2020

I have not run into that issue even with that many and more players connecting. Although the way I use it, my players are not all connecting into the lobby at the same exact time.

@blapaz
Copy link
Author

blapaz commented Jun 27, 2020

I would have to look at the code again but I feel like instead of sending an RPC for every player already in the lobby, a RPC should be created to send all that info in one call. One RPC that sends all players already connected to the newly connected player.

In theory would fix your issue, just would have to look how you could set it up.

@TonyViT
Copy link

TonyViT commented Jun 27, 2020

I'm going to investigate it next week for the program we are implementing, maybe if I find a solution, I can share it with the community. I will keep you posted!

@TonyViT
Copy link

TonyViT commented Jun 29, 2020

Hey @blapaz @Persegan I have improved the solution by Persegan:

  • It now supports Custom names
  • It sends only the necessary messages.

Now I have no endless loops anymore, even with 10-12 players!

My idea has been sending the messages of old players only to the last connecting user, and preventing the function to be called multiple times. Furthermore I've modified the RPC about players so now a name is shared.

I know git well, but I'm not very practical with big GitHub repos, so can you tell me how can I start from Persegan solution and do a pull request?

For people stumbling here before I make the pull request, I'll try to share here some code snippet. Start from solution from Persegan, not from the regular branch, or nothing will work.

Then in the LobbyManager:

  1. Add a variable
    /// <summary>
    /// True if the lobby has already sent a sync to get the list of connected players, false otherwise
    /// </summary>
    private bool m_setupped = false;
  1. Change the method SetupService with this one
    private void SetupService(NetworkObject obj)
    {
        if (!m_setupped)
        {
            LobbyService.Instance.Initialize(obj);
            _networkObjectReference = LobbyService.Instance.networkObject;
            LobbyService.Instance.networkObject.SendRpc(LobbyService.RPC_SYNC_ALL_PLAYERS, Receivers.Server, _networkObjectReference.MyPlayerId); //RPC Fix received on discord

            MainThreadManager.Run(() => SetupComplete());
            m_setupped = true;
        }
    }

This will make sure the event is sent only to the latest connecting player and won't be repeated

Now switch to LobbyService:
3. At line 483 change the signature of the RPC SyncAllPlayers to accept the id of the player and change PlayerJoined to accept a player name

networkObject.RegisterRpc("PlayerJoined", PlayerJoined, typeof(uint), typeof(string));
networkObject.RegisterRpc("SyncAllPlayers", SyncAllPlayers, typeof(uint));

  1. Change the code of SyncAllPlayers with this one, that makes the calls only to selected id
private void SyncAllPlayers(RpcArgs args)
        {           
            Debug.Log("---------------------------------------------------------------");
            if (networkObject.IsServer)
            {
                uint newlyJoinedPlayerId = args.GetNext<uint>();          
                int newlyJoinedPlayerIndex = LobbyService.Instance.MasterLobby.LobbyPlayers.FindIndex(player => player.NetworkId == (int)newlyJoinedPlayerId); //find the id of the object in the list

                //for (int i = 0; i < LobbyService.Instance.MasterLobby.LobbyPlayers.Count; i++)
                //{
                    LobbyService.Instance.networkObject.Networker.IteratePlayers((p) =>
                    {
                        IClientMockPlayer cPlayer = LobbyService.Instance.MasterLobby.LobbyPlayers.First(l => l.NetworkId == p.NetworkId);
                        Debug.Log("Debugging Name Before RPC Joined" + cPlayer.Name);
                        Debug.Log("Debugging Avatar ID Before RPC Joined " + cPlayer.AvatarID);
                        if (p == LobbyService.Instance.MasterLobby.LobbyPlayers[newlyJoinedPlayerIndex])
                            return;
                        LobbyService.Instance.networkObject.SendRpc(LobbyService.Instance.networkObject.Networker.Players[newlyJoinedPlayerIndex], RPC_PLAYER_JOINED, p.NetworkId, cPlayer.Name == null ? "" : cPlayer.Name);
                        Debug.Log("Debugging Name After RPC Joined " + cPlayer.Name);
                        Debug.Log("Debugging Avatar ID After RPC Joined " + cPlayer.AvatarID);
                        LobbyService.Instance.networkObject.SendRpc(LobbyService.Instance.networkObject.Networker.Players[newlyJoinedPlayerIndex], RPC_PLAYER_SYNC, p.NetworkId, cPlayer.Name, cPlayer.TeamID, cPlayer.AvatarID);
                    });
                //}
            }
            Debug.Log("---------------------------------------------------------------FIN");

        }
  1. Change the code of PlayerJoined with this one that accept the name of a player
        /// <summary>
        /// Arguments:
        /// uint playerid
        /// </summary>
        private void PlayerJoined(RpcArgs args)
        {
            Debug.Log("Player Joined Called");
            uint playerId = args.GetNext<uint>();
            string playerName = args.GetNext<string>();
            var player = CreateClientMockPlayer(playerId, String.IsNullOrEmpty(playerName) ? "Player " + playerId : playerName);

            MasterLobby.OnFNPlayerConnected(player);
        }
  1. In the PlayerConnected method, modify the calls to the PLAYER_JOINED RPC by adding a last empty-string parameter
    networkObject.SendRpc(RPC_PLAYER_JOINED, Receivers.All, player.NetworkId, "");
    networkObject.SendRpc(player, RPC_PLAYER_JOINED, p.NetworkId, "");

If I haven't forgotten anything, it should work, and you should have less exchange of messages and also the propagation of the names you have chosen for your players!

I hope this will help someone

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants