Skip to content

Commit 92d0df7

Browse files
paulpachvis2k
and
vis2k
committed
feat: SyncToOwner now works with authority (#1204)
* WIP redoing authority * Local client also handles authority * Remove unused callback * Update Assets/Mirror/Runtime/NetworkIdentity.cs Co-Authored-By: MrGadget <chris@clevertech.net> * Update Assets/Mirror/Runtime/NetworkIdentity.cs Co-Authored-By: vis2k <info@noobtuts.com> * Rename pendingOwner * Update Assets/Mirror/Runtime/NetworkIdentity.cs Co-Authored-By: vis2k <info@noobtuts.com> * Update Assets/Mirror/Runtime/NetworkIdentity.cs Co-Authored-By: vis2k <info@noobtuts.com> * Update Assets/Mirror/Runtime/NetworkIdentity.cs Co-Authored-By: vis2k <info@noobtuts.com> * Update Assets/Mirror/Runtime/NetworkIdentity.cs Co-Authored-By: vis2k <info@noobtuts.com>
1 parent 24d8368 commit 92d0df7

File tree

5 files changed

+47
-99
lines changed

5 files changed

+47
-99
lines changed

Assets/Mirror/Runtime/ClientScene.cs

+3-10
Original file line numberDiff line numberDiff line change
@@ -490,12 +490,14 @@ static void ApplySpawnPayload(NetworkIdentity identity, SpawnMessage msg)
490490

491491
identity.netId = msg.netId;
492492
NetworkIdentity.spawned[msg.netId] = identity;
493+
identity.pendingAuthority = msg.isOwner;
493494

494495
// objects spawned as part of initial state are started on a second pass
495496
if (isSpawnFinished)
496497
{
497498
identity.OnStartClient();
498499
CheckForLocalPlayer(identity);
500+
identity.hasAuthority = identity.pendingAuthority;
499501
}
500502
}
501503

@@ -599,6 +601,7 @@ internal static void OnObjectSpawnFinished(ObjectSpawnFinishedMessage _)
599601
// use data from scene objects
600602
foreach (NetworkIdentity identity in NetworkIdentity.spawned.Values.OrderBy(uv => uv.netId))
601603
{
604+
identity.hasAuthority = identity.pendingAuthority;
602605
if (!identity.isClient)
603606
{
604607
identity.OnStartClient();
@@ -712,16 +715,6 @@ internal static void OnSyncEventMessage(SyncEventMessage msg)
712715
}
713716
}
714717

715-
internal static void OnClientAuthority(ClientAuthorityMessage msg)
716-
{
717-
if (LogFilter.Debug) Debug.Log("ClientScene.OnClientAuthority for netId: " + msg.netId);
718-
719-
if (NetworkIdentity.spawned.TryGetValue(msg.netId, out NetworkIdentity identity))
720-
{
721-
identity.ForceAuthority(msg.authority);
722-
}
723-
}
724-
725718
// called for the one object in the spawn message which is the local player!
726719
internal static void OnSpawnMessageForLocalPlayer(uint netId)
727720
{

Assets/Mirror/Runtime/Messages.cs

+3-18
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,7 @@ public struct SpawnMessage : IMessageBase
340340
{
341341
public uint netId;
342342
public bool isLocalPlayer;
343+
public bool isOwner;
343344
public ulong sceneId;
344345
public Guid assetId;
345346
public Vector3 position;
@@ -353,6 +354,7 @@ public void Deserialize(NetworkReader reader)
353354
{
354355
netId = reader.ReadPackedUInt32();
355356
isLocalPlayer = reader.ReadBoolean();
357+
isOwner = reader.ReadBoolean();
356358
sceneId = reader.ReadPackedUInt64();
357359
if (sceneId == 0)
358360
{
@@ -368,6 +370,7 @@ public void Serialize(NetworkWriter writer)
368370
{
369371
writer.WritePackedUInt32(netId);
370372
writer.WriteBoolean(isLocalPlayer);
373+
writer.WriteBoolean(isOwner);
371374
writer.WritePackedUInt64(sceneId);
372375
if (sceneId == 0)
373376
{
@@ -424,24 +427,6 @@ public void Serialize(NetworkWriter writer)
424427
}
425428
}
426429

427-
public struct ClientAuthorityMessage : IMessageBase
428-
{
429-
public uint netId;
430-
public bool authority;
431-
432-
public void Deserialize(NetworkReader reader)
433-
{
434-
netId = reader.ReadPackedUInt32();
435-
authority = reader.ReadBoolean();
436-
}
437-
438-
public void Serialize(NetworkWriter writer)
439-
{
440-
writer.WritePackedUInt32(netId);
441-
writer.WriteBoolean(authority);
442-
}
443-
}
444-
445430
public struct UpdateVarsMessage : IMessageBase
446431
{
447432
public uint netId;

Assets/Mirror/Runtime/NetworkClient.cs

-1
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,6 @@ internal static void RegisterSystemHandlers(bool hostMode)
359359
RegisterHandler<ObjectSpawnFinishedMessage>(ClientScene.OnObjectSpawnFinished);
360360
RegisterHandler<UpdateVarsMessage>(ClientScene.OnUpdateVarsMessage);
361361
}
362-
RegisterHandler<ClientAuthorityMessage>(ClientScene.OnClientAuthority);
363362
RegisterHandler<RpcMessage>(ClientScene.OnRPCMessage);
364363
RegisterHandler<SyncEventMessage>(ClientScene.OnSyncEventMessage);
365364
}

Assets/Mirror/Runtime/NetworkIdentity.cs

+37-68
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,31 @@ public bool isServer
8282
/// <para>This value is determined at runtime. For most objects, authority is held by the server.</para>
8383
/// <para>For objects that had their authority set by AssignClientAuthority on the server, this will be true on the client that owns the object. NOT on other clients.</para>
8484
/// </summary>
85-
public bool hasAuthority { get; private set; }
85+
bool isOwner;
86+
87+
public bool hasAuthority
88+
{
89+
get => isOwner;
90+
set
91+
{
92+
bool previous = isOwner;
93+
isOwner = value;
94+
95+
if (previous && !isOwner)
96+
{
97+
OnStopAuthority();
98+
}
99+
if (!previous && isOwner)
100+
{
101+
OnStartAuthority();
102+
}
103+
}
104+
}
105+
106+
// whether this object has been spawned with authority
107+
// we need hasAuthority and pendingOwner because
108+
// we need to wait until all of them spawn before updating hasAuthority
109+
internal bool pendingAuthority { get; set; }
86110

87111
/// <summary>
88112
/// The set of network connections (players) that can see this object.
@@ -194,24 +218,6 @@ internal void SetClientOwner(NetworkConnection conn)
194218
connectionToClient.AddOwnedObject(this);
195219
}
196220

197-
internal void ForceAuthority(bool authority)
198-
{
199-
if (hasAuthority == authority)
200-
{
201-
return;
202-
}
203-
204-
hasAuthority = authority;
205-
if (authority)
206-
{
207-
OnStartAuthority();
208-
}
209-
else
210-
{
211-
OnStopAuthority();
212-
}
213-
}
214-
215221
static uint nextNetworkId = 1;
216222
internal static uint GetNextNetworkId() => nextNetworkId++;
217223

@@ -220,23 +226,6 @@ internal void ForceAuthority(bool authority)
220226
/// </summary>
221227
public static void ResetNextNetworkId() => nextNetworkId = 1;
222228

223-
/// <summary>
224-
/// Obsolete: Host Migration was removed
225-
/// </summary>
226-
/// <param name="conn">The network connection that is gaining or losing authority.</param>
227-
/// <param name="identity">The object whose client authority status is being changed.</param>
228-
/// <param name="authorityState">The new state of client authority of the object for the connection.</param>
229-
[EditorBrowsable(EditorBrowsableState.Never), Obsolete("Host Migration was removed")]
230-
public delegate void ClientAuthorityCallback(NetworkConnection conn, NetworkIdentity identity, bool authorityState);
231-
232-
/// <summary>
233-
/// Obsolete: Host Migration was removed
234-
/// <para>Whenever an object is spawned using SpawnWithClientAuthority, or the client authority status of an object is changed with AssignClientAuthority or RemoveClientAuthority, then this callback will be invoked.</para>
235-
/// <para>This callback is used by the NetworkMigrationManager to distribute client authority state to peers for host migration. If the NetworkMigrationManager is not being used, this callback does not need to be populated.</para>
236-
/// </summary>
237-
[EditorBrowsable(EditorBrowsableState.Never), Obsolete("Host Migration was removed")]
238-
public static ClientAuthorityCallback clientAuthorityCallback;
239-
240229
// used when the player object for a connection changes
241230
internal void SetNotLocalPlayer()
242231
{
@@ -901,17 +890,11 @@ internal void SetLocalPlayer()
901890
// OnStartAuthority should only be called if hasAuthority was false when this function began,
902891
// or it will be called twice for this object, but that state is lost by the time OnStartAuthority
903892
// is called below, so the original value is cached here to be checked below.
904-
bool originAuthority = hasAuthority;
905893
hasAuthority = true;
906894

907895
foreach (NetworkBehaviour comp in networkBehavioursCache)
908896
{
909897
comp.OnStartLocalPlayer();
910-
911-
if (!originAuthority)
912-
{
913-
comp.OnStartAuthority();
914-
}
915898
}
916899
}
917900

@@ -1096,24 +1079,19 @@ public void RemoveClientAuthority()
10961079

10971080
if (connectionToClient != null)
10981081
{
1099-
// send msg to that client
1100-
ClientAuthorityMessage msg = new ClientAuthorityMessage
1101-
{
1102-
netId = netId,
1103-
authority = false
1104-
};
1105-
1106-
connectionToClient.Send(msg);
1107-
#pragma warning disable CS0618 // Type or member is obsolete
1108-
clientAuthorityCallback?.Invoke(connectionToClient, this, false);
1109-
#pragma warning restore CS0618 // Type or member is obsolete
1082+
NetworkConnectionToClient previousOwner = connectionToClient;
11101083

11111084
connectionToClient.RemoveOwnedObject(this);
11121085
connectionToClient = null;
1113-
}
11141086

1115-
// server now has authority (this is only called on server)
1116-
ForceAuthority(false);
1087+
// we need to resynchronize the entire object
1088+
// so just spawn it again,
1089+
// the client will not create a new instance, it will simply
1090+
// reset all variables and remove authority
1091+
NetworkServer.SendSpawnMessage(this, previousOwner);
1092+
1093+
connectionToClient = null;
1094+
}
11171095
}
11181096

11191097
/// <summary>
@@ -1145,17 +1123,9 @@ public bool AssignClientAuthority(NetworkConnection conn)
11451123

11461124
SetClientOwner(conn);
11471125

1148-
// send msg to that client
1149-
ClientAuthorityMessage msg = new ClientAuthorityMessage
1150-
{
1151-
netId = netId,
1152-
authority = true
1153-
};
1154-
conn.Send(msg);
1155-
1156-
#pragma warning disable CS0618 // Type or member is obsolete
1157-
clientAuthorityCallback?.Invoke(conn, this, true);
1158-
#pragma warning restore CS0618 // Type or member is obsolete
1126+
// The client will match to the existing object
1127+
// update all variables and assign authority
1128+
NetworkServer.SendSpawnMessage(this, conn);
11591129
return true;
11601130
}
11611131

@@ -1173,7 +1143,6 @@ internal void Reset()
11731143
m_Reset = false;
11741144
m_IsServer = false;
11751145
isClient = false;
1176-
hasAuthority = false;
11771146

11781147
netId = 0;
11791148
isLocalPlayer = false;

Assets/Mirror/Runtime/NetworkServer.cs

+4-2
Original file line numberDiff line numberDiff line change
@@ -1090,6 +1090,7 @@ internal static void SendSpawnMessage(NetworkIdentity identity, NetworkConnectio
10901090
{
10911091
netId = identity.netId,
10921092
isLocalPlayer = conn?.identity == identity,
1093+
isOwner = identity.connectionToClient == conn && conn != null,
10931094
sceneId = identity.sceneId,
10941095
assetId = identity.assetId,
10951096
// use local values for VR support
@@ -1103,8 +1104,7 @@ internal static void SendSpawnMessage(NetworkIdentity identity, NetworkConnectio
11031104
{
11041105
// use owner segment if 'conn' owns this identity, otherwise
11051106
// use observers segment
1106-
bool isOwner = identity.connectionToClient == conn;
1107-
msg.payload = isOwner ? ownerSegment : observersSegment;
1107+
msg.payload = msg.isOwner ? ownerSegment : observersSegment;
11081108

11091109
conn.Send(msg);
11101110
}
@@ -1116,13 +1116,15 @@ internal static void SendSpawnMessage(NetworkIdentity identity, NetworkConnectio
11161116
// serialized because the spawn message contains more data.
11171117
// components might still be updated later on.)
11181118
msg.payload = ownerSegment;
1119+
msg.isOwner = true;
11191120
SendToClientOfPlayer(identity, msg);
11201121

11211122
// send observersWriter to everyone but owner
11221123
// (spawn no matter what, even if no components were
11231124
// serialized because the spawn message contains more data.
11241125
// components might still be updated later on.)
11251126
msg.payload = observersSegment;
1127+
msg.isOwner = false;
11261128
SendToReady(identity, msg, false);
11271129
}
11281130

0 commit comments

Comments
 (0)