mirror of
https://github.com/MirrorNetworking/Mirror.git
synced 2024-11-18 02:50:32 +00:00
Formatting doc comments (#2131)
* making comments in NetworkServer doc comments * making comments in NetworkIdentity doc comments
This commit is contained in:
parent
c3765c101d
commit
da629e5f71
@ -17,32 +17,89 @@
|
||||
namespace Mirror
|
||||
{
|
||||
/// <summary>
|
||||
/// The NetworkIdentity identifies objects across the network, between server and clients. Its primary data is a NetworkInstanceId which is allocated by the server and then set on clients. This is used in network communications to be able to lookup game objects on different machines.
|
||||
/// The NetworkIdentity identifies objects across the network, between server and clients.
|
||||
/// Its primary data is a NetworkInstanceId which is allocated by the server and then set on clients.
|
||||
/// This is used in network communications to be able to lookup game objects on different machines.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>The NetworkIdentity is used to synchronize information in the object with the network. Only the server should create instances of objects which have NetworkIdentity as otherwise they will not be properly connected to the system.</para>
|
||||
/// <para>For complex objects with a hierarchy of subcomponents, the NetworkIdentity must be on the root of the hierarchy. It is not supported to have multiple NetworkIdentity components on subcomponents of a hierarchy.</para>
|
||||
/// <para>NetworkBehaviour scripts require a NetworkIdentity on the game object to be able to function.</para>
|
||||
/// <para>The NetworkIdentity manages the dirty state of the NetworkBehaviours of the object. When it discovers that NetworkBehaviours are dirty, it causes an update packet to be created and sent to clients.</para>
|
||||
/// <para>The flow for serialization updates managed by the NetworkIdentity is:</para>
|
||||
/// <para>* Each NetworkBehaviour has a dirty mask. This mask is available inside OnSerialize as syncVarDirtyBits</para>
|
||||
/// <para>* Each SyncVar in a NetworkBehaviour script is assigned a bit in the dirty mask.</para>
|
||||
/// <para>* Changing the value of SyncVars causes the bit for that SyncVar to be set in the dirty mask</para>
|
||||
/// <para>* Alternatively, calling SetDirtyBit() writes directly to the dirty mask</para>
|
||||
/// <para>* NetworkIdentity objects are checked on the server as part of it's update loop</para>
|
||||
/// <para>* If any NetworkBehaviours on a NetworkIdentity are dirty, then an UpdateVars packet is created for that object</para>
|
||||
/// <para>* The UpdateVars packet is populated by calling OnSerialize on each NetworkBehaviour on the object</para>
|
||||
/// <para>* NetworkBehaviours that are NOT dirty write a zero to the packet for their dirty bits</para>
|
||||
/// <para>* NetworkBehaviours that are dirty write their dirty mask, then the values for the SyncVars that have changed</para>
|
||||
/// <para>* If OnSerialize returns true for a NetworkBehaviour, the dirty mask is reset for that NetworkBehaviour, so it will not send again until its value changes.</para>
|
||||
/// <para>* The UpdateVars packet is sent to ready clients that are observing the object</para>
|
||||
/// <para>On the client:</para>
|
||||
/// <para>* an UpdateVars packet is received for an object</para>
|
||||
/// <para>* The OnDeserialize function is called for each NetworkBehaviour script on the object</para>
|
||||
/// <para>* Each NetworkBehaviour script on the object reads a dirty mask.</para>
|
||||
/// <para>* If the dirty mask for a NetworkBehaviour is zero, the OnDeserialize functions returns without reading any more</para>
|
||||
/// <para>* If the dirty mask is non-zero value, then the OnDeserialize function reads the values for the SyncVars that correspond to the dirty bits that are set</para>
|
||||
/// <para>* If there are SyncVar hook functions, those are invoked with the value read from the stream.</para>
|
||||
/// <para>
|
||||
/// The NetworkIdentity is used to synchronize information in the object with the network.
|
||||
/// Only the server should create instances of objects which have NetworkIdentity as otherwise
|
||||
/// they will not be properly connected to the system.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// For complex objects with a hierarchy of subcomponents, the NetworkIdentity must be on the root of the hierarchy.
|
||||
/// It is not supported to have multiple NetworkIdentity components on subcomponents of a hierarchy.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// NetworkBehaviour scripts require a NetworkIdentity on the game object to be able to function.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The NetworkIdentity manages the dirty state of the NetworkBehaviours of the object.
|
||||
/// When it discovers that NetworkBehaviours are dirty, it causes an update packet to be created and sent to clients.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The flow for serialization updates managed by the NetworkIdentity is:
|
||||
/// <list type="bullet">
|
||||
/// <item>
|
||||
/// Each NetworkBehaviour has a dirty mask. This mask is available inside OnSerialize as syncVarDirtyBits
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// Each SyncVar in a NetworkBehaviour script is assigned a bit in the dirty mask.
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// Changing the value of SyncVars causes the bit for that SyncVar to be set in the dirty mask
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// Alternatively, calling SetDirtyBit() writes directly to the dirty mask
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// NetworkIdentity objects are checked on the server as part of it's update loop
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// If any NetworkBehaviours on a NetworkIdentity are dirty, then an UpdateVars packet is created for that object
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// The UpdateVars packet is populated by calling OnSerialize on each NetworkBehaviour on the object
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// NetworkBehaviours that are NOT dirty write a zero to the packet for their dirty bits
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// NetworkBehaviours that are dirty write their dirty mask, then the values for the SyncVars that have changed
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// If OnSerialize returns true for a NetworkBehaviour, the dirty mask is reset for that NetworkBehaviour,
|
||||
/// so it will not send again until its value changes.
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// The UpdateVars packet is sent to ready clients that are observing the object
|
||||
/// </item>
|
||||
/// </list>
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// On the client:
|
||||
/// <list type="bullet">
|
||||
/// <item>
|
||||
/// an UpdateVars packet is received for an object
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// The OnDeserialize function is called for each NetworkBehaviour script on the object
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// Each NetworkBehaviour script on the object reads a dirty mask.
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// If the dirty mask for a NetworkBehaviour is zero, the OnDeserialize functions returns without reading any more
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// If the dirty mask is non-zero value, then the OnDeserialize function reads the values for the SyncVars that correspond to the dirty bits that are set
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// If there are SyncVar hook functions, those are invoked with the value read from the stream.
|
||||
/// </item>
|
||||
/// </list>
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
[DisallowMultipleComponent]
|
||||
[AddComponentMenu("Network/NetworkIdentity")]
|
||||
@ -51,29 +108,46 @@ public sealed class NetworkIdentity : MonoBehaviour
|
||||
{
|
||||
static readonly ILogger logger = LogFactory.GetLogger<NetworkIdentity>();
|
||||
|
||||
// configuration
|
||||
NetworkBehaviour[] networkBehavioursCache;
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if running as a client and this object was spawned by a server.
|
||||
/// <para>
|
||||
/// <b>IMPORTANT:</b> checking NetworkClient.active means that isClient is false in OnDestroy:
|
||||
/// </para>
|
||||
/// <c>
|
||||
/// public bool isClient => NetworkClient.active && netId != 0 && !serverOnly;
|
||||
/// </c>
|
||||
/// <para>
|
||||
/// but we need it in OnDestroy, e.g. when saving skillbars on quit. this
|
||||
/// works fine if we keep the UNET way of setting isClient manually.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// => fixes <see cref="https://github.com/vis2k/Mirror/issues/1475"/>
|
||||
/// </para>
|
||||
/// </summary>
|
||||
//
|
||||
// IMPORTANT: checking NetworkClient.active means that isClient is false in OnDestroy:
|
||||
// public bool isClient => NetworkClient.active && netId != 0 && !serverOnly;
|
||||
// but we need it in OnDestroy, e.g. when saving skillbars on quit. this
|
||||
// works fine if we keep the UNET way of setting isClient manually.
|
||||
// => fixes https://github.com/vis2k/Mirror/issues/1475
|
||||
/// <remarks>
|
||||
/// </remarks>
|
||||
public bool isClient { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if NetworkServer.active and server is not stopped.
|
||||
/// </summary>
|
||||
//
|
||||
// IMPORTANT: checking NetworkServer.active means that isServer is false in OnDestroy:
|
||||
// public bool isServer => NetworkServer.active && netId != 0;
|
||||
// but we need it in OnDestroy, e.g. when saving players on quit. this
|
||||
// works fine if we keep the UNET way of setting isServer manually.
|
||||
// => fixes https://github.com/vis2k/Mirror/issues/1484
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// <b>IMPORTANT:</b> checking NetworkServer.active means that isServer is false in OnDestroy:
|
||||
/// </para>
|
||||
/// <c>
|
||||
/// public bool isServer => NetworkServer.active && netId != 0;
|
||||
/// </c>
|
||||
/// <para>
|
||||
/// but we need it in OnDestroy, e.g. when saving players on quit. this
|
||||
/// works fine if we keep the UNET way of setting isServer manually.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// => fixes <see cref="https://github.com/vis2k/Mirror/issues/1484"/>
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public bool isServer { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
@ -169,7 +243,6 @@ void CreateNetworkBehavioursCache()
|
||||
}
|
||||
|
||||
|
||||
// NetworkProximityChecker caching
|
||||
NetworkVisibility visibilityCache;
|
||||
public NetworkVisibility visibility
|
||||
{
|
||||
@ -185,18 +258,29 @@ public NetworkVisibility visibility
|
||||
|
||||
[SerializeField, HideInInspector] string m_AssetId;
|
||||
|
||||
// the AssetId trick:
|
||||
// - ideally we would have a serialized 'Guid m_AssetId' but Unity can't
|
||||
// serialize it because Guid's internal bytes are private
|
||||
// - UNET used 'NetworkHash128' originally, with byte0, ..., byte16
|
||||
// which works, but it just unnecessary extra code
|
||||
// - using just the Guid string would work, but it's 32 chars long and
|
||||
// would then be sent over the network as 64 instead of 16 bytes
|
||||
// -> the solution is to serialize the string internally here and then
|
||||
// use the real 'Guid' type for everything else via .assetId
|
||||
|
||||
/// <summary>
|
||||
/// Unique identifier used to find the source assets when server spawns the on clients.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The AssetId trick:
|
||||
/// <list type="bullet">
|
||||
/// <item>
|
||||
/// Ideally we would have a serialized 'Guid m_AssetId' but Unity can't
|
||||
/// serialize it because Guid's internal bytes are private
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// UNET used 'NetworkHash128' originally, with byte0, ..., byte16
|
||||
/// which works, but it just unnecessary extra code
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// Using just the Guid string would work, but it's 32 chars long and
|
||||
/// would then be sent over the network as 64 instead of 16 bytes
|
||||
/// </item>
|
||||
/// </list>
|
||||
/// The solution is to serialize the string internally here and then
|
||||
/// use the real 'Guid' type for everything else via .assetId
|
||||
/// </remarks>
|
||||
public Guid assetId
|
||||
{
|
||||
get
|
||||
@ -242,7 +326,9 @@ internal set
|
||||
}
|
||||
}
|
||||
|
||||
// keep track of all sceneIds to detect scene duplicates
|
||||
/// <summary>
|
||||
/// Keep track of all sceneIds to detect scene duplicates
|
||||
/// </summary>
|
||||
static readonly Dictionary<ulong, NetworkIdentity> sceneIds = new Dictionary<ulong, NetworkIdentity>();
|
||||
|
||||
/// <summary>
|
||||
@ -252,7 +338,10 @@ internal set
|
||||
/// <returns>NetworkIdentity from the sceneIds dictionary</returns>
|
||||
public static NetworkIdentity GetSceneIdentity(ulong id) => sceneIds[id];
|
||||
|
||||
// used when adding players
|
||||
/// <summary>
|
||||
/// used when adding players
|
||||
/// </summary>
|
||||
/// <param name="conn"></param>
|
||||
internal void SetClientOwner(NetworkConnection conn)
|
||||
{
|
||||
// do nothing if it already has an owner
|
||||
@ -289,13 +378,18 @@ internal void SetClientOwner(NetworkConnection conn)
|
||||
/// </summary>
|
||||
public static ClientAuthorityCallback clientAuthorityCallback;
|
||||
|
||||
// this is used when a connection is destroyed, since the "observers" property is read-only
|
||||
/// <summary>
|
||||
/// this is used when a connection is destroyed, since the "observers" property is read-only
|
||||
/// </summary>
|
||||
/// <param name="conn"></param>
|
||||
internal void RemoveObserverInternal(NetworkConnection conn)
|
||||
{
|
||||
observers?.Remove(conn.connectionId);
|
||||
}
|
||||
|
||||
// hasSpawned should always be false before runtime
|
||||
/// <summary>
|
||||
/// hasSpawned should always be false before runtime
|
||||
/// </summary>
|
||||
[SerializeField, HideInInspector] bool hasSpawned;
|
||||
public bool SpawnedFromInstantiate { get; private set; }
|
||||
|
||||
@ -358,49 +452,100 @@ static uint GetRandomUInt()
|
||||
}
|
||||
}
|
||||
|
||||
// persistent sceneId assignment
|
||||
// (because scene objects have no persistent unique ID in Unity)
|
||||
//
|
||||
// original UNET used OnPostProcessScene to assign an index based on
|
||||
// FindObjectOfType<NetworkIdentity> order.
|
||||
// -> this didn't work because FindObjectOfType order isn't deterministic.
|
||||
// -> one workaround is to sort them by sibling paths, but it can still
|
||||
// get out of sync when we open scene2 in editor and we have
|
||||
// DontDestroyOnLoad objects that messed with the sibling index.
|
||||
//
|
||||
// we absolutely need a persistent id. challenges:
|
||||
// * it needs to be 0 for prefabs
|
||||
// => we set it to 0 in SetupIDs() if prefab!
|
||||
// * it needs to be only assigned in edit time, not at runtime because
|
||||
// only the objects that were in the scene since beginning should have
|
||||
// a scene id.
|
||||
// => Application.isPlaying check solves that
|
||||
// * it needs to detect duplicated sceneIds after duplicating scene
|
||||
// objects
|
||||
// => sceneIds dict takes care of that
|
||||
// * duplicating the whole scene file shouldn't result in duplicate
|
||||
// scene objects
|
||||
// => buildIndex is shifted into sceneId for that.
|
||||
// => if we have no scenes in build index then it doesn't matter
|
||||
// because by definition a build can't switch to other scenes
|
||||
// => if we do have scenes in build index then it will be != -1
|
||||
// note: the duplicated scene still needs to be opened once for it to
|
||||
// be set properly
|
||||
// * scene objects need the correct scene index byte even if the scene's
|
||||
// build index was changed or a duplicated scene wasn't opened yet.
|
||||
// => OnPostProcessScene is the only function that gets called for
|
||||
// each scene before runtime, so this is where we set the scene
|
||||
// byte.
|
||||
// * disabled scenes in build settings should result in same scene index
|
||||
// in editor and in build
|
||||
// => .gameObject.scene.buildIndex filters out disabled scenes by
|
||||
// default
|
||||
// * generated sceneIds absolutely need to set scene dirty and force the
|
||||
// user to resave.
|
||||
// => Undo.RecordObject does that perfectly.
|
||||
// * sceneIds should never be generated temporarily for unopened scenes
|
||||
// when building, otherwise editor and build get out of sync
|
||||
// => BuildPipeline.isBuildingPlayer check solves that
|
||||
/// <summary>
|
||||
/// Persistent sceneId assignment
|
||||
/// (because scene objects have no persistent unique ID in Unity)
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// Original UNET used OnPostProcessScene to assign an index based on
|
||||
/// FindObjectOfType{NetworkIdentity} order.
|
||||
/// <list type="bullet">
|
||||
/// <item>
|
||||
/// this didn't work because FindObjectOfType order isn't deterministic.
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// one workaround is to sort them by sibling paths, but it can still
|
||||
/// get out of sync when we open scene2 in editor and we have
|
||||
/// DontDestroyOnLoad objects that messed with the sibling index.
|
||||
/// </item>
|
||||
/// </list>
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// We absolutely need a persistent id. challenges:
|
||||
/// <list type="bullet">
|
||||
/// <item>
|
||||
/// It needs to be 0 for prefabs
|
||||
/// <para>
|
||||
/// => we set it to 0 in SetupIDs() if prefab!
|
||||
/// </para>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// It needs to be only assigned in edit time, not at runtime because
|
||||
/// only the objects that were in the scene since beginning should have
|
||||
/// a scene id.
|
||||
/// <para>
|
||||
/// => Application.isPlaying check solves that
|
||||
/// </para>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// It needs to detect duplicated sceneIds after duplicating scene
|
||||
/// objects
|
||||
/// <para>
|
||||
/// => sceneIds dict takes care of that
|
||||
/// </para>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// Duplicating the whole scene file shouldn't result in duplicate
|
||||
/// scene objects
|
||||
/// <para>
|
||||
/// => buildIndex is shifted into sceneId for that.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// => if we have no scenes in build index then it doesn't matter
|
||||
/// because by definition a build can't switch to other scenes
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// => if we do have scenes in build index then it will be != -1
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// note: the duplicated scene still needs to be opened once for it to
|
||||
/// be set properly
|
||||
/// </para>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// Scene objects need the correct scene index byte even if the scene's
|
||||
/// build index was changed or a duplicated scene wasn't opened yet.
|
||||
/// <para>
|
||||
/// => OnPostProcessScene is the only function that gets called for
|
||||
/// each scene before runtime, so this is where we set the scene
|
||||
/// byte.
|
||||
/// </para>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// Disabled scenes in build settings should result in same scene index
|
||||
/// in editor and in build
|
||||
/// <para>
|
||||
/// => .gameObject.scene.buildIndex filters out disabled scenes by default
|
||||
/// </para>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// Generated sceneIds absolutely need to set scene dirty and force the
|
||||
/// user to resave.
|
||||
/// <para>
|
||||
/// => Undo.RecordObject does that perfectly.
|
||||
/// </para>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// SceneIds should never be generated temporarily for unopened scenes
|
||||
/// when building, otherwise editor and build get out of sync
|
||||
/// <para>
|
||||
/// => BuildPipeline.isBuildingPlayer check solves that
|
||||
/// </para>
|
||||
/// </item>
|
||||
/// </list>
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
void AssignSceneID()
|
||||
{
|
||||
// we only ever assign sceneIds at edit time, never at runtime.
|
||||
@ -454,17 +599,33 @@ void AssignSceneID()
|
||||
sceneIds[sceneId] = this;
|
||||
}
|
||||
|
||||
// copy scene path hash into sceneId for scene objects.
|
||||
// this is the only way for scene file duplication to not contain
|
||||
// duplicate sceneIds as it seems.
|
||||
// -> sceneId before: 0x00000000AABBCCDD
|
||||
// -> then we clear the left 4 bytes, so that our 'OR' uses 0x00000000
|
||||
// -> then we OR the hash into the 0x00000000 part
|
||||
// -> buildIndex is not enough, because Editor and Build have different
|
||||
// build indices if there are disabled scenes in build settings, and
|
||||
// if no scene is in build settings then Editor and Build have
|
||||
// different indices too (Editor=0, Build=-1)
|
||||
// => ONLY USE THIS FROM POSTPROCESSSCENE!
|
||||
/// <summary>
|
||||
/// <para>
|
||||
/// Copy scene path hash into sceneId for scene objects.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// this is the only way for scene file duplication to not contain
|
||||
/// duplicate sceneIds as it seems.
|
||||
/// </para>
|
||||
/// <list type="bullet">
|
||||
/// <item>
|
||||
/// sceneId before: 0x00000000AABBCCDD
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// then we clear the left 4 bytes, so that our 'OR' uses 0x00000000
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// then we OR the hash into the 0x00000000 part
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// buildIndex is not enough, because Editor and Build have different
|
||||
/// build indices if there are disabled scenes in build settings, and
|
||||
/// if no scene is in build settings then Editor and Build have
|
||||
/// different indices too (Editor=0, Build=-1)
|
||||
/// </item>
|
||||
/// </list>
|
||||
/// <b>ONLY USE THIS FROM POSTPROCESSSCENE!</b>
|
||||
/// </summary>
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public void SetSceneIdSceneHashPartInternal()
|
||||
{
|
||||
@ -531,8 +692,10 @@ void SetupIDs()
|
||||
}
|
||||
#endif
|
||||
|
||||
// Unity will Destroy all networked objects on Scene Change, so we have to handle that here silently.
|
||||
// That means we cannot have any warning or logging in this method.
|
||||
/// <summary>
|
||||
/// Unity will Destroy all networked objects on Scene Change, so we have to handle that here silently.
|
||||
/// That means we cannot have any warning or logging in this method.
|
||||
/// </summary>
|
||||
void OnDestroy()
|
||||
{
|
||||
// Objects spawned from Instantiate are not allowed so are destroyed right away
|
||||
@ -744,10 +907,19 @@ internal void OnSetHostVisibility(bool visible)
|
||||
}
|
||||
}
|
||||
|
||||
// check if observer can be seen by connection.
|
||||
// * returns true if seen.
|
||||
// * returns true if we have no proximity checker, so by default all are
|
||||
// seen.
|
||||
/// <summary>
|
||||
/// check if observer can be seen by connection.
|
||||
/// <list type="bullet">
|
||||
/// <item>
|
||||
/// returns visibility.OnCheckObserver
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// returns true if we have no NetworkVisibility, default objects are visible
|
||||
/// </item>
|
||||
/// </list>
|
||||
/// </summary>
|
||||
/// <param name="conn"></param>
|
||||
/// <returns></returns>
|
||||
internal bool OnCheckObserver(NetworkConnection conn)
|
||||
{
|
||||
if (visibility != null)
|
||||
@ -785,11 +957,31 @@ internal void OnStopClient()
|
||||
}
|
||||
}
|
||||
|
||||
// vis2k: readstring bug prevention: https://issuetracker.unity3d.com/issues/unet-networkwriter-dot-write-causing-readstring-slash-readbytes-out-of-range-errors-in-clients
|
||||
// -> OnSerialize writes length,componentData,length,componentData,...
|
||||
// -> OnDeserialize carefully extracts each data, then deserializes each component with separate readers
|
||||
// -> it will be impossible to read too many or too few bytes in OnDeserialize
|
||||
// -> we can properly track down errors
|
||||
/// <summary>
|
||||
/// Serializes component and its lengths
|
||||
/// </summary>
|
||||
/// <param name="comp"></param>
|
||||
/// <param name="writer"></param>
|
||||
/// <param name="initialState"></param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// vis2k: readstring bug prevention:
|
||||
/// <see cref="https://issuetracker.unity3d.com/issues/unet-networkwriter-dot-write-causing-readstring-slash-readbytes-out-of-range-errors-in-clients"/>
|
||||
/// <list type="bullet">
|
||||
/// <item>
|
||||
/// OnSerialize writes length,componentData,length,componentData,...
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// OnDeserialize carefully extracts each data, then deserializes each component with separate readers
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// It will be impossible to read too many or too few bytes in OnDeserialize
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// We can properly track down errors
|
||||
/// </item>
|
||||
/// </list>
|
||||
/// </remarks>
|
||||
bool OnSerializeSafely(NetworkBehaviour comp, NetworkWriter writer, bool initialState)
|
||||
{
|
||||
// write placeholder length bytes
|
||||
@ -822,9 +1014,17 @@ bool OnSerializeSafely(NetworkBehaviour comp, NetworkWriter writer, bool initial
|
||||
return result;
|
||||
}
|
||||
|
||||
// serialize all components using dirtyComponentsMask
|
||||
// -> check ownerWritten/observersWritten to know if anything was written
|
||||
// We pass dirtyComponentsMask into this function so that we can check if any Components are dirty before creating writers
|
||||
/// <summary>
|
||||
/// serialize all components using dirtyComponentsMask
|
||||
/// <para>check ownerWritten/observersWritten to know if anything was written</para>
|
||||
/// <para>We pass dirtyComponentsMask into this function so that we can check if any Components are dirty before creating writers</para>
|
||||
/// </summary>
|
||||
/// <param name="initialState"></param>
|
||||
/// <param name="dirtyComponentsMask"></param>
|
||||
/// <param name="ownerWriter"></param>
|
||||
/// <param name="ownerWritten"></param>
|
||||
/// <param name="observersWriter"></param>
|
||||
/// <param name="observersWritten"></param>
|
||||
internal void OnSerializeAllSafely(bool initialState, ulong dirtyComponentsMask, NetworkWriter ownerWriter, out int ownerWritten, NetworkWriter observersWriter, out int observersWritten)
|
||||
{
|
||||
// clear 'written' variables
|
||||
@ -914,7 +1114,10 @@ internal ulong GetInitialComponentsMask()
|
||||
}
|
||||
|
||||
|
||||
// a mask that contains all the components with SyncMode.Observers
|
||||
/// <summary>
|
||||
/// a mask that contains all the components with SyncMode.Observers
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
internal ulong GetSyncModeObserversMask()
|
||||
{
|
||||
// loop through all components
|
||||
@ -988,7 +1191,14 @@ internal void OnDeserializeAllSafely(NetworkReader reader, bool initialState)
|
||||
}
|
||||
}
|
||||
|
||||
// helper function to handle SyncEvent/Command/Rpc
|
||||
/// <summary>
|
||||
/// Helper function to handle SyncEvent/Command/Rpc
|
||||
/// </summary>
|
||||
/// <param name="componentIndex"></param>
|
||||
/// <param name="functionHash"></param>
|
||||
/// <param name="invokeType"></param>
|
||||
/// <param name="reader"></param>
|
||||
/// <param name="senderConnection"></param>
|
||||
void HandleRemoteCall(int componentIndex, int functionHash, MirrorInvokeType invokeType, NetworkReader reader, NetworkConnectionToClient senderConnection = null)
|
||||
{
|
||||
// check if unity object has been destroyed
|
||||
@ -1013,19 +1223,35 @@ void HandleRemoteCall(int componentIndex, int functionHash, MirrorInvokeType inv
|
||||
}
|
||||
}
|
||||
|
||||
// happens on client
|
||||
/// <summary>
|
||||
/// Runs on client
|
||||
/// </summary>
|
||||
/// <param name="componentIndex"></param>
|
||||
/// <param name="eventHash"></param>
|
||||
/// <param name="reader"></param>
|
||||
internal void HandleSyncEvent(int componentIndex, int eventHash, NetworkReader reader)
|
||||
{
|
||||
HandleRemoteCall(componentIndex, eventHash, MirrorInvokeType.SyncEvent, reader);
|
||||
}
|
||||
|
||||
// happens on server
|
||||
/// <summary>
|
||||
/// Runs on server
|
||||
/// </summary>
|
||||
/// <param name="componentIndex"></param>
|
||||
/// <param name="cmdHash"></param>
|
||||
/// <param name="reader"></param>
|
||||
/// <param name="senderConnection"></param>
|
||||
internal void HandleCommand(int componentIndex, int cmdHash, NetworkReader reader, NetworkConnectionToClient senderConnection)
|
||||
{
|
||||
HandleRemoteCall(componentIndex, cmdHash, MirrorInvokeType.Command, reader, senderConnection);
|
||||
}
|
||||
|
||||
// happens on server
|
||||
/// <summary>
|
||||
/// Runs on server
|
||||
/// </summary>
|
||||
/// <param name="componentIndex"></param>
|
||||
/// <param name="cmdHash"></param>
|
||||
/// <returns></returns>
|
||||
internal CommandInfo GetCommandInfo(int componentIndex, int cmdHash)
|
||||
{
|
||||
// check if unity object has been destroyed
|
||||
@ -1048,7 +1274,12 @@ internal CommandInfo GetCommandInfo(int componentIndex, int cmdHash)
|
||||
}
|
||||
}
|
||||
|
||||
// happens on client
|
||||
/// <summary>
|
||||
/// Runs on client
|
||||
/// </summary>
|
||||
/// <param name="componentIndex"></param>
|
||||
/// <param name="rpcHash"></param>
|
||||
/// <param name="reader"></param>
|
||||
internal void HandleRPC(int componentIndex, int rpcHash, NetworkReader reader)
|
||||
{
|
||||
HandleRemoteCall(componentIndex, rpcHash, MirrorInvokeType.ClientRpc, reader);
|
||||
@ -1087,10 +1318,15 @@ internal void AddObserver(NetworkConnection conn)
|
||||
conn.AddToVisList(this);
|
||||
}
|
||||
|
||||
// helper function to call OnRebuildObservers in all components
|
||||
// -> HashSet is passed in so we can cache it!
|
||||
// -> returns true if we have a proxchecker, false otherwise
|
||||
// -> initialize is true on first rebuild, false on consecutive rebuilds
|
||||
/// <summary>
|
||||
/// Helper function to call OnRebuildObservers in all components
|
||||
/// <para>HashSet is passed in so we can cache it!</para>
|
||||
/// <para>Returns true if we have a NetworkVisibility, false otherwise</para>
|
||||
/// <para>Initialize is true on first rebuild, false on consecutive rebuilds</para>
|
||||
/// </summary>
|
||||
/// <param name="observersSet"></param>
|
||||
/// <param name="initialize"></param>
|
||||
/// <returns></returns>
|
||||
internal bool GetNewObservers(HashSet<NetworkConnection> observersSet, bool initialize)
|
||||
{
|
||||
observersSet.Clear();
|
||||
@ -1101,14 +1337,16 @@ internal bool GetNewObservers(HashSet<NetworkConnection> observersSet, bool init
|
||||
return true;
|
||||
}
|
||||
|
||||
// we have no proximity checker. return false to indicate that we
|
||||
// we have no NetworkVisibility. return false to indicate that we
|
||||
// should use the default implementation.
|
||||
return false;
|
||||
}
|
||||
|
||||
// helper function to add all server connections as observers.
|
||||
// this is used if none of the components provides their own
|
||||
// OnRebuildObservers function.
|
||||
/// <summary>
|
||||
/// Helper function to add all server connections as observers.
|
||||
/// This is used if none of the components provides their own
|
||||
/// OnRebuildObservers function.
|
||||
/// </summary>
|
||||
internal void AddAllReadyServerConnectionsToObservers()
|
||||
{
|
||||
// add all server connections
|
||||
@ -1128,7 +1366,8 @@ internal void AddAllReadyServerConnectionsToObservers()
|
||||
static readonly HashSet<NetworkConnection> newObservers = new HashSet<NetworkConnection>();
|
||||
|
||||
/// <summary>
|
||||
/// This causes the set of players that can see this object to be rebuild. The OnRebuildObservers callback function will be invoked on each NetworkBehaviour.
|
||||
/// This causes the set of players that can see this object to be rebuild.
|
||||
/// The OnRebuildObservers callback function will be invoked on each NetworkBehaviour.
|
||||
/// </summary>
|
||||
/// <param name="initialize">True if this is the first time.</param>
|
||||
public void RebuildObservers(bool initialize)
|
||||
@ -1151,8 +1390,7 @@ public void RebuildObservers(bool initialize)
|
||||
newObservers.Add(connectionToClient);
|
||||
}
|
||||
|
||||
// if no component implemented OnRebuildObservers, then add all
|
||||
// server connections.
|
||||
// if no NetworkVisibility component, then add all server connections.
|
||||
if (!rebuildOverwritten)
|
||||
{
|
||||
// only add all connections when rebuilding the first time.
|
||||
@ -1308,9 +1546,12 @@ public void RemoveClientAuthority()
|
||||
}
|
||||
}
|
||||
|
||||
// marks the identity for future reset, this is because we cant reset the identity during destroy
|
||||
// as people might want to be able to read the members inside OnDestroy(), and we have no way
|
||||
// of invoking reset after OnDestroy is called.
|
||||
|
||||
/// <summary>
|
||||
/// Marks the identity for future reset, this is because we cant reset the identity during destroy
|
||||
/// as people might want to be able to read the members inside OnDestroy(), and we have no way
|
||||
/// of invoking reset after OnDestroy is called.
|
||||
/// </summary>
|
||||
internal void Reset()
|
||||
{
|
||||
// make sure to call this before networkBehavioursCache is cleared below
|
||||
@ -1329,7 +1570,9 @@ internal void Reset()
|
||||
ClearObservers();
|
||||
}
|
||||
|
||||
// invoked by NetworkServer during Update()
|
||||
/// <summary>
|
||||
/// Invoked by NetworkServer.Update during LateUpdate
|
||||
/// </summary>
|
||||
internal void ServerUpdate()
|
||||
{
|
||||
if (observers != null && observers.Count > 0)
|
||||
@ -1397,7 +1640,9 @@ void SendUpdateVarsMessage(ulong dirtyComponentsMask)
|
||||
}
|
||||
|
||||
|
||||
// clear all component's dirty bits no matter what
|
||||
/// <summary>
|
||||
/// clear all component's dirty bits no matter what
|
||||
/// </summary>
|
||||
internal void ClearAllComponentsDirtyBits()
|
||||
{
|
||||
foreach (NetworkBehaviour comp in NetworkBehaviours)
|
||||
@ -1406,8 +1651,10 @@ internal void ClearAllComponentsDirtyBits()
|
||||
}
|
||||
}
|
||||
|
||||
// clear only dirty component's dirty bits. ignores components which
|
||||
// may be dirty but not ready to be synced yet (because of syncInterval)
|
||||
/// <summary>
|
||||
/// Clear only dirty component's dirty bits. ignores components which
|
||||
/// may be dirty but not ready to be synced yet (because of syncInterval)
|
||||
/// </summary>
|
||||
internal void ClearDirtyComponentsDirtyBits()
|
||||
{
|
||||
foreach (NetworkBehaviour comp in NetworkBehaviours)
|
||||
|
@ -26,9 +26,6 @@ public static class NetworkServer
|
||||
/// <summary>
|
||||
/// The connection to the host mode client (if any).
|
||||
/// </summary>
|
||||
// original HLAPI has .localConnections list with only m_LocalConnection in it
|
||||
// (for backwards compatibility because they removed the real localConnections list a while ago)
|
||||
// => removed it for easier code. use .localConnection now!
|
||||
public static NetworkConnectionToClient localConnection { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
@ -75,12 +72,14 @@ public static class NetworkServer
|
||||
/// </summary>
|
||||
public static float disconnectInactiveTimeout = 60f;
|
||||
|
||||
// cache the Send(connectionIds) list to avoid allocating each time
|
||||
/// <summary>
|
||||
/// cache the Send(connectionIds) list to avoid allocating each time
|
||||
/// </summary>
|
||||
static readonly List<int> connectionIdsCache = new List<int>();
|
||||
|
||||
// Deprecated 02/23/2020
|
||||
/// <summary>
|
||||
/// Reset the NetworkServer singleton.
|
||||
/// <para>Deprecated 02/23/2020</para>
|
||||
/// </summary>
|
||||
[Obsolete("NetworkServer.Reset was used to reset the singleton, but all it does is set active to false ever since we made NetworkServer static. Use StopServer to stop the server, or Shutdown to fully reset the server.")]
|
||||
public static void Reset()
|
||||
@ -215,7 +214,10 @@ public static bool RemoveConnection(int connectionId)
|
||||
return connections.Remove(connectionId);
|
||||
}
|
||||
|
||||
// called by LocalClient to add itself. dont call directly.
|
||||
/// <summary>
|
||||
/// called by LocalClient to add itself. dont call directly.
|
||||
/// </summary>
|
||||
/// <param name="conn"></param>
|
||||
internal static void SetLocalConnection(ULocalConnectionToClient conn)
|
||||
{
|
||||
if (localConnection != null)
|
||||
@ -251,8 +253,15 @@ public static void ActivateHostScene()
|
||||
}
|
||||
}
|
||||
|
||||
// this is like SendToReady - but it doesn't check the ready flag on the connection.
|
||||
// this is used for ObjectDestroy messages.
|
||||
|
||||
/// <summary>
|
||||
/// this is like SendToReady - but it doesn't check the ready flag on the connection.
|
||||
/// this is used for ObjectDestroy messages.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="identity"></param>
|
||||
/// <param name="msg"></param>
|
||||
/// <param name="channelId"></param>
|
||||
static void SendToObservers<T>(NetworkIdentity identity, T msg, int channelId = Channels.DefaultReliable) where T : IMessageBase
|
||||
{
|
||||
if (logger.LogEnabled()) logger.Log("Server.SendToObservers id:" + typeof(T));
|
||||
@ -471,7 +480,10 @@ public static void DisconnectAllConnections()
|
||||
connections.Clear();
|
||||
}
|
||||
|
||||
// The user should never need to pump the update loop manually
|
||||
/// <summary>
|
||||
/// Called from NetworkManager in LateUpdate
|
||||
/// <para>The user should never need to pump the update loop manually</para>
|
||||
/// </summary>
|
||||
public static void Update()
|
||||
{
|
||||
if (!active)
|
||||
@ -949,16 +961,20 @@ public static void SetClientNotReady(NetworkConnection conn)
|
||||
}
|
||||
}
|
||||
|
||||
// default ready handler.
|
||||
/// <summary>
|
||||
/// default ready handler.
|
||||
/// </summary>
|
||||
/// <param name="conn"></param>
|
||||
/// <param name="msg"></param>
|
||||
static void OnClientReadyMessage(NetworkConnection conn, ReadyMessage msg)
|
||||
{
|
||||
if (logger.LogEnabled()) logger.Log("Default handler for ready message from " + conn);
|
||||
SetClientReady(conn);
|
||||
}
|
||||
|
||||
// Deprecated 5/2/2020
|
||||
/// <summary>
|
||||
/// Obsolete: Removed as a security risk. Use <see cref="RemovePlayerForConnection(NetworkConnection, bool)">NetworkServer.RemovePlayerForConnection</see> instead.
|
||||
/// <para>Deprecated 5/2/2020</para>
|
||||
/// </summary>
|
||||
[EditorBrowsable(EditorBrowsableState.Never), Obsolete("Removed as a security risk. Use NetworkServer.RemovePlayerForConnection(NetworkConnection conn, bool keepAuthority = false) instead", true)]
|
||||
static void OnRemovePlayerMessage(NetworkConnection conn, RemovePlayerMessage msg) { }
|
||||
@ -985,7 +1001,11 @@ public static void RemovePlayerForConnection(NetworkConnection conn, bool destro
|
||||
}
|
||||
}
|
||||
|
||||
// Handle command from specific player, this could be one of multiple players on a single client
|
||||
/// <summary>
|
||||
/// Handle command from specific player, this could be one of multiple players on a single client
|
||||
/// </summary>
|
||||
/// <param name="conn"></param>
|
||||
/// <param name="msg"></param>
|
||||
static void OnCommandMessage(NetworkConnection conn, CommandMessage msg)
|
||||
{
|
||||
if (!NetworkIdentity.spawned.TryGetValue(msg.netId, out NetworkIdentity identity))
|
||||
|
Loading…
Reference in New Issue
Block a user