northwood-studios/NwPluginAPI

Previous PlayerIDs of Dedicated Server are staying in Player.PlayersIds after round restart

Lufou opened this issue · 2 comments

Lufou commented

I made the tests only for Player.PlayersIds but I think it works the same with Player.PlayersUserIds (not sure for this one).
But anyway, Player.PlayersIds dict is not correctly cleared when the round is restarting. This leads to error when TryGetting an IGameComponent from PlayerID, for instance, PlayerID 10 is assigned to the player, if the PlayerID 10 is already in the PlayersIds dict, it's not added in the dict because of the condition :

if (!Player.PlayersIds.ContainsKey(this.PlayerId))
{
     Player.PlayersIds.Add(this.PlayerId, this.ReferenceHub);
}

So this leads to problems when trying to TryGet an IGameComponent from a playerID from this dictinary, because it's pointing to destroyed RHubs. (used in the Player.Get(int playerId) method)

Example of the dictionary not cleaning properly:

[2023-01-17 11:34:17.200 +01:00] [Warning] Round #1 -> PlayersId #1 -> Server: False
[2023-01-17 11:34:17.212 +01:00] [Warning] Round #1 -> PlayersId #2 -> Server: True

Both rounds were started only with the Dedicated Server, on the second round dedi was pid 2 and on the first round it was pid 1.

I want to precise that PlayersIds only keep previous Dedicated Server PID meaning that OnInternalDestroy() (which should remove the PID from the dictionary) is not called for the Dedicated Server

Lufou commented

The error when you TryGet from this dict a PID of a player who's currently on the server but where the PID was previously assigned to Dedicated Server and so, still in the PlayersIds dict:

System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.NullReferenceException
                                   at (wrapper managed-to-native) UnityEngine.Component.get_gameObject(UnityEngine.Component)
                                   at ReferenceHub.GetHashCode () [0x00000] in <114aeb735cee4e8082cd0686c54991e8>:0
                                   at System.Collections.Generic.ObjectEqualityComparer`1[T].GetHashCode (T obj) [0x0000a] in <9577ac7a62ef43179789031239ba8798>:0
                                   at System.Collections.Generic.Dictionary`2[TKey,TValue].FindEntry (TKey key) [0x0001b] in <9577ac7a62ef43179789031239ba8798>:0
                                   at System.Collections.Generic.Dictionary`2[TKey,TValue].TryGetValue (TKey key, TValuevalue) [0x00000] in <9577ac7a62ef43179789031239ba8798>:0
                                   at PluginAPI.Core.Factories.Factory`1[T].GetOrAdd (PluginAPI.Core.Interfaces.IGameComponent component) [0x00000] in <4c2a3c9f04a54612acd3e9a88faf0eba>:0
                                   at PluginAPI.Core.Player.TryGet[T] (PluginAPI.Core.Interfaces.IGameComponent component, Tplayer) [0x00039] in <4c2a3c9f04a54612acd3e9a88faf0eba>:0
                                   at PluginAPI.Core.Player.TryGet[T] (System.Int32 playerId, Tplayer) [0x00018] in <4c2a3c9f04a54612acd3e9a88faf0eba>:0
                                   at PluginAPI.Core.Player.TryGet (System.Int32 playerId, PluginAPI.Core.Playerplayer) [0x00000] in
Lufou commented

I confirm that the root of the issue is that Player.OnInternalDestroy() is not called for the Dedicated Server.