fix: NetworkIdentity.OnStartLocalPlayer catches exceptions now too. fixes a potential bug where an exception in PlayerInventory.OnStartLocalPlayer would cause PlayerEquipment.OnStartLocalPlayer to not be called

This commit is contained in:
vis2k 2020-02-28 16:33:38 +01:00
parent 4926bb818a
commit 5ed5f84409
2 changed files with 34 additions and 2 deletions

View File

@ -582,9 +582,21 @@ internal void OnStartLocalPlayer()
previousLocalPlayer = this; previousLocalPlayer = this;
foreach (NetworkBehaviour comp in NetworkBehaviours) foreach (NetworkBehaviour comp in NetworkBehaviours)
{
// an exception in OnStartLocalPlayer should be caught, so that
// one component's exception doesn't stop all other components
// from being initialized
// => this is what Unity does for Start() etc. too.
// one exception doesn't stop all the other Start() calls!
try
{ {
comp.OnStartLocalPlayer(); comp.OnStartLocalPlayer();
} }
catch (Exception e)
{
Debug.LogError("Exception in OnStartClient:" + e.Message + " " + e.StackTrace);
}
}
} }
bool hadAuthority; bool hadAuthority;

View File

@ -74,6 +74,16 @@ class StopAuthorityCalledNetworkBehaviour : NetworkBehaviour
public override void OnStopAuthority() { ++called; } public override void OnStopAuthority() { ++called; }
} }
class StartLocalPlayerExceptionNetworkBehaviour : NetworkBehaviour
{
public int called;
public override void OnStartLocalPlayer()
{
++called;
throw new Exception("some exception");
}
}
class StartLocalPlayerCalledNetworkBehaviour : NetworkBehaviour class StartLocalPlayerCalledNetworkBehaviour : NetworkBehaviour
{ {
public int called; public int called;
@ -855,16 +865,26 @@ public void OnStartLocalPlayer()
// create a networkidentity with our test component // create a networkidentity with our test component
GameObject gameObject = new GameObject(); GameObject gameObject = new GameObject();
NetworkIdentity identity = gameObject.AddComponent<NetworkIdentity>(); NetworkIdentity identity = gameObject.AddComponent<NetworkIdentity>();
StartLocalPlayerExceptionNetworkBehaviour compEx = gameObject.AddComponent<StartLocalPlayerExceptionNetworkBehaviour>();
StartLocalPlayerCalledNetworkBehaviour comp = gameObject.AddComponent<StartLocalPlayerCalledNetworkBehaviour>(); StartLocalPlayerCalledNetworkBehaviour comp = gameObject.AddComponent<StartLocalPlayerCalledNetworkBehaviour>();
// call OnStartLocalPlayer on identity should call it in comp // make sure our test values are set to 0
Assert.That(compEx.called, Is.EqualTo(0));
Assert.That(comp.called, Is.EqualTo(0)); Assert.That(comp.called, Is.EqualTo(0));
// call OnStartLocalPlayer in identity
// one component will throw an exception, but that shouldn't stop
// OnStartLocalPlayer from being called in the second one
LogAssert.ignoreFailingMessages = true; // exception will log an error
identity.OnStartLocalPlayer(); identity.OnStartLocalPlayer();
LogAssert.ignoreFailingMessages = false;
Assert.That(compEx.called, Is.EqualTo(1));
Assert.That(comp.called, Is.EqualTo(1)); Assert.That(comp.called, Is.EqualTo(1));
// we have checks to make sure that it's only called once. // we have checks to make sure that it's only called once.
// let's see if they work. // let's see if they work.
identity.OnStartLocalPlayer(); identity.OnStartLocalPlayer();
Assert.That(compEx.called, Is.EqualTo(1)); // same as before?
Assert.That(comp.called, Is.EqualTo(1)); // same as before? Assert.That(comp.called, Is.EqualTo(1)); // same as before?
// clean up // clean up