2018-06-07 13:41:08 +00:00
#if ENABLE_UNET
using System ;
using System.Collections.Generic ;
using UnityEngine.Networking.NetworkSystem ;
namespace UnityEngine.Networking
{
public class ClientScene
{
static List < PlayerController > s_LocalPlayers = new List < PlayerController > ( ) ;
static NetworkConnection s_ReadyConnection ;
static Dictionary < NetworkSceneId , NetworkIdentity > s_SpawnableObjects ;
static bool s_IsReady ;
static bool s_IsSpawnFinished ;
static NetworkScene s_NetworkScene = new NetworkScene ( ) ;
// static message objects to avoid runtime-allocations
static ObjectSpawnSceneMessage s_ObjectSpawnSceneMessage = new ObjectSpawnSceneMessage ( ) ;
static ObjectSpawnFinishedMessage s_ObjectSpawnFinishedMessage = new ObjectSpawnFinishedMessage ( ) ;
static ObjectDestroyMessage s_ObjectDestroyMessage = new ObjectDestroyMessage ( ) ;
static ObjectSpawnMessage s_ObjectSpawnMessage = new ObjectSpawnMessage ( ) ;
static OwnerMessage s_OwnerMessage = new OwnerMessage ( ) ;
static ClientAuthorityMessage s_ClientAuthorityMessage = new ClientAuthorityMessage ( ) ;
#if ENABLE_UNET_HOST_MIGRATION
public const int ReconnectIdInvalid = - 1 ;
public const int ReconnectIdHost = 0 ;
static int s_ReconnectId = ReconnectIdInvalid ;
static PeerInfoMessage [ ] s_Peers ;
static bool hasMigrationPending ( ) { return s_ReconnectId ! = ReconnectIdInvalid ; }
static public void SetReconnectId ( int newReconnectId , PeerInfoMessage [ ] peers )
{
s_ReconnectId = newReconnectId ;
s_Peers = peers ;
if ( LogFilter . logDebug ) { Debug . Log ( "ClientScene::SetReconnectId: " + newReconnectId ) ; }
}
#endif
static internal void SetNotReady ( )
{
s_IsReady = false ;
}
struct PendingOwner
{
public NetworkInstanceId netId ;
public short playerControllerId ;
}
static List < PendingOwner > s_PendingOwnerIds = new List < PendingOwner > ( ) ;
public static List < PlayerController > localPlayers { get { return s_LocalPlayers ; } }
public static bool ready { get { return s_IsReady ; } }
public static NetworkConnection readyConnection { get { return s_ReadyConnection ; } }
#if ENABLE_UNET_HOST_MIGRATION
public static int reconnectId { get { return s_ReconnectId ; } }
#endif
//NOTE: spawn handlers, prefabs and local objects now live in NetworkScene
public static Dictionary < NetworkInstanceId , NetworkIdentity > objects { get { return s_NetworkScene . localObjects ; } }
public static Dictionary < NetworkHash128 , GameObject > prefabs { get { return NetworkScene . guidToPrefab ; } }
public static Dictionary < NetworkSceneId , NetworkIdentity > spawnableObjects { get { return s_SpawnableObjects ; } }
internal static void Shutdown ( )
{
s_NetworkScene . Shutdown ( ) ;
s_LocalPlayers = new List < PlayerController > ( ) ;
s_PendingOwnerIds = new List < PendingOwner > ( ) ;
s_SpawnableObjects = null ;
s_ReadyConnection = null ;
s_IsReady = false ;
s_IsSpawnFinished = false ;
#if ENABLE_UNET_HOST_MIGRATION
s_ReconnectId = ReconnectIdInvalid ;
#endif
NetworkTransport . Shutdown ( ) ;
NetworkTransport . Init ( ) ;
}
internal static bool GetPlayerController ( short playerControllerId , out PlayerController player )
{
player = null ;
if ( playerControllerId > = localPlayers . Count )
{
if ( LogFilter . logWarn ) { Debug . Log ( "ClientScene::GetPlayer: no local player found for: " + playerControllerId ) ; }
return false ;
}
if ( localPlayers [ playerControllerId ] = = null )
{
if ( LogFilter . logWarn ) { Debug . LogWarning ( "ClientScene::GetPlayer: local player is null for: " + playerControllerId ) ; }
return false ;
}
player = localPlayers [ playerControllerId ] ;
return player . gameObject ! = null ;
}
// this is called from message handler for Owner message
internal static void InternalAddPlayer ( NetworkIdentity view , short playerControllerId )
{
if ( LogFilter . logDebug ) { Debug . LogWarning ( "ClientScene::InternalAddPlayer: playerControllerId : " + playerControllerId ) ; }
if ( playerControllerId > = s_LocalPlayers . Count )
{
if ( LogFilter . logWarn ) { Debug . LogWarning ( "ClientScene::InternalAddPlayer: playerControllerId higher than expected: " + playerControllerId ) ; }
while ( playerControllerId > = s_LocalPlayers . Count )
{
s_LocalPlayers . Add ( new PlayerController ( ) ) ;
}
}
// NOTE: It can be "normal" when changing scenes for the player to be destroyed and recreated.
// But, the player structures are not cleaned up, we'll just replace the old player
var newPlayer = new PlayerController { gameObject = view . gameObject , playerControllerId = playerControllerId , unetView = view } ;
s_LocalPlayers [ playerControllerId ] = newPlayer ;
2018-06-08 12:23:59 +00:00
if ( s_ReadyConnection = = null )
{
if ( LogFilter . logWarn ) { Debug . LogWarning ( "No ready connection found for setting player controller during InternalAddPlayer" ) ; }
}
else
{
s_ReadyConnection . SetPlayerController ( newPlayer ) ;
}
2018-06-07 13:41:08 +00:00
}
// use this if already ready
public static bool AddPlayer ( short playerControllerId )
{
return AddPlayer ( null , playerControllerId ) ;
}
// use this to implicitly become ready
public static bool AddPlayer ( NetworkConnection readyConn , short playerControllerId )
{
return AddPlayer ( readyConn , playerControllerId , null ) ;
}
// use this to implicitly become ready
public static bool AddPlayer ( NetworkConnection readyConn , short playerControllerId , MessageBase extraMessage )
{
if ( playerControllerId < 0 )
{
if ( LogFilter . logError ) { Debug . LogError ( "ClientScene::AddPlayer: playerControllerId of " + playerControllerId + " is negative" ) ; }
return false ;
}
if ( playerControllerId > PlayerController . MaxPlayersPerClient )
{
if ( LogFilter . logError ) { Debug . LogError ( "ClientScene::AddPlayer: playerControllerId of " + playerControllerId + " is too high, max is " + PlayerController . MaxPlayersPerClient ) ; }
return false ;
}
if ( playerControllerId > PlayerController . MaxPlayersPerClient / 2 )
{
if ( LogFilter . logWarn ) { Debug . LogWarning ( "ClientScene::AddPlayer: playerControllerId of " + playerControllerId + " is unusually high" ) ; }
}
// fill out local players array
while ( playerControllerId > = s_LocalPlayers . Count )
{
s_LocalPlayers . Add ( new PlayerController ( ) ) ;
}
// ensure valid ready connection
if ( readyConn = = null )
{
if ( ! s_IsReady )
{
if ( LogFilter . logError ) { Debug . LogError ( "Must call AddPlayer() with a connection the first time to become ready." ) ; }
return false ;
}
}
else
{
s_IsReady = true ;
s_ReadyConnection = readyConn ;
}
PlayerController existingPlayerController ;
if ( s_ReadyConnection . GetPlayerController ( playerControllerId , out existingPlayerController ) )
{
if ( existingPlayerController . IsValid & & existingPlayerController . gameObject ! = null )
{
if ( LogFilter . logError ) { Debug . LogError ( "ClientScene::AddPlayer: playerControllerId of " + playerControllerId + " already in use." ) ; }
return false ;
}
}
if ( LogFilter . logDebug ) { Debug . Log ( "ClientScene::AddPlayer() for ID " + playerControllerId + " called with connection [" + s_ReadyConnection + "]" ) ; }
#if ENABLE_UNET_HOST_MIGRATION
if ( ! hasMigrationPending ( ) )
{
#endif
var msg = new AddPlayerMessage ( ) ;
msg . playerControllerId = playerControllerId ;
if ( extraMessage ! = null )
{
var writer = new NetworkWriter ( ) ;
extraMessage . Serialize ( writer ) ;
msg . msgData = writer . ToArray ( ) ;
msg . msgSize = writer . Position ;
}
s_ReadyConnection . Send ( MsgType . AddPlayer , msg ) ;
#if ENABLE_UNET_HOST_MIGRATION
}
else
{
return SendReconnectMessage ( extraMessage ) ;
}
#endif
return true ;
}
#if ENABLE_UNET_HOST_MIGRATION
public static bool SendReconnectMessage ( MessageBase extraMessage )
{
if ( ! hasMigrationPending ( ) )
return false ;
if ( LogFilter . logDebug ) { Debug . Log ( "ClientScene::AddPlayer reconnect " + s_ReconnectId ) ; }
if ( s_Peers = = null )
{
SetReconnectId ( ReconnectIdInvalid , null ) ;
if ( LogFilter . logError )
{
Debug . LogError ( "ClientScene::AddPlayer: reconnecting, but no peers." ) ;
}
return false ;
}
// reconnect all the players
for ( int i = 0 ; i < s_Peers . Length ; i + + )
{
var peer = s_Peers [ i ] ;
if ( peer . playerIds = = null )
{
// this could be empty if this peer had no players
continue ;
}
if ( peer . connectionId = = s_ReconnectId )
{
for ( int pid = 0 ; pid < peer . playerIds . Length ; pid + + )
{
var msg = new ReconnectMessage ( ) ;
msg . oldConnectionId = s_ReconnectId ;
msg . netId = peer . playerIds [ pid ] . netId ;
msg . playerControllerId = peer . playerIds [ pid ] . playerControllerId ;
if ( extraMessage ! = null )
{
var writer = new NetworkWriter ( ) ;
extraMessage . Serialize ( writer ) ;
msg . msgData = writer . ToArray ( ) ;
msg . msgSize = writer . Position ;
}
s_ReadyConnection . Send ( MsgType . ReconnectPlayer , msg ) ;
}
}
}
// this should only be done once.
SetReconnectId ( ReconnectIdInvalid , null ) ;
return true ;
}
#endif
public static bool RemovePlayer ( short playerControllerId )
{
if ( LogFilter . logDebug ) { Debug . Log ( "ClientScene::RemovePlayer() for ID " + playerControllerId + " called with connection [" + s_ReadyConnection + "]" ) ; }
PlayerController playerController ;
if ( s_ReadyConnection . GetPlayerController ( playerControllerId , out playerController ) )
{
var msg = new RemovePlayerMessage ( ) ;
msg . playerControllerId = playerControllerId ;
s_ReadyConnection . Send ( MsgType . RemovePlayer , msg ) ;
s_ReadyConnection . RemovePlayerController ( playerControllerId ) ;
s_LocalPlayers [ playerControllerId ] = new PlayerController ( ) ;
Object . Destroy ( playerController . gameObject ) ;
return true ;
}
if ( LogFilter . logError ) { Debug . LogError ( "Failed to find player ID " + playerControllerId ) ; }
return false ;
}
public static bool Ready ( NetworkConnection conn )
{
if ( s_IsReady )
{
if ( LogFilter . logError ) { Debug . LogError ( "A connection has already been set as ready. There can only be one." ) ; }
return false ;
}
if ( LogFilter . logDebug ) { Debug . Log ( "ClientScene::Ready() called with connection [" + conn + "]" ) ; }
if ( conn ! = null )
{
var msg = new ReadyMessage ( ) ;
conn . Send ( MsgType . Ready , msg ) ;
s_IsReady = true ;
s_ReadyConnection = conn ;
s_ReadyConnection . isReady = true ;
return true ;
}
if ( LogFilter . logError ) { Debug . LogError ( "Ready() called with invalid connection object: conn=null" ) ; }
return false ;
}
static public NetworkClient ConnectLocalServer ( )
{
var newClient = new LocalClient ( ) ;
NetworkServer . instance . ActivateLocalClientScene ( ) ;
newClient . InternalConnectLocalServer ( true ) ;
return newClient ;
}
#if ENABLE_UNET_HOST_MIGRATION
static internal NetworkClient ReconnectLocalServer ( )
{
LocalClient newClient = new LocalClient ( ) ;
NetworkServer . instance . ActivateLocalClientScene ( ) ;
newClient . InternalConnectLocalServer ( false ) ;
return newClient ;
}
static internal void ClearLocalPlayers ( )
{
s_LocalPlayers . Clear ( ) ;
}
#endif
static internal void HandleClientDisconnect ( NetworkConnection conn )
{
if ( s_ReadyConnection = = conn & & s_IsReady )
{
s_IsReady = false ;
s_ReadyConnection = null ;
}
}
internal static void PrepareToSpawnSceneObjects ( )
{
//NOTE: what is there are already objects in this dict?! should we merge with them?
s_SpawnableObjects = new Dictionary < NetworkSceneId , NetworkIdentity > ( ) ;
var uvs = Resources . FindObjectsOfTypeAll < NetworkIdentity > ( ) ;
for ( int i = 0 ; i < uvs . Length ; i + + )
{
var uv = uvs [ i ] ;
if ( uv . gameObject . activeSelf )
{
// already active, cannot spawn it
continue ;
}
if ( uv . gameObject . hideFlags = = HideFlags . NotEditable | | uv . gameObject . hideFlags = = HideFlags . HideAndDontSave )
continue ;
if ( uv . sceneId . IsEmpty ( ) )
continue ;
s_SpawnableObjects [ uv . sceneId ] = uv ;
if ( LogFilter . logDebug ) { Debug . Log ( "ClientScene::PrepareSpawnObjects sceneId:" + uv . sceneId ) ; }
}
}
internal static NetworkIdentity SpawnSceneObject ( NetworkSceneId sceneId )
{
if ( s_SpawnableObjects . ContainsKey ( sceneId ) )
{
NetworkIdentity foundId = s_SpawnableObjects [ sceneId ] ;
s_SpawnableObjects . Remove ( sceneId ) ;
return foundId ;
}
return null ;
}
static internal void RegisterSystemHandlers ( NetworkClient client , bool localClient )
{
if ( localClient )
{
client . RegisterHandlerSafe ( MsgType . ObjectDestroy , OnLocalClientObjectDestroy ) ;
client . RegisterHandlerSafe ( MsgType . ObjectHide , OnLocalClientObjectHide ) ;
client . RegisterHandlerSafe ( MsgType . ObjectSpawn , OnLocalClientObjectSpawn ) ;
client . RegisterHandlerSafe ( MsgType . ObjectSpawnScene , OnLocalClientObjectSpawnScene ) ;
client . RegisterHandlerSafe ( MsgType . LocalClientAuthority , OnClientAuthority ) ;
}
else
{
// LocalClient shares the sim/scene with the server, no need for these events
client . RegisterHandlerSafe ( MsgType . ObjectSpawn , OnObjectSpawn ) ;
client . RegisterHandlerSafe ( MsgType . ObjectSpawnScene , OnObjectSpawnScene ) ;
client . RegisterHandlerSafe ( MsgType . SpawnFinished , OnObjectSpawnFinished ) ;
client . RegisterHandlerSafe ( MsgType . ObjectDestroy , OnObjectDestroy ) ;
client . RegisterHandlerSafe ( MsgType . ObjectHide , OnObjectDestroy ) ;
client . RegisterHandlerSafe ( MsgType . UpdateVars , OnUpdateVarsMessage ) ;
client . RegisterHandlerSafe ( MsgType . Owner , OnOwnerMessage ) ;
client . RegisterHandlerSafe ( MsgType . SyncList , OnSyncListMessage ) ;
client . RegisterHandlerSafe ( MsgType . Animation , NetworkAnimator . OnAnimationClientMessage ) ;
client . RegisterHandlerSafe ( MsgType . AnimationParameters , NetworkAnimator . OnAnimationParametersClientMessage ) ;
client . RegisterHandlerSafe ( MsgType . LocalClientAuthority , OnClientAuthority ) ;
}
client . RegisterHandlerSafe ( MsgType . Rpc , OnRPCMessage ) ;
client . RegisterHandlerSafe ( MsgType . SyncEvent , OnSyncEventMessage ) ;
client . RegisterHandlerSafe ( MsgType . AnimationTrigger , NetworkAnimator . OnAnimationTriggerClientMessage ) ;
}
// ------------------------ NetworkScene pass-throughs ---------------------
static internal string GetStringForAssetId ( NetworkHash128 assetId )
{
GameObject prefab ;
if ( NetworkScene . GetPrefab ( assetId , out prefab ) )
{
return prefab . name ;
}
SpawnDelegate handler ;
if ( NetworkScene . GetSpawnHandler ( assetId , out handler ) )
{
return handler . GetMethodName ( ) ;
}
return "unknown" ;
}
// this assigns the newAssetId to the prefab. This is for registering dynamically created game objects for already know assetIds.
static public void RegisterPrefab ( GameObject prefab , NetworkHash128 newAssetId )
{
NetworkScene . RegisterPrefab ( prefab , newAssetId ) ;
}
static public void RegisterPrefab ( GameObject prefab )
{
NetworkScene . RegisterPrefab ( prefab ) ;
}
static public void RegisterPrefab ( GameObject prefab , SpawnDelegate spawnHandler , UnSpawnDelegate unspawnHandler )
{
NetworkScene . RegisterPrefab ( prefab , spawnHandler , unspawnHandler ) ;
}
static public void UnregisterPrefab ( GameObject prefab )
{
NetworkScene . UnregisterPrefab ( prefab ) ;
}
static public void RegisterSpawnHandler ( NetworkHash128 assetId , SpawnDelegate spawnHandler , UnSpawnDelegate unspawnHandler )
{
NetworkScene . RegisterSpawnHandler ( assetId , spawnHandler , unspawnHandler ) ;
}
static public void UnregisterSpawnHandler ( NetworkHash128 assetId )
{
NetworkScene . UnregisterSpawnHandler ( assetId ) ;
}
static public void ClearSpawners ( )
{
NetworkScene . ClearSpawners ( ) ;
}
static public void DestroyAllClientObjects ( )
{
s_NetworkScene . DestroyAllClientObjects ( ) ;
}
static public void SetLocalObject ( NetworkInstanceId netId , GameObject obj )
{
// if still receiving initial state, dont set isClient
s_NetworkScene . SetLocalObject ( netId , obj , s_IsSpawnFinished , false ) ;
}
static public GameObject FindLocalObject ( NetworkInstanceId netId )
{
return s_NetworkScene . FindLocalObject ( netId ) ;
}
static void ApplySpawnPayload ( NetworkIdentity uv , Vector3 position , byte [ ] payload , NetworkInstanceId netId , GameObject newGameObject )
{
if ( ! uv . gameObject . activeSelf )
{
uv . gameObject . SetActive ( true ) ;
}
uv . transform . position = position ;
if ( payload ! = null & & payload . Length > 0 )
{
var payloadReader = new NetworkReader ( payload ) ;
uv . OnUpdateVars ( payloadReader , true ) ;
}
if ( newGameObject = = null )
{
return ;
}
newGameObject . SetActive ( true ) ;
uv . SetNetworkInstanceId ( netId ) ;
SetLocalObject ( netId , newGameObject ) ;
// objects spawned as part of initial state are started on a second pass
if ( s_IsSpawnFinished )
{
uv . OnStartClient ( ) ;
CheckForOwner ( uv ) ;
}
}
static void OnObjectSpawn ( NetworkMessage netMsg )
{
netMsg . ReadMessage ( s_ObjectSpawnMessage ) ;
if ( ! s_ObjectSpawnMessage . assetId . IsValid ( ) )
{
if ( LogFilter . logError ) { Debug . LogError ( "OnObjSpawn netId: " + s_ObjectSpawnMessage . netId + " has invalid asset Id" ) ; }
return ;
}
if ( LogFilter . logDebug ) { Debug . Log ( "Client spawn handler instantiating [netId:" + s_ObjectSpawnMessage . netId + " asset ID:" + s_ObjectSpawnMessage . assetId + " pos:" + s_ObjectSpawnMessage . position + "]" ) ; }
#if UNITY_EDITOR
UnityEditor . NetworkDetailStats . IncrementStat (
UnityEditor . NetworkDetailStats . NetworkDirection . Incoming ,
MsgType . ObjectSpawn , GetStringForAssetId ( s_ObjectSpawnMessage . assetId ) , 1 ) ;
#endif
NetworkIdentity localNetworkIdentity ;
if ( s_NetworkScene . GetNetworkIdentity ( s_ObjectSpawnMessage . netId , out localNetworkIdentity ) )
{
// this object already exists (was in the scene), just apply the update to existing object
ApplySpawnPayload ( localNetworkIdentity , s_ObjectSpawnMessage . position , s_ObjectSpawnMessage . payload , s_ObjectSpawnMessage . netId , null ) ;
return ;
}
GameObject prefab ;
SpawnDelegate handler ;
if ( NetworkScene . GetPrefab ( s_ObjectSpawnMessage . assetId , out prefab ) )
{
var obj = ( GameObject ) Object . Instantiate ( prefab , s_ObjectSpawnMessage . position , s_ObjectSpawnMessage . rotation ) ;
if ( LogFilter . logDebug )
{
Debug . Log ( "Client spawn handler instantiating [netId:" + s_ObjectSpawnMessage . netId + " asset ID:" + s_ObjectSpawnMessage . assetId + " pos:" + s_ObjectSpawnMessage . position + " rotation: " + s_ObjectSpawnMessage . rotation + "]" ) ;
}
localNetworkIdentity = obj . GetComponent < NetworkIdentity > ( ) ;
if ( localNetworkIdentity = = null )
{
if ( LogFilter . logError ) { Debug . LogError ( "Client object spawned for " + s_ObjectSpawnMessage . assetId + " does not have a NetworkIdentity" ) ; }
return ;
}
localNetworkIdentity . Reset ( ) ;
ApplySpawnPayload ( localNetworkIdentity , s_ObjectSpawnMessage . position , s_ObjectSpawnMessage . payload , s_ObjectSpawnMessage . netId , obj ) ;
}
// lookup registered factory for type:
else if ( NetworkScene . GetSpawnHandler ( s_ObjectSpawnMessage . assetId , out handler ) )
{
GameObject obj = handler ( s_ObjectSpawnMessage . position , s_ObjectSpawnMessage . assetId ) ;
if ( obj = = null )
{
if ( LogFilter . logWarn ) { Debug . LogWarning ( "Client spawn handler for " + s_ObjectSpawnMessage . assetId + " returned null" ) ; }
return ;
}
localNetworkIdentity = obj . GetComponent < NetworkIdentity > ( ) ;
if ( localNetworkIdentity = = null )
{
if ( LogFilter . logError ) { Debug . LogError ( "Client object spawned for " + s_ObjectSpawnMessage . assetId + " does not have a network identity" ) ; }
return ;
}
localNetworkIdentity . Reset ( ) ;
localNetworkIdentity . SetDynamicAssetId ( s_ObjectSpawnMessage . assetId ) ;
ApplySpawnPayload ( localNetworkIdentity , s_ObjectSpawnMessage . position , s_ObjectSpawnMessage . payload , s_ObjectSpawnMessage . netId , obj ) ;
}
else
{
if ( LogFilter . logError ) { Debug . LogError ( "Failed to spawn server object, did you forget to add it to the NetworkManager? assetId=" + s_ObjectSpawnMessage . assetId + " netId=" + s_ObjectSpawnMessage . netId ) ; }
}
}
static void OnObjectSpawnScene ( NetworkMessage netMsg )
{
netMsg . ReadMessage ( s_ObjectSpawnSceneMessage ) ;
if ( LogFilter . logDebug ) { Debug . Log ( "Client spawn scene handler instantiating [netId:" + s_ObjectSpawnSceneMessage . netId + " sceneId:" + s_ObjectSpawnSceneMessage . sceneId + " pos:" + s_ObjectSpawnSceneMessage . position ) ; }
#if UNITY_EDITOR
UnityEditor . NetworkDetailStats . IncrementStat (
UnityEditor . NetworkDetailStats . NetworkDirection . Incoming ,
MsgType . ObjectSpawnScene , "sceneId" , 1 ) ;
#endif
NetworkIdentity localNetworkIdentity ;
if ( s_NetworkScene . GetNetworkIdentity ( s_ObjectSpawnSceneMessage . netId , out localNetworkIdentity ) )
{
// this object already exists (was in the scene)
ApplySpawnPayload ( localNetworkIdentity , s_ObjectSpawnSceneMessage . position , s_ObjectSpawnSceneMessage . payload , s_ObjectSpawnSceneMessage . netId , localNetworkIdentity . gameObject ) ;
return ;
}
NetworkIdentity spawnedId = SpawnSceneObject ( s_ObjectSpawnSceneMessage . sceneId ) ;
if ( spawnedId = = null )
{
2018-06-08 08:59:32 +00:00
if ( LogFilter . logError )
{
Debug . LogError ( "Spawn scene object not found for " + s_ObjectSpawnSceneMessage . sceneId + " SpawnableObjects.Count=" + s_SpawnableObjects . Count ) ;
// dump the whole spawnable objects dict for easier debugging
foreach ( var kvp in s_SpawnableObjects )
Debug . Log ( "Spawnable: SceneId=" + kvp . Key + " name=" + kvp . Value . name ) ;
}
2018-06-07 13:41:08 +00:00
return ;
}
if ( LogFilter . logDebug ) { Debug . Log ( "Client spawn for [netId:" + s_ObjectSpawnSceneMessage . netId + "] [sceneId:" + s_ObjectSpawnSceneMessage . sceneId + "] obj:" + spawnedId . gameObject . name ) ; }
ApplySpawnPayload ( spawnedId , s_ObjectSpawnSceneMessage . position , s_ObjectSpawnSceneMessage . payload , s_ObjectSpawnSceneMessage . netId , spawnedId . gameObject ) ;
}
static void OnObjectSpawnFinished ( NetworkMessage netMsg )
{
netMsg . ReadMessage ( s_ObjectSpawnFinishedMessage ) ;
if ( LogFilter . logDebug ) { Debug . Log ( "SpawnFinished:" + s_ObjectSpawnFinishedMessage . state ) ; }
if ( s_ObjectSpawnFinishedMessage . state = = 0 )
{
PrepareToSpawnSceneObjects ( ) ;
s_IsSpawnFinished = false ;
return ;
}
foreach ( var uv in objects . Values )
{
if ( ! uv . isClient )
{
uv . OnStartClient ( ) ;
CheckForOwner ( uv ) ;
}
}
s_IsSpawnFinished = true ;
}
static void OnObjectDestroy ( NetworkMessage netMsg )
{
netMsg . ReadMessage ( s_ObjectDestroyMessage ) ;
if ( LogFilter . logDebug ) { Debug . Log ( "ClientScene::OnObjDestroy netId:" + s_ObjectDestroyMessage . netId ) ; }
NetworkIdentity localObject ;
if ( s_NetworkScene . GetNetworkIdentity ( s_ObjectDestroyMessage . netId , out localObject ) )
{
#if UNITY_EDITOR
UnityEditor . NetworkDetailStats . IncrementStat (
UnityEditor . NetworkDetailStats . NetworkDirection . Incoming ,
MsgType . ObjectDestroy , GetStringForAssetId ( localObject . assetId ) , 1 ) ;
#endif
localObject . OnNetworkDestroy ( ) ;
if ( ! NetworkScene . InvokeUnSpawnHandler ( localObject . assetId , localObject . gameObject ) )
{
// default handling
if ( localObject . sceneId . IsEmpty ( ) )
{
Object . Destroy ( localObject . gameObject ) ;
}
else
{
// scene object.. disable it in scene instead of destroying
localObject . gameObject . SetActive ( false ) ;
s_SpawnableObjects [ localObject . sceneId ] = localObject ;
}
}
s_NetworkScene . RemoveLocalObject ( s_ObjectDestroyMessage . netId ) ;
localObject . MarkForReset ( ) ;
}
else
{
if ( LogFilter . logDebug ) { Debug . LogWarning ( "Did not find target for destroy message for " + s_ObjectDestroyMessage . netId ) ; }
}
}
static void OnLocalClientObjectDestroy ( NetworkMessage netMsg )
{
netMsg . ReadMessage ( s_ObjectDestroyMessage ) ;
if ( LogFilter . logDebug ) { Debug . Log ( "ClientScene::OnLocalObjectObjDestroy netId:" + s_ObjectDestroyMessage . netId ) ; }
s_NetworkScene . RemoveLocalObject ( s_ObjectDestroyMessage . netId ) ;
}
static void OnLocalClientObjectHide ( NetworkMessage netMsg )
{
netMsg . ReadMessage ( s_ObjectDestroyMessage ) ;
if ( LogFilter . logDebug ) { Debug . Log ( "ClientScene::OnLocalObjectObjHide netId:" + s_ObjectDestroyMessage . netId ) ; }
NetworkIdentity localObject ;
if ( s_NetworkScene . GetNetworkIdentity ( s_ObjectDestroyMessage . netId , out localObject ) )
{
localObject . OnSetLocalVisibility ( false ) ;
}
}
static void OnLocalClientObjectSpawn ( NetworkMessage netMsg )
{
netMsg . ReadMessage ( s_ObjectSpawnMessage ) ;
NetworkIdentity localObject ;
if ( s_NetworkScene . GetNetworkIdentity ( s_ObjectSpawnMessage . netId , out localObject ) )
{
localObject . OnSetLocalVisibility ( true ) ;
}
}
static void OnLocalClientObjectSpawnScene ( NetworkMessage netMsg )
{
netMsg . ReadMessage ( s_ObjectSpawnSceneMessage ) ;
NetworkIdentity localObject ;
if ( s_NetworkScene . GetNetworkIdentity ( s_ObjectSpawnSceneMessage . netId , out localObject ) )
{
localObject . OnSetLocalVisibility ( true ) ;
}
}
static void OnUpdateVarsMessage ( NetworkMessage netMsg )
{
NetworkInstanceId netId = netMsg . reader . ReadNetworkId ( ) ;
if ( LogFilter . logDev ) { Debug . Log ( "ClientScene::OnUpdateVarsMessage " + netId + " channel:" + netMsg . channelId ) ; }
NetworkIdentity localObject ;
if ( s_NetworkScene . GetNetworkIdentity ( netId , out localObject ) )
{
localObject . OnUpdateVars ( netMsg . reader , false ) ;
}
else
{
2018-06-08 10:06:04 +00:00
if ( LogFilter . logWarn ) { Debug . LogWarning ( "Did not find target for sync message for " + netId + " . Note: this can be completely normal because UDP messages may arrive out of order, so this message might have arrived after a Destroy message." ) ; }
2018-06-07 13:41:08 +00:00
}
}
static void OnRPCMessage ( NetworkMessage netMsg )
{
var cmdHash = ( int ) netMsg . reader . ReadPackedUInt32 ( ) ;
var netId = netMsg . reader . ReadNetworkId ( ) ;
if ( LogFilter . logDebug ) { Debug . Log ( "ClientScene::OnRPCMessage hash:" + cmdHash + " netId:" + netId ) ; }
NetworkIdentity uv ;
if ( s_NetworkScene . GetNetworkIdentity ( netId , out uv ) )
{
uv . HandleRPC ( cmdHash , netMsg . reader ) ;
}
else
{
if ( LogFilter . logWarn )
{
string errorCmdName = NetworkBehaviour . GetCmdHashHandlerName ( cmdHash ) ;
Debug . LogWarningFormat ( "Could not find target object with netId:{0} for RPC call {1}" , netId , errorCmdName ) ;
}
}
}
static void OnSyncEventMessage ( NetworkMessage netMsg )
{
var cmdHash = ( int ) netMsg . reader . ReadPackedUInt32 ( ) ;
var netId = netMsg . reader . ReadNetworkId ( ) ;
if ( LogFilter . logDebug ) { Debug . Log ( "ClientScene::OnSyncEventMessage " + netId ) ; }
NetworkIdentity uv ;
if ( s_NetworkScene . GetNetworkIdentity ( netId , out uv ) )
{
uv . HandleSyncEvent ( cmdHash , netMsg . reader ) ;
}
else
{
if ( LogFilter . logWarn ) { Debug . LogWarning ( "Did not find target for SyncEvent message for " + netId ) ; }
}
#if UNITY_EDITOR
UnityEditor . NetworkDetailStats . IncrementStat (
UnityEditor . NetworkDetailStats . NetworkDirection . Outgoing ,
MsgType . SyncEvent , NetworkBehaviour . GetCmdHashHandlerName ( cmdHash ) , 1 ) ;
#endif
}
static void OnSyncListMessage ( NetworkMessage netMsg )
{
var netId = netMsg . reader . ReadNetworkId ( ) ;
var cmdHash = ( int ) netMsg . reader . ReadPackedUInt32 ( ) ;
if ( LogFilter . logDebug ) { Debug . Log ( "ClientScene::OnSyncListMessage " + netId ) ; }
NetworkIdentity uv ;
if ( s_NetworkScene . GetNetworkIdentity ( netId , out uv ) )
{
uv . HandleSyncList ( cmdHash , netMsg . reader ) ;
}
else
{
if ( LogFilter . logWarn ) { Debug . LogWarning ( "Did not find target for SyncList message for " + netId ) ; }
}
#if UNITY_EDITOR
UnityEditor . NetworkDetailStats . IncrementStat (
UnityEditor . NetworkDetailStats . NetworkDirection . Outgoing ,
MsgType . SyncList , NetworkBehaviour . GetCmdHashHandlerName ( cmdHash ) , 1 ) ;
#endif
}
static void OnClientAuthority ( NetworkMessage netMsg )
{
netMsg . ReadMessage ( s_ClientAuthorityMessage ) ;
if ( LogFilter . logDebug ) { Debug . Log ( "ClientScene::OnClientAuthority for connectionId=" + netMsg . conn . connectionId + " netId: " + s_ClientAuthorityMessage . netId ) ; }
NetworkIdentity uv ;
if ( s_NetworkScene . GetNetworkIdentity ( s_ClientAuthorityMessage . netId , out uv ) )
{
uv . HandleClientAuthority ( s_ClientAuthorityMessage . authority ) ;
}
}
// OnClientAddedPlayer?
static void OnOwnerMessage ( NetworkMessage netMsg )
{
netMsg . ReadMessage ( s_OwnerMessage ) ;
if ( LogFilter . logDebug ) { Debug . Log ( "ClientScene::OnOwnerMessage - connectionId=" + netMsg . conn . connectionId + " netId: " + s_OwnerMessage . netId ) ; }
// is there already an owner that is a different object??
PlayerController oldOwner ;
if ( netMsg . conn . GetPlayerController ( s_OwnerMessage . playerControllerId , out oldOwner ) )
{
oldOwner . unetView . SetNotLocalPlayer ( ) ;
}
NetworkIdentity localNetworkIdentity ;
if ( s_NetworkScene . GetNetworkIdentity ( s_OwnerMessage . netId , out localNetworkIdentity ) )
{
// this object already exists
localNetworkIdentity . SetConnectionToServer ( netMsg . conn ) ;
localNetworkIdentity . SetLocalPlayer ( s_OwnerMessage . playerControllerId ) ;
InternalAddPlayer ( localNetworkIdentity , s_OwnerMessage . playerControllerId ) ;
}
else
{
var pendingOwner = new PendingOwner { netId = s_OwnerMessage . netId , playerControllerId = s_OwnerMessage . playerControllerId } ;
s_PendingOwnerIds . Add ( pendingOwner ) ;
}
}
static void CheckForOwner ( NetworkIdentity uv )
{
for ( int i = 0 ; i < s_PendingOwnerIds . Count ; i + + )
{
var pendingOwner = s_PendingOwnerIds [ i ] ;
if ( pendingOwner . netId = = uv . netId )
{
// found owner, turn into a local player
// Set isLocalPlayer to true on this NetworkIdentity and trigger OnStartLocalPlayer in all scripts on the same GO
uv . SetConnectionToServer ( s_ReadyConnection ) ;
uv . SetLocalPlayer ( pendingOwner . playerControllerId ) ;
if ( LogFilter . logDev ) { Debug . Log ( "ClientScene::OnOwnerMessage - player=" + uv . gameObject . name ) ; }
if ( s_ReadyConnection . connectionId < 0 )
{
if ( LogFilter . logError ) { Debug . LogError ( "Owner message received on a local client." ) ; }
return ;
}
InternalAddPlayer ( uv , pendingOwner . playerControllerId ) ;
s_PendingOwnerIds . RemoveAt ( i ) ;
break ;
}
}
}
}
}
#endif //ENABLE_UNET