PlayerControllers removed because couch co-op while playing online is such a rare use case that it's hardly worth supporting the insane complexity

This commit is contained in:
vis2k 2018-09-26 17:40:07 +02:00
parent d3c81957da
commit 1e61aaa05a
16 changed files with 132 additions and 352 deletions

View File

@ -80,21 +80,12 @@ public override void OnInspectorGUI()
if (m_ShowObservers)
{
EditorGUI.indentLevel += 1;
foreach (var o in m_NetworkIdentity.observers)
foreach (NetworkConnection observer in m_NetworkIdentity.observers)
{
GameObject obj = null;
foreach (var p in o.playerControllers)
{
if (p != null)
{
obj = p.gameObject;
break;
}
}
if (obj)
EditorGUILayout.ObjectField("Connection " + o.connectionId, obj, typeof(GameObject), false);
if (observer.playerController != null)
EditorGUILayout.ObjectField("Connection " + observer.connectionId, observer.playerController.gameObject, typeof(GameObject), false);
else
EditorGUILayout.TextField("Connection " + o.connectionId);
EditorGUILayout.TextField("Connection " + observer.connectionId);
}
EditorGUI.indentLevel -= 1;
}

View File

@ -231,8 +231,6 @@ void GetNetworkInformation(GameObject gameObject)
m_Info.Add(GetString("Network ID", m_Identity.netId.ToString()));
m_Info.Add(GetString("Player Controller ID", m_Identity.playerControllerId.ToString()));
m_Info.Add(GetBoolean("Is Client", m_Identity.isClient));
m_Info.Add(GetBoolean("Is Server", m_Identity.isServer));
m_Info.Add(GetBoolean("Has Authority", m_Identity.hasAuthority));

View File

@ -120,10 +120,7 @@ void ShowServerConnections()
if (m_ShowPlayersForConnections[index])
{
EditorGUI.indentLevel += 1;
foreach (var player in con.playerControllers)
{
EditorGUILayout.ObjectField("Player: " + player.playerControllerId, player.gameObject, typeof(GameObject), true);
}
EditorGUILayout.ObjectField("Player: ", con.playerController.gameObject, typeof(GameObject), true);
EditorGUI.indentLevel -= 1;
}
@ -253,10 +250,7 @@ void ShowClientInfo()
{
EditorGUILayout.TextField("client " + count + ":" , cl.GetType().Name + " Conn: " + cl.connection);
EditorGUI.indentLevel += 1;
foreach (var p in cl.connection.playerControllers)
{
EditorGUILayout.LabelField("Player", p.ToString());
}
EditorGUILayout.LabelField("Player", cl.connection.playerController.name);
EditorGUI.indentLevel -= 1;
}
count++;
@ -330,9 +324,9 @@ void ShowControls()
{
ClientScene.Ready(m_Manager.client.connection);
if (ClientScene.localPlayers.Count == 0)
if (ClientScene.localPlayer == null)
{
ClientScene.AddPlayer(0);
ClientScene.AddPlayer();
}
}
}

View File

@ -5,7 +5,7 @@ namespace Mirror
{
public class ClientScene
{
static List<PlayerController> s_LocalPlayers = new List<PlayerController>();
static NetworkIdentity s_LocalPlayer;
static NetworkConnection s_ReadyConnection;
static Dictionary<NetworkSceneId, NetworkIdentity> s_SpawnableObjects;
@ -18,14 +18,9 @@ internal static void SetNotReady()
s_IsReady = false;
}
struct PendingOwner
{
public NetworkInstanceId netId;
public short playerControllerId;
}
static List<PendingOwner> s_PendingOwnerIds = new List<PendingOwner>();
static List<NetworkInstanceId> s_PendingOwnerIds = new List<NetworkInstanceId>();
public static List<PlayerController> localPlayers { get { return s_LocalPlayers; } }
public static NetworkIdentity localPlayer { get { return s_LocalPlayer; } }
public static bool ready { get { return s_IsReady; } }
public static NetworkConnection readyConnection { get { return s_ReadyConnection; }}
@ -37,8 +32,7 @@ struct PendingOwner
internal static void Shutdown()
{
s_NetworkScene.Shutdown();
s_LocalPlayers = new List<PlayerController>();
s_PendingOwnerIds = new List<PendingOwner>();
s_PendingOwnerIds = new List<NetworkInstanceId>();
s_SpawnableObjects = null;
s_ReadyConnection = null;
s_IsReady = false;
@ -48,69 +42,38 @@ internal static void Shutdown()
}
// this is called from message handler for Owner message
internal static void InternalAddPlayer(NetworkIdentity view, short playerControllerId)
internal static void InternalAddPlayer(NetworkIdentity view)
{
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());
}
}
if (LogFilter.logDebug) { Debug.LogWarning("ClientScene::InternalAddPlayer"); }
// 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;
s_LocalPlayer = view;
if (s_ReadyConnection == null)
{
if (LogFilter.logWarn) { Debug.LogWarning("No ready connection found for setting player controller during InternalAddPlayer"); }
}
else
{
s_ReadyConnection.SetPlayerController(newPlayer);
s_ReadyConnection.SetPlayerController(view);
}
}
// use this if already ready
public static bool AddPlayer(short playerControllerId)
public static bool AddPlayer()
{
return AddPlayer(null, playerControllerId);
return AddPlayer(null);
}
// use this to implicitly become ready
public static bool AddPlayer(NetworkConnection readyConn, short playerControllerId)
public static bool AddPlayer(NetworkConnection readyConn)
{
return AddPlayer(readyConn, playerControllerId, null);
return AddPlayer(readyConn, null);
}
// use this to implicitly become ready
public static bool AddPlayer(NetworkConnection readyConn, short playerControllerId, MessageBase extraMessage)
public static bool AddPlayer(NetworkConnection readyConn, 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)
{
@ -124,23 +87,18 @@ public static bool AddPlayer(NetworkConnection readyConn, short playerController
return false;
}
PlayerController existingPlayerController;
if (s_ReadyConnection.GetPlayerController(playerControllerId, out existingPlayerController))
if (s_ReadyConnection.playerController != null)
{
if (existingPlayerController.IsValid && existingPlayerController.gameObject != null)
{
if (LogFilter.logError) { Debug.LogError("ClientScene::AddPlayer: playerControllerId of " + playerControllerId + " already in use."); }
return false;
}
if (LogFilter.logError) { Debug.LogError("ClientScene::AddPlayer: a PlayerController was already added. Did you call AddPlayer twice?"); }
return false;
}
if (LogFilter.logDebug) { Debug.Log("ClientScene::AddPlayer() for ID " + playerControllerId + " called with connection [" + s_ReadyConnection + "]"); }
if (LogFilter.logDebug) { Debug.Log("ClientScene::AddPlayer() called with connection [" + s_ReadyConnection + "]"); }
var msg = new AddPlayerMessage();
msg.playerControllerId = playerControllerId;
AddPlayerMessage msg = new AddPlayerMessage();
if (extraMessage != null)
{
var writer = new NetworkWriter();
NetworkWriter writer = new NetworkWriter();
extraMessage.Serialize(writer);
msg.msgData = writer.ToArray();
}
@ -148,24 +106,21 @@ public static bool AddPlayer(NetworkConnection readyConn, short playerController
return true;
}
public static bool RemovePlayer(short playerControllerId)
public static bool RemovePlayer()
{
if (LogFilter.logDebug) { Debug.Log("ClientScene::RemovePlayer() for ID " + playerControllerId + " called with connection [" + s_ReadyConnection + "]"); }
if (LogFilter.logDebug) { Debug.Log("ClientScene::RemovePlayer() called with connection [" + s_ReadyConnection + "]"); }
PlayerController playerController;
if (s_ReadyConnection.GetPlayerController(playerControllerId, out playerController))
if (s_ReadyConnection.playerController != null)
{
var msg = new RemovePlayerMessage();
msg.playerControllerId = playerControllerId;
RemovePlayerMessage msg = new RemovePlayerMessage();
s_ReadyConnection.Send((short)MsgType.RemovePlayer, msg);
s_ReadyConnection.RemovePlayerController(playerControllerId);
s_LocalPlayers[playerControllerId] = new PlayerController();
s_ReadyConnection.RemovePlayerController();
s_LocalPlayer = null;
Object.Destroy(playerController.gameObject);
Object.Destroy(s_ReadyConnection.playerController.gameObject);
return true;
}
if (LogFilter.logError) { Debug.LogError("Failed to find player ID " + playerControllerId); }
return false;
}
@ -669,10 +624,9 @@ static void OnOwnerMessage(NetworkMessage netMsg)
// is there already an owner that is a different object??
PlayerController oldOwner;
if (netMsg.conn.GetPlayerController(msg.playerControllerId, out oldOwner))
if (netMsg.conn.playerController != null)
{
oldOwner.unetView.SetNotLocalPlayer();
netMsg.conn.playerController.SetNotLocalPlayer();
}
NetworkIdentity localNetworkIdentity;
@ -680,13 +634,12 @@ static void OnOwnerMessage(NetworkMessage netMsg)
{
// this object already exists
localNetworkIdentity.SetConnectionToServer(netMsg.conn);
localNetworkIdentity.SetLocalPlayer(msg.playerControllerId);
InternalAddPlayer(localNetworkIdentity, msg.playerControllerId);
localNetworkIdentity.SetLocalPlayer();
InternalAddPlayer(localNetworkIdentity);
}
else
{
var pendingOwner = new PendingOwner { netId = msg.netId, playerControllerId = msg.playerControllerId };
s_PendingOwnerIds.Add(pendingOwner);
s_PendingOwnerIds.Add(msg.netId);
}
}
@ -694,15 +647,15 @@ static void CheckForOwner(NetworkIdentity uv)
{
for (int i = 0; i < s_PendingOwnerIds.Count; i++)
{
var pendingOwner = s_PendingOwnerIds[i];
NetworkInstanceId pendingOwner = s_PendingOwnerIds[i];
if (pendingOwner.netId == uv.netId)
if (pendingOwner == 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);
uv.SetLocalPlayer();
if (LogFilter.logDev) { Debug.Log("ClientScene::OnOwnerMessage - player=" + uv.gameObject.name); }
if (s_ReadyConnection.connectionId < 0)
@ -710,7 +663,7 @@ static void CheckForOwner(NetworkIdentity uv)
if (LogFilter.logError) { Debug.LogError("Owner message received on a local client."); }
return;
}
InternalAddPlayer(uv, pendingOwner.playerControllerId);
InternalAddPlayer(uv);
s_PendingOwnerIds.RemoveAt(i);
break;

View File

@ -52,19 +52,19 @@ internal override void Update()
}
// Called by the server to set the LocalClient's LocalPlayer object during NetworkServer.AddPlayer()
internal void AddLocalPlayer(PlayerController localPlayer)
internal void AddLocalPlayer(NetworkIdentity localPlayer)
{
if (LogFilter.logDev) Debug.Log("Local client AddLocalPlayer " + localPlayer.gameObject.name + " conn=" + m_Connection.connectionId);
m_Connection.isReady = true;
m_Connection.SetPlayerController(localPlayer);
var uv = localPlayer.unetView;
NetworkIdentity uv = localPlayer;
if (uv != null)
{
ClientScene.SetLocalObject(uv.netId, localPlayer.gameObject);
uv.SetConnectionToServer(m_Connection);
}
// there is no SystemOwnerMessage for local client. add to ClientScene here instead
ClientScene.InternalAddPlayer(uv, localPlayer.playerControllerId);
ClientScene.InternalAddPlayer(uv);
}
private void PostInternalMessage(short msgType, byte[] content)

View File

@ -103,35 +103,21 @@ public class NotReadyMessage : EmptyMessage
public class AddPlayerMessage : MessageBase
{
public short playerControllerId;
public byte[] msgData;
public override void Deserialize(NetworkReader reader)
{
playerControllerId = (short)reader.ReadPackedUInt32();
msgData = reader.ReadBytesAndSize();
}
public override void Serialize(NetworkWriter writer)
{
writer.WritePackedUInt32((uint)playerControllerId);
writer.WriteBytesAndSize(msgData);
}
}
public class RemovePlayerMessage : MessageBase
{
public short playerControllerId;
public override void Deserialize(NetworkReader reader)
{
playerControllerId = (short)reader.ReadPackedUInt32();
}
public override void Serialize(NetworkWriter writer)
{
writer.WritePackedUInt32((uint)playerControllerId);
}
}
// ---------- System Messages requried for code gen path -------------------
@ -317,18 +303,15 @@ public override void Serialize(NetworkWriter writer)
class OwnerMessage : MessageBase
{
public NetworkInstanceId netId;
public short playerControllerId;
public override void Deserialize(NetworkReader reader)
{
netId = reader.ReadNetworkId();
playerControllerId = (short)reader.ReadPackedUInt32();
}
public override void Serialize(NetworkWriter writer)
{
writer.Write(netId);
writer.WritePackedUInt32((uint)playerControllerId);
}
}

View File

@ -78,7 +78,6 @@
<Compile Include="NetworkTranformChild.cs" />
<Compile Include="NetworkTransform.cs" />
<Compile Include="NetworkTransformVisualizer.cs" />
<Compile Include="PlayerController.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="NetworkClient.cs" />
<Compile Include="NetworkConnection.cs" />

View File

@ -23,7 +23,6 @@ public class NetworkBehaviour : MonoBehaviour
public NetworkInstanceId netId { get { return myView.netId; } }
public NetworkConnection connectionToServer { get { return myView.connectionToServer; } }
public NetworkConnection connectionToClient { get { return myView.connectionToClient; } }
public short playerControllerId { get { return myView.playerControllerId; } }
protected ulong syncVarDirtyBits { get { return m_SyncVarDirtyBits; } }
protected bool syncVarHookGuard { get { return m_SyncVarGuard; } set { m_SyncVarGuard = value; }}

View File

@ -12,7 +12,7 @@ namespace Mirror
*/
public class NetworkConnection : IDisposable
{
List<PlayerController> m_PlayerControllers = new List<PlayerController>();
NetworkIdentity m_PlayerController;
HashSet<NetworkIdentity> m_VisList = new HashSet<NetworkIdentity>();
public HashSet<NetworkIdentity> visList { get { return m_VisList; } }
@ -25,7 +25,7 @@ public class NetworkConnection : IDisposable
public bool isReady;
public string address;
public float lastMessageTime;
public List<PlayerController> playerControllers { get { return m_PlayerControllers; } }
public NetworkIdentity playerController { get { return m_PlayerController; } }
public HashSet<NetworkInstanceId> clientOwnedObjects { get { return m_ClientOwnedObjects; } }
public bool logNetworkMessages = false;
public bool isConnected { get { return hostId != -1; }}
@ -148,36 +148,14 @@ public void UnregisterHandler(short msgType)
m_MessageHandlers.Remove(msgType);
}
internal void SetPlayerController(PlayerController player)
internal void SetPlayerController(NetworkIdentity player)
{
while (player.playerControllerId >= m_PlayerControllers.Count)
{
m_PlayerControllers.Add(new PlayerController());
}
m_PlayerControllers[player.playerControllerId] = player;
m_PlayerController = player;
}
internal void RemovePlayerController(short playerControllerId)
internal void RemovePlayerController()
{
int count = m_PlayerControllers.Count;
while (count >= 0)
{
if (playerControllerId == count && playerControllerId == m_PlayerControllers[count].playerControllerId)
{
m_PlayerControllers[count] = new PlayerController();
return;
}
count -= 1;
}
if (LogFilter.logError) { Debug.LogError("RemovePlayer player at playerControllerId " + playerControllerId + " not found"); }
}
// Get player controller from connection's list
internal bool GetPlayerController(short playerControllerId, out PlayerController playerController)
{
playerController = playerControllers.Find(pc => pc.IsValid && pc.playerControllerId == playerControllerId);
return playerController != null;
m_PlayerController = null;
}
public virtual bool Send(short msgType, MessageBase msg)

View File

@ -30,7 +30,6 @@ public sealed class NetworkIdentity : MonoBehaviour
bool m_IsLocalPlayer;
NetworkConnection m_ConnectionToServer;
NetworkConnection m_ConnectionToClient;
short m_PlayerId = -1;
NetworkBehaviour[] m_NetworkBehaviours;
// there is a list AND a hashSet of connections, for fast verification of dupes, but the main operation is iteration over the list.
@ -112,7 +111,6 @@ internal void ForceAuthority(bool authority)
}
public bool isLocalPlayer { get { return m_IsLocalPlayer; } }
public short playerControllerId { get { return m_PlayerId; } }
public NetworkConnection connectionToServer { get { return m_ConnectionToServer; } }
public NetworkConnection connectionToClient { get { return m_ConnectionToClient; } }
@ -749,10 +747,9 @@ internal void OnUpdateVars(NetworkReader reader, bool initialState)
OnDeserializeAllSafely(m_NetworkBehaviours, reader, initialState);
}
internal void SetLocalPlayer(short localPlayerControllerId)
internal void SetLocalPlayer()
{
m_IsLocalPlayer = true;
m_PlayerId = localPlayerControllerId;
// there is an ordering issue here that originAuthority solves. OnStartAuthority should only be called if m_HasAuthority was false when this function began,
// or it will be called twice for this object. But that state is lost by the time OnStartAuthority is called below, so the original value is cached
@ -780,9 +777,8 @@ internal void SetConnectionToServer(NetworkConnection conn)
m_ConnectionToServer = conn;
}
internal void SetConnectionToClient(NetworkConnection conn, short newPlayerControllerId)
internal void SetConnectionToClient(NetworkConnection conn)
{
m_PlayerId = newPlayerControllerId;
m_ConnectionToClient = conn;
}
@ -1049,7 +1045,6 @@ internal void Reset()
m_IsLocalPlayer = false;
m_ConnectionToServer = null;
m_ConnectionToClient = null;
m_PlayerId = -1;
m_NetworkBehaviours = null;
ClearObservers();

View File

@ -60,21 +60,7 @@ public class NetworkManager : MonoBehaviour
public bool clientLoadedScene { get { return m_ClientLoadedScene; } set { m_ClientLoadedScene = value; } }
// only really valid on the server
public int numPlayers
{
get
{
int amount = 0;
foreach (NetworkConnection conn in NetworkServer.connections)
{
if (conn != null)
{
amount += conn.playerControllers.Count(pc => pc.IsValid);
}
}
return amount;
}
}
public int numPlayers { get { return NetworkServer.connections.Count(conn => conn.playerController != null); } }
// runtime data
public static string networkSceneName = ""; // this is used to make sure that all scene changes are initialized by UNET. loading a scene manually wont set networkSceneName, so UNET would still load it again on start.
@ -579,12 +565,12 @@ internal void OnServerAddPlayerMessageInternal(NetworkMessage netMsg)
if (msg.msgData != null && msg.msgData.Length > 0)
{
var reader = new NetworkReader(msg.msgData);
OnServerAddPlayer(netMsg.conn, msg.playerControllerId, reader);
NetworkReader reader = new NetworkReader(msg.msgData);
OnServerAddPlayer(netMsg.conn, reader);
}
else
{
OnServerAddPlayer(netMsg.conn, msg.playerControllerId);
OnServerAddPlayer(netMsg.conn);
}
}
@ -595,10 +581,11 @@ internal void OnServerRemovePlayerMessageInternal(NetworkMessage netMsg)
RemovePlayerMessage msg = new RemovePlayerMessage();
netMsg.ReadMessage(msg);
PlayerController player;
netMsg.conn.GetPlayerController(msg.playerControllerId, out player);
OnServerRemovePlayer(netMsg.conn, player);
netMsg.conn.RemovePlayerController(msg.playerControllerId);
if (netMsg.conn.playerController != null)
{
OnServerRemovePlayer(netMsg.conn, netMsg.conn.playerController);
netMsg.conn.RemovePlayerController();
}
}
internal void OnServerErrorInternal(NetworkMessage netMsg)
@ -680,13 +667,13 @@ public virtual void OnServerConnect(NetworkConnection conn)
public virtual void OnServerDisconnect(NetworkConnection conn)
{
NetworkServer.DestroyPlayersForConnection(conn);
NetworkServer.DestroyPlayerForConnection(conn);
if (LogFilter.logDebug) { Debug.Log("OnServerDisconnect: Client disconnected."); }
}
public virtual void OnServerReady(NetworkConnection conn)
{
if (conn.playerControllers.Count == 0)
if (conn.playerController == null)
{
// this is now allowed (was not for a while)
if (LogFilter.logDebug) { Debug.Log("Ready with no player object"); }
@ -694,17 +681,17 @@ public virtual void OnServerReady(NetworkConnection conn)
NetworkServer.SetClientReady(conn);
}
public virtual void OnServerAddPlayer(NetworkConnection conn, short playerControllerId, NetworkReader extraMessageReader)
public virtual void OnServerAddPlayer(NetworkConnection conn, NetworkReader extraMessageReader)
{
OnServerAddPlayerInternal(conn, playerControllerId);
OnServerAddPlayerInternal(conn);
}
public virtual void OnServerAddPlayer(NetworkConnection conn, short playerControllerId)
public virtual void OnServerAddPlayer(NetworkConnection conn)
{
OnServerAddPlayerInternal(conn, playerControllerId);
OnServerAddPlayerInternal(conn);
}
void OnServerAddPlayerInternal(NetworkConnection conn, short playerControllerId)
void OnServerAddPlayerInternal(NetworkConnection conn)
{
if (m_PlayerPrefab == null)
{
@ -718,9 +705,9 @@ void OnServerAddPlayerInternal(NetworkConnection conn, short playerControllerId)
return;
}
if (playerControllerId < conn.playerControllers.Count && conn.playerControllers[playerControllerId].IsValid && conn.playerControllers[playerControllerId].gameObject != null)
if (conn.playerController != null)
{
if (LogFilter.logError) { Debug.LogError("There is already a player at that playerControllerId for this connections."); }
if (LogFilter.logError) { Debug.LogError("There is already a player for this connections."); }
return;
}
@ -735,7 +722,7 @@ void OnServerAddPlayerInternal(NetworkConnection conn, short playerControllerId)
player = Instantiate(m_PlayerPrefab, Vector3.zero, Quaternion.identity);
}
NetworkServer.AddPlayerForConnection(conn, player, playerControllerId);
NetworkServer.AddPlayerForConnection(conn, player);
}
public Transform GetStartPosition()
@ -763,7 +750,7 @@ public Transform GetStartPosition()
return null;
}
public virtual void OnServerRemovePlayer(NetworkConnection conn, PlayerController player)
public virtual void OnServerRemovePlayer(NetworkConnection conn, NetworkIdentity player)
{
if (player.gameObject != null)
{
@ -789,7 +776,7 @@ public virtual void OnClientConnect(NetworkConnection conn)
ClientScene.Ready(conn);
if (m_AutoCreatePlayer)
{
ClientScene.AddPlayer(0);
ClientScene.AddPlayer();
}
}
}
@ -815,10 +802,10 @@ public virtual void OnClientSceneChanged(NetworkConnection conn)
// vis2k: replaced all this weird code with something more simple
if (m_AutoCreatePlayer)
{
// add player if all existing ones are null (or if list is empty, then .All returns true)
if (ClientScene.localPlayers.All(pc => pc.gameObject == null))
// add player if existing one is null
if (ClientScene.localPlayer == null)
{
ClientScene.AddPlayer(0);
ClientScene.AddPlayer();
}
}
}

View File

@ -99,9 +99,9 @@ void OnGUI()
{
ClientScene.Ready(manager.client.connection);
if (ClientScene.localPlayers.Count == 0)
if (ClientScene.localPlayer == null)
{
ClientScene.AddPlayer(0);
ClientScene.AddPlayer();
}
}
}

View File

@ -46,14 +46,9 @@ public override bool OnCheckObserver(NetworkConnection newObserver)
if (forceHidden)
return false;
// this cant use newObserver.playerControllers[0]. must iterate to find a valid player.
PlayerController controller = newObserver.playerControllers.Find(
pc => pc != null && pc.gameObject != null
);
if (controller != null)
if (newObserver.playerController != null)
{
GameObject player = controller.gameObject;
return Vector3.Distance(player.transform.position, transform.position) < visRange;
return Vector3.Distance(newObserver.playerController.transform.position, transform.position) < visRange;
}
return false;
}

View File

@ -441,7 +441,7 @@ static void OnDisconnected(NetworkConnection conn)
{
conn.InvokeHandlerNoData((short)MsgType.Disconnect);
if (conn.playerControllers.Any(pc => pc.gameObject != null))
if (conn.playerController != null)
{
//NOTE: should there be default behaviour here to destroy the associated player?
if (LogFilter.logWarn) { Debug.LogWarning("Player not destroyed when connection disconnected."); }
@ -555,17 +555,13 @@ public static void SendToClientOfPlayer(GameObject player, short msgType, Messag
{
for (int i = 0; i < connections.Count; i++)
{
var conn = connections[i];
if (conn != null)
NetworkConnection conn = connections[i];
if (conn != null &&
conn.playerController != null &&
conn.playerController.gameObject == player)
{
for (int j = 0; j < conn.playerControllers.Count; j++)
{
if (conn.playerControllers[j].IsValid && conn.playerControllers[j].gameObject == player)
{
conn.Send(msgType, msg);
return;
}
}
conn.Send(msgType, msg);
return;
}
}
@ -586,37 +582,37 @@ public static void SendToClient(int connectionId, short msgType, MessageBase msg
if (LogFilter.logError) { Debug.LogError("Failed to send message to connection ID '" + connectionId + ", not found in connection list"); }
}
public static bool ReplacePlayerForConnection(NetworkConnection conn, GameObject player, short playerControllerId, NetworkHash128 assetId)
public static bool ReplacePlayerForConnection(NetworkConnection conn, GameObject player, NetworkHash128 assetId)
{
NetworkIdentity id;
if (GetNetworkIdentity(player, out id))
{
id.SetDynamicAssetId(assetId);
}
return InternalReplacePlayerForConnection(conn, player, playerControllerId);
return InternalReplacePlayerForConnection(conn, player);
}
public static bool ReplacePlayerForConnection(NetworkConnection conn, GameObject player, short playerControllerId)
public static bool ReplacePlayerForConnection(NetworkConnection conn, GameObject player)
{
return InternalReplacePlayerForConnection(conn, player, playerControllerId);
return InternalReplacePlayerForConnection(conn, player);
}
public static bool AddPlayerForConnection(NetworkConnection conn, GameObject player, short playerControllerId, NetworkHash128 assetId)
public static bool AddPlayerForConnection(NetworkConnection conn, GameObject player, NetworkHash128 assetId)
{
NetworkIdentity id;
if (GetNetworkIdentity(player, out id))
{
id.SetDynamicAssetId(assetId);
}
return InternalAddPlayerForConnection(conn, player, playerControllerId);
return InternalAddPlayerForConnection(conn, player);
}
public static bool AddPlayerForConnection(NetworkConnection conn, GameObject player, short playerControllerId)
public static bool AddPlayerForConnection(NetworkConnection conn, GameObject player)
{
return InternalAddPlayerForConnection(conn, player, playerControllerId);
return InternalAddPlayerForConnection(conn, player);
}
internal static bool InternalAddPlayerForConnection(NetworkConnection conn, GameObject playerGameObject, short playerControllerId)
internal static bool InternalAddPlayerForConnection(NetworkConnection conn, GameObject playerGameObject)
{
NetworkIdentity playerNetworkIdentity;
if (!GetNetworkIdentity(playerGameObject, out playerNetworkIdentity))
@ -626,31 +622,21 @@ internal static bool InternalAddPlayerForConnection(NetworkConnection conn, Game
}
playerNetworkIdentity.Reset();
if (!CheckPlayerControllerIdForConnection(conn, playerControllerId))
return false;
// cannot have a player object in "Add" version
PlayerController oldController = null;
GameObject oldPlayer = null;
if (conn.GetPlayerController(playerControllerId, out oldController))
if (conn.playerController != null)
{
oldPlayer = oldController.gameObject;
}
if (oldPlayer != null)
{
if (LogFilter.logError) { Debug.Log("AddPlayer: player object already exists for playerControllerId of " + playerControllerId); }
if (LogFilter.logError) { Debug.Log("AddPlayer: player object already exists"); }
return false;
}
PlayerController newPlayerController = new PlayerController(playerGameObject, playerControllerId);
conn.SetPlayerController(newPlayerController);
conn.SetPlayerController(playerNetworkIdentity);
// Set the playerControllerId on the NetworkIdentity on the server, NetworkIdentity.SetLocalPlayer is not called on the server (it is on clients and that sets the playerControllerId there)
playerNetworkIdentity.SetConnectionToClient(conn, newPlayerController.playerControllerId);
// Set the connection on the NetworkIdentity on the server, NetworkIdentity.SetLocalPlayer is not called on the server (it is on clients)
playerNetworkIdentity.SetConnectionToClient(conn);
SetClientReady(conn);
if (SetupLocalPlayerForConnection(conn, playerNetworkIdentity, newPlayerController))
if (SetupLocalPlayerForConnection(conn, playerNetworkIdentity))
{
return true;
}
@ -665,26 +651,7 @@ internal static bool InternalAddPlayerForConnection(NetworkConnection conn, Game
return true;
}
static bool CheckPlayerControllerIdForConnection(NetworkConnection conn, short playerControllerId)
{
if (playerControllerId < 0)
{
if (LogFilter.logError) { Debug.LogError("AddPlayer: playerControllerId of " + playerControllerId + " is negative"); }
return false;
}
if (playerControllerId > PlayerController.MaxPlayersPerClient)
{
if (LogFilter.logError) { Debug.Log("AddPlayer: playerControllerId of " + playerControllerId + " is too high. max is " + PlayerController.MaxPlayersPerClient); }
return false;
}
if (playerControllerId > PlayerController.MaxPlayersPerClient / 2)
{
if (LogFilter.logWarn) { Debug.LogWarning("AddPlayer: playerControllerId of " + playerControllerId + " is unusually high"); }
}
return true;
}
static bool SetupLocalPlayerForConnection(NetworkConnection conn, NetworkIdentity uv, PlayerController newPlayerController)
static bool SetupLocalPlayerForConnection(NetworkConnection conn, NetworkIdentity uv)
{
if (LogFilter.logDev) { Debug.Log("NetworkServer SetupLocalPlayerForConnection netID:" + uv.netId); }
@ -704,14 +671,14 @@ static bool SetupLocalPlayerForConnection(NetworkConnection conn, NetworkIdentit
SendSpawnMessage(uv, null);
// Set up local player instance on the client instance and update local object map
localConnection.localClient.AddLocalPlayer(newPlayerController);
localConnection.localClient.AddLocalPlayer(uv);
uv.SetClientOwner(conn);
// Trigger OnAuthority
uv.ForceAuthority(true);
// Trigger OnStartLocalPlayer
uv.SetLocalPlayer(newPlayerController.playerControllerId);
uv.SetLocalPlayer();
return true;
}
return false;
@ -728,11 +695,10 @@ static void FinishPlayerForConnection(NetworkConnection conn, NetworkIdentity uv
OwnerMessage owner = new OwnerMessage();
owner.netId = uv.netId;
owner.playerControllerId = uv.playerControllerId;
conn.Send((short)MsgType.Owner, owner);
}
internal static bool InternalReplacePlayerForConnection(NetworkConnection conn, GameObject playerGameObject, short playerControllerId)
internal static bool InternalReplacePlayerForConnection(NetworkConnection conn, GameObject playerGameObject)
{
NetworkIdentity playerNetworkIdentity;
if (!GetNetworkIdentity(playerGameObject, out playerNetworkIdentity))
@ -741,31 +707,26 @@ internal static bool InternalReplacePlayerForConnection(NetworkConnection conn,
return false;
}
if (!CheckPlayerControllerIdForConnection(conn, playerControllerId))
return false;
//NOTE: there can be an existing player
if (LogFilter.logDev) { Debug.Log("NetworkServer ReplacePlayer"); }
// is there already an owner that is a different object??
PlayerController oldOwner;
if (conn.GetPlayerController(playerControllerId, out oldOwner))
if (conn.playerController != null)
{
oldOwner.unetView.SetNotLocalPlayer();
oldOwner.unetView.ClearClientOwner();
conn.playerController.SetNotLocalPlayer();
conn.playerController.ClearClientOwner();
}
PlayerController newPlayerController = new PlayerController(playerGameObject, playerControllerId);
conn.SetPlayerController(newPlayerController);
conn.SetPlayerController(playerNetworkIdentity);
// Set the playerControllerId on the NetworkIdentity on the server, NetworkIdentity.SetLocalPlayer is not called on the server (it is on clients and that sets the playerControllerId there)
playerNetworkIdentity.SetConnectionToClient(conn, newPlayerController.playerControllerId);
// Set the connection on the NetworkIdentity on the server, NetworkIdentity.SetLocalPlayer is not called on the server (it is on clients)
playerNetworkIdentity.SetConnectionToClient(conn);
//NOTE: DONT set connection ready.
if (LogFilter.logDev) { Debug.Log("NetworkServer ReplacePlayer setup local"); }
if (SetupLocalPlayerForConnection(conn, playerNetworkIdentity, newPlayerController))
if (SetupLocalPlayerForConnection(conn, playerNetworkIdentity))
{
return true;
}
@ -806,7 +767,7 @@ internal static void SetClientReadyInternal(NetworkConnection conn)
return;
}
if (conn.playerControllers.Count == 0)
if (conn.playerController == null)
{
// this is now allowed
if (LogFilter.logDebug) { Debug.LogWarning("Ready with no player object"); }
@ -932,21 +893,19 @@ static void OnRemovePlayerMessage(NetworkMessage netMsg)
RemovePlayerMessage msg = new RemovePlayerMessage();
netMsg.ReadMessage(msg);
PlayerController player = null;
netMsg.conn.GetPlayerController(msg.playerControllerId, out player);
if (player != null)
if (netMsg.conn.playerController != null)
{
netMsg.conn.RemovePlayerController(msg.playerControllerId);
Destroy(player.gameObject);
netMsg.conn.RemovePlayerController();
Destroy(netMsg.conn.playerController.gameObject);
}
else
{
if (LogFilter.logError) { Debug.LogError("Received remove player message but could not find the player ID: " + msg.playerControllerId); }
if (LogFilter.logError) { Debug.LogError("Received remove player message but connection has no player"); }
}
}
// Handle command from specific player, this could be one of multiple players on a single client
static void OnCommandMessage(NetworkMessage netMsg)
static void OnCommandMessage(NetworkMessage netMsg)
{
CommandMessage message = netMsg.ReadMessage<CommandMessage>();
@ -965,10 +924,9 @@ static void OnCommandMessage(NetworkMessage netMsg)
}
// Commands can be for player objects, OR other objects with client-authority
// => check if there is no owner
if (!netMsg.conn.playerControllers.Any(
pc => pc.gameObject != null &&
pc.gameObject.GetComponent<NetworkIdentity>().netId == uv.netId))
// -> so if this connection's controller has a different netId then
// only allow the command if clientAuthorityOwner
if (netMsg.conn.playerController != null && netMsg.conn.playerController.netId != uv.netId)
{
if (uv.clientAuthorityOwner != netMsg.conn)
{
@ -1063,17 +1021,17 @@ internal static void SendSpawnMessage(NetworkIdentity uv, NetworkConnection conn
}
}
public static void DestroyPlayersForConnection(NetworkConnection conn)
public static void DestroyPlayerForConnection(NetworkConnection conn)
{
if (conn.playerControllers.Count == 0)
if (conn.playerController == null)
{
// list is empty if players are still in a lobby etc., no need to show a warning
// null if players are still in a lobby etc., no need to show a warning
return;
}
if (conn.clientOwnedObjects != null)
{
var tmp = new HashSet<NetworkInstanceId>(conn.clientOwnedObjects);
HashSet<NetworkInstanceId> tmp = new HashSet<NetworkInstanceId>(conn.clientOwnedObjects);
foreach (var netId in tmp)
{
var obj = FindLocalObject(netId);
@ -1084,24 +1042,12 @@ public static void DestroyPlayersForConnection(NetworkConnection conn)
}
}
for (int i = 0; i < conn.playerControllers.Count; i++)
if (conn.playerController != null)
{
var player = conn.playerControllers[i];
if (player.IsValid)
{
if (player.unetView == null)
{
// the playerController's object has been destroyed, but RemovePlayerForConnection was never called.
// this is ok, just dont double destroy it.
}
else
{
DestroyObject(player.unetView, true);
}
player.gameObject = null;
}
DestroyObject(conn.playerController, true);
}
conn.playerControllers.Clear();
conn.RemovePlayerController();
}
static void UnSpawnObject(GameObject obj)

View File

@ -1,36 +0,0 @@
using System;
using UnityEngine;
namespace Mirror
{
// This class represents the player entity in a network game, there can be multiple players per client
// when there are multiple people playing on one machine
// The server has one connection per client, and the connection has the player instances of that client
// The client has player instances as member variables (should this be removed and just go though the connection like the server does?)
public class PlayerController
{
public short playerControllerId = -1;
public NetworkIdentity unetView;
public GameObject gameObject;
public const int MaxPlayersPerClient = 32;
public PlayerController()
{
}
public bool IsValid { get { return playerControllerId != -1; } }
internal PlayerController(GameObject go, short playerControllerId)
{
gameObject = go;
unetView = go.GetComponent<NetworkIdentity>();
this.playerControllerId = playerControllerId;
}
public override string ToString()
{
return string.Format("ID={0} NetworkIdentity NetID={1} Player={2}", new object[] { playerControllerId, (unetView != null ? unetView.netId.ToString() : "null"), (gameObject != null ? gameObject.name : "null") });
}
}
}

View File

@ -80,7 +80,6 @@ class Weaver
public static MethodReference MemoryStreamCtor;
public static MethodReference getComponentReference;
public static MethodReference getUNetIdReference;
public static MethodReference getPlayerIdReference;
public static TypeReference NetworkIdentityType;
public static TypeReference NetworkInstanceIdType;
public static TypeReference NetworkSceneIdType;
@ -1446,7 +1445,6 @@ static void SetupTargetTypes()
gameObjectInequality = ResolveMethod(unityObjectType, "op_Inequality");
UBehaviourIsServer = ResolveMethod(NetworkBehaviourType, "get_isServer");
getPlayerIdReference = ResolveMethod(NetworkBehaviourType, "get_playerControllerId");
setSyncVarReference = ResolveMethod(NetworkBehaviourType, "SetSyncVar");
setSyncVarHookGuard = ResolveMethod(NetworkBehaviourType, "set_syncVarHookGuard");
getSyncVarHookGuard = ResolveMethod(NetworkBehaviourType, "get_syncVarHookGuard");