in MRTK Tutorials/Assets/Photon/PhotonUnityNetworking/Code/PhotonNetworkPart.cs [2183:2442]
private static void OnEvent(EventData photonEvent)
{
int actorNr = photonEvent.Sender;
Player originatingPlayer = null;
if (actorNr > 0 && NetworkingClient.CurrentRoom != null)
{
originatingPlayer = NetworkingClient.CurrentRoom.GetPlayer(actorNr);
}
switch (photonEvent.Code)
{
case EventCode.Join:
ResetPhotonViewsOnSerialize();
break;
case PunEvent.RPC:
ExecuteRpc(photonEvent.CustomData as Hashtable, originatingPlayer);
break;
case PunEvent.SendSerialize:
case PunEvent.SendSerializeReliable:
// Debug.Log(photonEvent.ToStringFull());
/* This case must match definition in RunViewUpdate() and OnSerializeWrite().
* Format of the event's data object[]:
* [0] = PhotonNetwork.ServerTimestamp;
* [1] = currentLevelPrefix; OPTIONAL!
* [2] = object[] of PhotonView x
* [3] = object[] of PhotonView y or NULL
* [...]
*
* We only combine updates for XY objects into one RaiseEvent to avoid fragmentation.
* The Reliability and Interest Group are only used for RaiseEvent and not contained in the event/data that reaches the other clients.
* This is read in OnEvent().
*/
object[] pvUpdates = (object[])photonEvent[ParameterCode.Data];
int remoteUpdateServerTimestamp = (int)pvUpdates[0];
short remoteLevelPrefix = (pvUpdates[1] != null) ? (byte)pvUpdates[1] : (short)0;
object[] viewUpdate = null;
for (int i = 2; i < pvUpdates.Length; i++)
{
viewUpdate = pvUpdates[i] as object[];
if (viewUpdate == null)
{
break;
}
OnSerializeRead(viewUpdate, originatingPlayer, remoteUpdateServerTimestamp, remoteLevelPrefix);
}
break;
case PunEvent.Instantiation:
NetworkInstantiate((Hashtable)photonEvent.CustomData, originatingPlayer);
break;
case PunEvent.CloseConnection:
// MasterClient "requests" a disconnection from us
if (originatingPlayer == null || !originatingPlayer.IsMasterClient)
{
Debug.LogError("Error: Someone else(" + originatingPlayer + ") then the masterserver requests a disconnect!");
}
else
{
PhotonNetwork.LeaveRoom(false);
}
break;
case PunEvent.DestroyPlayer:
Hashtable evData = (Hashtable)photonEvent.CustomData;
int targetPlayerId = (int)evData[keyByteZero];
if (targetPlayerId >= 0)
{
DestroyPlayerObjects(targetPlayerId, true);
}
else
{
DestroyAll(true);
}
break;
case EventCode.Leave:
// destroy objects & buffered messages
if (CurrentRoom != null && CurrentRoom.AutoCleanUp && (originatingPlayer == null || !originatingPlayer.IsInactive))
{
DestroyPlayerObjects(actorNr, true);
}
break;
case PunEvent.Destroy:
evData = (Hashtable)photonEvent.CustomData;
int instantiationId = (int)evData[keyByteZero];
// Debug.Log("Ev Destroy for viewId: " + instantiationId + " sent by owner: " + (instantiationId / PhotonNetwork.MAX_VIEW_IDS == actorNr) + " this client is owner: " + (instantiationId / PhotonNetwork.MAX_VIEW_IDS == this.LocalPlayer.ID));
PhotonView pvToDestroy = null;
if (photonViewList.TryGetValue(instantiationId, out pvToDestroy))
{
RemoveInstantiatedGO(pvToDestroy.gameObject, true);
}
else
{
Debug.LogError("Ev Destroy Failed. Could not find PhotonView with instantiationId " + instantiationId + ". Sent by actorNr: " + actorNr);
}
break;
case PunEvent.OwnershipRequest:
{
int[] requestValues = (int[])photonEvent.CustomData;
int requestedViewId = requestValues[0];
int requestedFromOwnerId = requestValues[1];
PhotonView requestedView = GetPhotonView(requestedViewId);
if (requestedView == null)
{
Debug.LogWarning("Can't find PhotonView of incoming OwnershipRequest. ViewId not found: " + requestedViewId);
break;
}
if (PhotonNetwork.LogLevel == PunLogLevel.Informational)
{
Debug.Log(string.Format("OwnershipRequest. actorNr {0} requests view {1} from {2}. current pv owner: {3} is {4}. isMine: {6} master client: {5}", actorNr, requestedViewId, requestedFromOwnerId, requestedView.OwnerActorNr, requestedView.IsOwnerActive ? "active" : "inactive", MasterClient.ActorNumber, requestedView.IsMine));
}
switch (requestedView.OwnershipTransfer)
{
case OwnershipOption.Takeover:
int currentPvOwnerId = requestedView.OwnerActorNr;
if (requestedFromOwnerId == currentPvOwnerId || (requestedFromOwnerId == 0 && currentPvOwnerId == MasterClient.ActorNumber) || currentPvOwnerId == 0)
{
// a takeover is successful automatically, if taken from current owner
Player prevOwner = requestedView.Owner;
requestedView.OwnerActorNr = actorNr;
requestedView.ControllerActorNr = actorNr;
if (PhotonNetwork.OnOwnershipTransferedEv != null)
{
PhotonNetwork.OnOwnershipTransferedEv(requestedView, prevOwner);
}
}
else
{
if (PhotonNetwork.OnOwnershipTransferFailedEv != null)
{
PhotonNetwork.OnOwnershipTransferFailedEv(requestedView, originatingPlayer);
}
//Debug.LogWarning("requestedView.OwnershipTransfer was ignored! ");
}
break;
case OwnershipOption.Request:
if (PhotonNetwork.OnOwnershipRequestEv != null)
{
PhotonNetwork.OnOwnershipRequestEv(requestedView, originatingPlayer);
}
break;
default:
Debug.LogWarning("Ownership mode == " + (requestedView.OwnershipTransfer) + ". Ignoring request.");
break;
}
}
break;
case PunEvent.OwnershipTransfer:
{
int[] transferViewToUserID = (int[])photonEvent.CustomData;
int requestedViewId = transferViewToUserID[0];
int newOwnerId = transferViewToUserID[1];
if (PhotonNetwork.LogLevel >= PunLogLevel.Informational)
{
Debug.Log("Ev OwnershipTransfer. ViewID " + requestedViewId + " to: " + newOwnerId + " Time: " + Environment.TickCount % 1000);
}
PhotonView requestedView = GetPhotonView(requestedViewId);
if (requestedView != null)
{
// Only apply this if pv allows Takeover, or allows Request and this message originates from the controller or owner.
if (requestedView.OwnershipTransfer == OwnershipOption.Takeover ||
(requestedView.OwnershipTransfer == OwnershipOption.Request && (originatingPlayer == requestedView.Controller || originatingPlayer == requestedView.Owner)))
{
Player prevOwner = requestedView.Owner;
requestedView.OwnerActorNr= newOwnerId;
requestedView.ControllerActorNr = newOwnerId;
if (PhotonNetwork.OnOwnershipTransferedEv != null)
{
PhotonNetwork.OnOwnershipTransferedEv(requestedView, prevOwner);
}
}
else if (PhotonNetwork.LogLevel >= PunLogLevel.Informational)
{
if (requestedView.OwnershipTransfer == OwnershipOption.Request)
Debug.Log("Failed incoming OwnershipTransfer attempt for '" + requestedView.name + "; " + requestedViewId +
" - photonView has OwnershipTransfer set to OwnershipOption.Request, but Player attempting to change owner is not the current owner/controller.");
else
Debug.Log("Failed incoming OwnershipTransfer attempt for '" + requestedView.name + "; " + requestedViewId +
" - photonView has OwnershipTransfer set to OwnershipOption.Fixed.");
}
}
else if (PhotonNetwork.LogLevel >= PunLogLevel.ErrorsOnly)
{
Debug.LogErrorFormat("Failed to find a PhotonView with ID={0} for incoming OwnershipTransfer event (newOwnerActorNumber={1}), sender={2}",
requestedViewId, newOwnerId, actorNr);
}
break;
}
case PunEvent.OwnershipUpdate:
{
reusablePVHashset.Clear();
// Deserialize the list of exceptions, these are views on the master who's Owner and Creator didn't match.
int[] viewOwnerPair = (int[])photonEvent.CustomData;
for (int i = 0, cnt = viewOwnerPair.Length; i < cnt; i++)
{
int viewId = viewOwnerPair[i];
i++;
int newOwnerId = viewOwnerPair[i];
PhotonView view = GetPhotonView(viewId);
Player prevOwner = view.Owner;
Player newOwner = CurrentRoom.GetPlayer(newOwnerId, true);
view.OwnerActorNr= newOwnerId;
view.ControllerActorNr = newOwnerId;
reusablePVHashset.Add(view);
// If this produces an owner change locally, fire the OnOwnershipTransfered callbacks
if (PhotonNetwork.OnOwnershipTransferedEv != null && newOwner != prevOwner)
{
PhotonNetwork.OnOwnershipTransferedEv(view, prevOwner);
}
}
// Initialize all views. Typically this is just fired on a new client after it joins a room and gets the first OwnershipUpdate from the Master.
// This was moved from PhotonHandler OnJoinedRoom to here, to allow objects to retain controller = -1 until an controller is actually known.
foreach (var view in PhotonViewCollection)
{
if (!reusablePVHashset.Contains(view))
view.RebuildControllerCache();
}
break;
}
}
}