PlayerProperties
How do I use Player Properties
Below are practical examples compiled from projects for learning and reference purposes
Featured Snippets
File name: LoadbalancingPeer.cs
Copy
86 public virtual bool OpCreateRoom(string roomName, RoomOptions roomOptions, TypedLobby lobby, Hashtable playerProperties, bool onGameServer)
87 {
88 if (this.DebugOut >= DebugLevel.INFO)
89 {
90 this.Listener.DebugReturn(DebugLevel.INFO, "OpCreateRoom()");
91 }
92
93 Dictionary
94
95 if (!string.IsNullOrEmpty(roomName))
96 {
97 op[ParameterCode.RoomName] = roomName;
98 }
99 if (lobby != null)
100 {
101 op[ParameterCode.LobbyName] = lobby.Name;
102 op[ParameterCode.LobbyType] = (byte)lobby.Type;
103 }
104
105 if (onGameServer)
106 {
107 if (playerProperties != null && playerProperties.Count > 0)
108 {
109 op[ParameterCode.PlayerProperties] = playerProperties;
110 op[ParameterCode.Broadcast] = true; // TODO: check if this also makes sense when creating a room?! // broadcast actor properties
111 }
112
113
114 if (roomOptions == null)
115 {
116 roomOptions = new RoomOptions();
117 }
118
119 Hashtable gameProperties = new Hashtable();
120 op[ParameterCode.GameProperties] = gameProperties;
121 gameProperties.MergeStringKeys(roomOptions.customRoomProperties);
122
123 gameProperties[GameProperties.IsOpen] = roomOptions.isOpen; // TODO: check default value. dont send this then
124 gameProperties[GameProperties.IsVisible] = roomOptions.isVisible; // TODO: check default value. dont send this then
125 gameProperties[GameProperties.PropsListedInLobby] = roomOptions.customRoomPropertiesForLobby;
126 if (roomOptions.maxPlayers > 0)
127 {
128 gameProperties[GameProperties.MaxPlayers] = roomOptions.maxPlayers;
129 }
130 if (roomOptions.cleanupCacheOnLeave)
131 {
132 op[ParameterCode.CleanupCacheOnLeave] = true; // this is actually setting the room's config
133 gameProperties[GameProperties.CleanupCacheOnLeave] = true; // this is only informational for the clients which join
134 }
135 }
136
137 // UnityEngine.Debug.Log("CreateGame: " + SupportClass.DictionaryToString(op));
138 return this.OpCustom(OperationCode.CreateGame, op, true);
139 }
File name: LoadbalancingPeer.cs
Copy
143 public virtual bool OpJoinRoom(string roomName, RoomOptions roomOptions, TypedLobby lobby, bool createIfNotExists, Hashtable playerProperties, bool onGameServer)
144 {
145 Dictionary
146
147 if (!string.IsNullOrEmpty(roomName))
148 {
149 op[ParameterCode.RoomName] = roomName;
150 }
151 if (createIfNotExists)
152 {
153 op[ParameterCode.CreateIfNotExists] = true;
154 if (lobby != null)
155 {
156 op[ParameterCode.LobbyName] = lobby.Name;
157 op[ParameterCode.LobbyType] = (byte)lobby.Type;
158 }
159 }
160
161 if (onGameServer)
162 {
163 if (playerProperties != null && playerProperties.Count > 0)
164 {
165 op[ParameterCode.PlayerProperties] = playerProperties;
166 op[ParameterCode.Broadcast] = true; // broadcast actor properties
167 }
168
169
170 if (createIfNotExists)
171 {
172 if (roomOptions == null)
173 {
174 roomOptions = new RoomOptions();
175 }
176
177 Hashtable gameProperties = new Hashtable();
178 op[ParameterCode.GameProperties] = gameProperties;
179 gameProperties.MergeStringKeys(roomOptions.customRoomProperties);
180
181 gameProperties[GameProperties.IsOpen] = roomOptions.isOpen;
182 gameProperties[GameProperties.IsVisible] = roomOptions.isVisible;
183 gameProperties[GameProperties.PropsListedInLobby] = roomOptions.customRoomPropertiesForLobby;
184 if (roomOptions.maxPlayers > 0)
185 {
186 gameProperties[GameProperties.MaxPlayers] = roomOptions.maxPlayers;
187 }
188 if (roomOptions.cleanupCacheOnLeave)
189 {
190 op[ParameterCode.CleanupCacheOnLeave] = true; // this is actually setting the room's config
191 gameProperties[GameProperties.CleanupCacheOnLeave] = true; // this is only informational for the clients which join
192 }
193 }
194 }
195
196 // UnityEngine.Debug.Log("JoinGame: " + SupportClass.DictionaryToString(op));
197 return this.OpCustom(OperationCode.JoinGame, op, true);
198 }
File name: LoadbalancingPeer.cs
Copy
212 public virtual bool OpJoinRandomRoom(Hashtable expectedCustomRoomProperties, byte expectedMaxPlayers, Hashtable playerProperties, MatchmakingMode matchingType, TypedLobby typedLobby, string sqlLobbyFilter)
213 {
214 if (this.DebugOut >= DebugLevel.INFO)
215 {
216 this.Listener.DebugReturn(DebugLevel.INFO, "OpJoinRandomRoom()");
217 }
218
219 Hashtable expectedRoomProperties = new Hashtable();
220 expectedRoomProperties.MergeStringKeys(expectedCustomRoomProperties);
221 if (expectedMaxPlayers > 0)
222 {
223 expectedRoomProperties[GameProperties.MaxPlayers] = expectedMaxPlayers;
224 }
225
226 Dictionary
227 if (expectedRoomProperties.Count > 0)
228 {
229 opParameters[ParameterCode.GameProperties] = expectedRoomProperties;
230 }
231
232 if (playerProperties != null && playerProperties.Count > 0)
233 {
234 opParameters[ParameterCode.PlayerProperties] = playerProperties;
235 }
236
237 if (matchingType != MatchmakingMode.FillRoom)
238 {
239 opParameters[ParameterCode.MatchMakingType] = (byte)matchingType;
240 }
241
242 if (typedLobby != null)
243 {
244 opParameters[ParameterCode.LobbyName] = typedLobby.Name;
245 opParameters[ParameterCode.LobbyType] = (byte)typedLobby.Type;
246 }
247
248 if (!string.IsNullOrEmpty(sqlLobbyFilter))
249 {
250 opParameters[ParameterCode.Data] = sqlLobbyFilter;
251 }
252
253 // UnityEngine.Debug.LogWarning("OpJoinRandom: " + opParameters.ToStringFull());
254 return this.OpCustom(OperationCode.JoinRandomGame, opParameters, true);
255 }
File name: NetworkingPeer.cs
Copy
530 // joins a room and sets your current username as custom actorproperty (will broadcast that)
536 private void ReadoutProperties(Hashtable gameProperties, Hashtable pActorProperties, int targetActorNr)
537 {
538 // Debug.LogWarning("ReadoutProperties gameProperties: " + gameProperties.ToStringFull() + " pActorProperties: " + pActorProperties.ToStringFull() + " targetActorNr: " + targetActorNr);
539 // read game properties and cache them locally
540 if (this.mCurrentGame != null && gameProperties != null)
541 {
542 this.mCurrentGame.CacheProperties(gameProperties);
543 SendMonoMessage(PhotonNetworkingMessage.OnPhotonCustomRoomPropertiesChanged, gameProperties);
544 if (PhotonNetwork.automaticallySyncScene)
545 {
546 this.LoadLevelIfSynced(); // will load new scene if sceneName was changed
547 }
548 }
549
550 if (pActorProperties != null && pActorProperties.Count > 0)
551 {
552 if (targetActorNr > 0)
553 {
554 // we have a single entry in the pActorProperties with one
555 // user's name
556 // targets MUST exist before you set properties
557 PhotonPlayer target = this.GetPlayerWithID(targetActorNr);
558 if (target != null)
559 {
560 Hashtable props = this.GetActorPropertiesForActorNr(pActorProperties, targetActorNr);
561 target.InternalCacheProperties(props);
562 SendMonoMessage(PhotonNetworkingMessage.OnPhotonPlayerPropertiesChanged, target, props);
563 }
564 }
565 else
566 {
567 // in this case, we've got a key-value pair per actor (each
568 // value is a hashtable with the actor's properties then)
569 int actorNr;
570 Hashtable props;
571 string newName;
572 PhotonPlayer target;
573
574 foreach (object key in pActorProperties.Keys)
575 {
576 actorNr = (int)key;
577 props = (Hashtable)pActorProperties[key];
578 newName = (string)props[ActorProperties.PlayerName];
579
580 target = this.GetPlayerWithID(actorNr);
581 if (target == null)
582 {
583 target = new PhotonPlayer(false, actorNr, newName);
584 this.AddNewPlayer(actorNr, target);
585 }
586
587 target.InternalCacheProperties(props);
588 SendMonoMessage(PhotonNetworkingMessage.OnPhotonPlayerPropertiesChanged, target, props);
589 }
590 }
591 }
592 }
File name: NetworkingPeer.cs
Copy
822 private void GameEnteredOnGameServer(OperationResponse operationResponse)
823 {
824 if (operationResponse.ReturnCode != 0)
825 {
826 switch (operationResponse.OperationCode)
827 {
828 case OperationCode.CreateGame:
829 if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational)
830 {
831 Debug.Log("Create failed on GameServer. Changing back to MasterServer. Msg: " + operationResponse.DebugMessage);
832 }
833 SendMonoMessage(PhotonNetworkingMessage.OnPhotonCreateRoomFailed, operationResponse.ReturnCode, operationResponse.DebugMessage);
834 break;
835 case OperationCode.JoinGame:
836 if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational)
837 {
838 Debug.Log("Join failed on GameServer. Changing back to MasterServer. Msg: " + operationResponse.DebugMessage);
839 if (operationResponse.ReturnCode == ErrorCode.GameDoesNotExist)
840 {
841 Debug.Log("Most likely the game became empty during the switch to GameServer.");
842 }
843 }
844 SendMonoMessage(PhotonNetworkingMessage.OnPhotonJoinRoomFailed, operationResponse.ReturnCode, operationResponse.DebugMessage);
845 break;
846 case OperationCode.JoinRandomGame:
847 if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational)
848 {
849 Debug.Log("Join failed on GameServer. Changing back to MasterServer. Msg: " + operationResponse.DebugMessage);
850 if (operationResponse.ReturnCode == ErrorCode.GameDoesNotExist)
851 {
852 Debug.Log("Most likely the game became empty during the switch to GameServer.");
853 }
854 }
855 SendMonoMessage(PhotonNetworkingMessage.OnPhotonRandomJoinFailed, operationResponse.ReturnCode, operationResponse.DebugMessage);
856 break;
857 }
858
859 this.DisconnectToReconnect();
860 return;
861 }
862
863 this.State = global::PeerState.Joined;
864 this.mRoomToGetInto.isLocalClientInside = true;
865
866 Hashtable actorProperties = (Hashtable)operationResponse[ParameterCode.PlayerProperties];
867 Hashtable gameProperties = (Hashtable)operationResponse[ParameterCode.GameProperties];
868 this.ReadoutProperties(gameProperties, actorProperties, 0);
869
870 // the local player's actor-properties are not returned in join-result. add this player to the list
871 int localActorNr = (int)operationResponse[ParameterCode.ActorNr];
872
873 this.ChangeLocalID(localActorNr);
874 this.CheckMasterClient(-1);
875
876 if (this.mPlayernameHasToBeUpdated)
877 {
878 this.SendPlayerName();
879 }
880
881 switch (operationResponse.OperationCode)
882 {
883 case OperationCode.CreateGame:
884 SendMonoMessage(PhotonNetworkingMessage.OnCreatedRoom);
885 break;
886 case OperationCode.JoinGame:
887 case OperationCode.JoinRandomGame:
888 // the mono message for this is sent at another place
889 break;
890 }
891 }
File name: NetworkingPeer.cs
Copy
968 public override bool OpJoinRandomRoom(Hashtable expectedCustomRoomProperties, byte expectedMaxPlayers, Hashtable playerProperties, MatchmakingMode matchingType, TypedLobby typedLobby, string sqlLobbyFilter)
969 {
970 this.mRoomToGetInto = new Room(null, null);
971 this.mRoomToEnterLobby = null; // join random never stores the lobby. the following join will not affect the room lobby
972 // if typedLobby is null, the server will automatically use the active lobby or default, which is what we want anyways
973
974 this.mLastJoinType = JoinType.JoinRandomGame;
975 return base.OpJoinRandomRoom(expectedCustomRoomProperties, expectedMaxPlayers, playerProperties, matchingType, typedLobby, sqlLobbyFilter);
976 }
File name: NetworkingPeer.cs
Copy
1016 public void OnOperationResponse(OperationResponse operationResponse)
1017 {
1018 if (PhotonNetwork.networkingPeer.State == global::PeerState.Disconnecting)
1019 {
1020 if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational)
1021 {
1022 Debug.Log("OperationResponse ignored while disconnecting. Code: " + operationResponse.OperationCode);
1023 }
1024 return;
1025 }
1026
1027 // extra logging for error debugging (helping developers with a bit of automated analysis)
1028 if (operationResponse.ReturnCode == 0)
1029 {
1030 if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational)
1031 Debug.Log(operationResponse.ToString());
1032 }
1033 else
1034 {
1035 if (operationResponse.ReturnCode == ErrorCode.OperationNotAllowedInCurrentState)
1036 {
1037 Debug.LogError("Operation " + operationResponse.OperationCode + " could not be executed (yet). Wait for state JoinedLobby or ConnectedToMaster and their callbacks before calling operations. WebRPCs need a server-side configuration. Enum OperationCode helps identify the operation.");
1038 }
1039 else if (operationResponse.ReturnCode == ErrorCode.WebHookCallFailed)
1040 {
1041 Debug.LogError("Operation " + operationResponse.OperationCode + " failed in a server-side plugin. Check the configuration in the Dashboard. Message from server-plugin: " + operationResponse.DebugMessage);
1042 }
1043 else if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational)
1044 {
1045 Debug.LogError("Operation failed: " + operationResponse.ToStringFull() + " Server: " + this.server);
1046 }
1047 }
1048
1049 // use the "secret" or "token" whenever we get it. doesn't really matter if it's in AuthResponse.
1050 if (operationResponse.Parameters.ContainsKey(ParameterCode.Secret))
1051 {
1052 if (this.CustomAuthenticationValues == null)
1053 {
1054 this.CustomAuthenticationValues = new AuthenticationValues();
1055 // this.DebugReturn(DebugLevel.ERROR, "Server returned secret. Created CustomAuthenticationValues.");
1056 }
1057
1058 this.CustomAuthenticationValues.Secret = operationResponse[ParameterCode.Secret] as string;
1059 }
1060
1061 switch (operationResponse.OperationCode)
1062 {
1063 case OperationCode.Authenticate:
1064 {
1065 // PeerState oldState = this.State;
1066
1067 if (operationResponse.ReturnCode != 0)
1068 {
1069 if (operationResponse.ReturnCode == ErrorCode.InvalidOperationCode)
1070 {
1071 Debug.LogError(string.Format("If you host Photon yourself, make sure to start the 'Instance LoadBalancing' "+ this.ServerAddress));
1072 }
1073 else if (operationResponse.ReturnCode == ErrorCode.InvalidAuthentication)
1074 {
1075 Debug.LogError(string.Format("The appId this client sent is unknown on the server (Cloud). Check settings. If using the Cloud, check account."));
1076 SendMonoMessage(PhotonNetworkingMessage.OnFailedToConnectToPhoton, DisconnectCause.InvalidAuthentication);
1077 }
1078 else if (operationResponse.ReturnCode == ErrorCode.CustomAuthenticationFailed)
1079 {
1080 Debug.LogError(string.Format("Custom Authentication failed (either due to user-input or configuration or AuthParameter string format). Calling: OnCustomAuthenticationFailed()"));
1081 SendMonoMessage(PhotonNetworkingMessage.OnCustomAuthenticationFailed, operationResponse.DebugMessage);
1082 }
1083 else
1084 {
1085 Debug.LogError(string.Format("Authentication failed: '{0}' Code: {1}", operationResponse.DebugMessage, operationResponse.ReturnCode));
1086 }
1087
1088 this.State = global::PeerState.Disconnecting;
1089 this.Disconnect();
1090
1091 if (operationResponse.ReturnCode == ErrorCode.MaxCcuReached)
1092 {
1093 if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational)
1094 Debug.LogWarning(string.Format("Currently, the limit of users is reached for this title. Try again later. Disconnecting"));
1095 SendMonoMessage(PhotonNetworkingMessage.OnPhotonMaxCccuReached);
1096 SendMonoMessage(PhotonNetworkingMessage.OnConnectionFail, DisconnectCause.MaxCcuReached);
1097 }
1098 else if (operationResponse.ReturnCode == ErrorCode.InvalidRegion)
1099 {
1100 if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational)
1101 Debug.LogError(string.Format("The used master server address is not available with the subscription currently used. Got to Photon Cloud Dashboard or change URL. Disconnecting."));
1102 SendMonoMessage(PhotonNetworkingMessage.OnConnectionFail, DisconnectCause.InvalidRegion);
1103 }
1104 else if (operationResponse.ReturnCode == ErrorCode.AuthenticationTicketExpired)
1105 {
1106 if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational)
1107 Debug.LogError(string.Format("The authentication ticket expired. You need to connect (and authenticate) again. Disconnecting."));
1108 SendMonoMessage(PhotonNetworkingMessage.OnConnectionFail, DisconnectCause.AuthenticationTicketExpired);
1109 }
1110 break;
1111 }
1112 else
1113 {
1114 if (this.server == ServerConnection.NameServer)
1115 {
1116 // on the NameServer, authenticate returns the MasterServer address for a region and we hop off to there
1117 this.MasterServerAddress = operationResponse[ParameterCode.Address] as string;
1118 this.DisconnectToReconnect();
1119 }
1120 else if (this.server == ServerConnection.MasterServer)
1121 {
1122 if (PhotonNetwork.autoJoinLobby)
1123 {
1124 this.State = global::PeerState.Authenticated;
1125 this.OpJoinLobby(this.lobby);
1126 }
1127 else
1128 {
1129 this.State = global::PeerState.ConnectedToMaster;
1130 NetworkingPeer.SendMonoMessage(PhotonNetworkingMessage.OnConnectedToMaster);
1131 }
1132 }
1133 else if (this.server == ServerConnection.GameServer)
1134 {
1135 this.State = global::PeerState.Joining;
1136
1137 if (this.mLastJoinType == JoinType.JoinGame || this.mLastJoinType == JoinType.JoinRandomGame || this.mLastJoinType == JoinType.JoinOrCreateOnDemand)
1138 {
1139 // if we just "join" the game, do so. if we wanted to "create the room on demand", we have to send this to the game server as well.
1140 this.OpJoinRoom(this.mRoomToGetInto.name, this.mRoomOptionsForCreate, this.mRoomToEnterLobby, this.mLastJoinType == JoinType.JoinOrCreateOnDemand);
1141 }
1142 else if (this.mLastJoinType == JoinType.CreateGame)
1143 {
1144 // on the game server, we have to apply the room properties that were chosen for creation of the room, so we use this.mRoomToGetInto
1145 this.OpCreateGame(this.mRoomToGetInto.name, this.mRoomOptionsForCreate, this.mRoomToEnterLobby);
1146 }
1147
1148 break;
1149 }
1150 }
1151 break;
1152 }
1153
1154 case OperationCode.GetRegions:
1155 // Debug.Log("GetRegions returned: " + operationResponse.ToStringFull());
1156
1157 if (operationResponse.ReturnCode == ErrorCode.InvalidAuthentication)
1158 {
1159 Debug.LogError(string.Format("The appId this client sent is unknown on the server (Cloud). Check settings. If using the Cloud, check account."));
1160 SendMonoMessage(PhotonNetworkingMessage.OnFailedToConnectToPhoton, DisconnectCause.InvalidAuthentication);
1161
1162 this.State = global::PeerState.Disconnecting;
1163 this.Disconnect();
1164 return;
1165 }
1166
1167 string[] regions = operationResponse[ParameterCode.Region] as string[];
1168 string[] servers = operationResponse[ParameterCode.Address] as string[];
1169
1170 if (regions == null || servers == null || regions.Length != servers.Length)
1171 {
1172 Debug.LogError("The region arrays from Name Server are not ok. Must be non-null and same length.");
1173 break;
1174 }
1175
1176 this.AvailableRegions = new List
1177 for (int i = 0; i < regions.Length; i++)
1178 {
1179 string regionCodeString = regions[i];
1180 if (string.IsNullOrEmpty(regionCodeString))
1181 {
1182 continue;
1183 }
1184 regionCodeString = regionCodeString.ToLower();
1185
1186 CloudRegionCode code = Region.Parse(regionCodeString);
1187 this.AvailableRegions.Add(new Region() { Code = code, HostAndPort = servers[i] });
1188 }
1189
1190 // PUN assumes you fetch the name-server's list of regions to ping them
1191 if (PhotonNetwork.PhotonServerSettings.HostType == ServerSettings.HostingOption.BestRegion)
1192 {
1193 PhotonHandler.PingAvailableRegionsAndConnectToBest();
1194 }
1195 break;
1196
1197 case OperationCode.CreateGame:
1198 {
1199 if (this.server == ServerConnection.GameServer)
1200 {
1201 this.GameEnteredOnGameServer(operationResponse);
1202 }
1203 else
1204 {
1205 if (operationResponse.ReturnCode != 0)
1206 {
1207 if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational)
1208 Debug.LogWarning(string.Format("CreateRoom failed, client stays on masterserver: {0}.", operationResponse.ToStringFull()));
1209
1210 SendMonoMessage(PhotonNetworkingMessage.OnPhotonCreateRoomFailed);
1211 break;
1212 }
1213
1214 string gameID = (string) operationResponse[ParameterCode.RoomName];
1215 if (!string.IsNullOrEmpty(gameID))
1216 {
1217 // is only sent by the server's response, if it has not been
1218 // sent with the client's request before!
1219 this.mRoomToGetInto.name = gameID;
1220 }
1221
1222 this.mGameserver = (string)operationResponse[ParameterCode.Address];
1223 this.DisconnectToReconnect();
1224 }
1225
1226 break;
1227 }
1228
1229 case OperationCode.JoinGame:
1230 {
1231 if (this.server != ServerConnection.GameServer)
1232 {
1233 if (operationResponse.ReturnCode != 0)
1234 {
1235 if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational)
1236 Debug.Log(string.Format("JoinRoom failed (room maybe closed by now). Client stays on masterserver: {0}. State: {1}", operationResponse.ToStringFull(), this.State));
1237
1238 SendMonoMessage(PhotonNetworkingMessage.OnPhotonJoinRoomFailed);
1239 break;
1240 }
1241
1242 this.mGameserver = (string)operationResponse[ParameterCode.Address];
1243 this.DisconnectToReconnect();
1244 }
1245 else
1246 {
1247 this.GameEnteredOnGameServer(operationResponse);
1248 }
1249
1250 break;
1251 }
1252
1253 case OperationCode.JoinRandomGame:
1254 {
1255 // happens only on master. on gameserver, this is a regular join (we don't need to find a random game again)
1256 // the operation OpJoinRandom either fails (with returncode 8) or returns game-to-join information
1257 if (operationResponse.ReturnCode != 0)
1258 {
1259 if (operationResponse.ReturnCode == ErrorCode.NoRandomMatchFound)
1260 {
1261 if (PhotonNetwork.logLevel >= PhotonLogLevel.Full)
1262 Debug.Log("JoinRandom failed: No open game. Calling: OnPhotonRandomJoinFailed() and staying on master server.");
1263 }
1264 else if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational)
1265 {
1266 Debug.LogWarning(string.Format("JoinRandom failed: {0}.", operationResponse.ToStringFull()));
1267 }
1268
1269 SendMonoMessage(PhotonNetworkingMessage.OnPhotonRandomJoinFailed, operationResponse.ReturnCode, operationResponse.DebugMessage);
1270 break;
1271 }
1272
1273 string roomName = (string)operationResponse[ParameterCode.RoomName];
1274 this.mRoomToGetInto.name = roomName;
1275 this.mGameserver = (string)operationResponse[ParameterCode.Address];
1276 this.DisconnectToReconnect();
1277 break;
1278 }
1279
1280 case OperationCode.JoinLobby:
1281 this.State = global::PeerState.JoinedLobby;
1282 this.insideLobby = true;
1283 SendMonoMessage(PhotonNetworkingMessage.OnJoinedLobby);
1284
1285 // this.mListener.joinLobbyReturn();
1286 break;
1287 case OperationCode.LeaveLobby:
1288 this.State = global::PeerState.Authenticated;
1289 this.LeftLobbyCleanup(); // will set insideLobby = false
1290 break;
1291
1292 case OperationCode.Leave:
1293 this.DisconnectToReconnect();
1294 break;
1295
1296 case OperationCode.SetProperties:
1297 // this.mListener.setPropertiesReturn(returnCode, debugMsg);
1298 break;
1299
1300 case OperationCode.GetProperties:
1301 {
1302 Hashtable actorProperties = (Hashtable)operationResponse[ParameterCode.PlayerProperties];
1303 Hashtable gameProperties = (Hashtable)operationResponse[ParameterCode.GameProperties];
1304 this.ReadoutProperties(gameProperties, actorProperties, 0);
1305
1306 // RemoveByteTypedPropertyKeys(actorProperties, false);
1307 // RemoveByteTypedPropertyKeys(gameProperties, false);
1308 // this.mListener.getPropertiesReturn(gameProperties, actorProperties, returnCode, debugMsg);
1309 break;
1310 }
1311
1312 case OperationCode.RaiseEvent:
1313 // this usually doesn't give us a result. only if the caching is affected the server will send one.
1314 break;
1315
1316 case OperationCode.FindFriends:
1317 bool[] onlineList = operationResponse[ParameterCode.FindFriendsResponseOnlineList] as bool[];
1318 string[] roomList = operationResponse[ParameterCode.FindFriendsResponseRoomIdList] as string[];
1319
1320 if (onlineList != null && roomList != null && this.friendListRequested != null && onlineList.Length == this.friendListRequested.Length)
1321 {
1322 List
1323 for (int index = 0; index < this.friendListRequested.Length; index++)
1324 {
1325 FriendInfo friend = new FriendInfo();
1326 friend.Name = this.friendListRequested[index];
1327 friend.Room = roomList[index];
1328 friend.IsOnline = onlineList[index];
1329 friendList.Insert(index, friend);
1330 }
1331 PhotonNetwork.Friends = friendList;
1332 }
1333 else
1334 {
1335 // any of the lists is null and shouldn't. print a error
1336 Debug.LogError("FindFriends failed to apply the result, as a required value wasn't provided or the friend list length differed from result.");
1337 }
1338
1339 this.friendListRequested = null;
1340 this.isFetchingFriends = false;
1341 this.friendListTimestamp = Environment.TickCount;
1342 if (this.friendListTimestamp == 0)
1343 {
1344 this.friendListTimestamp = 1; // makes sure the timestamp is not accidentally 0
1345 }
1346
1347 SendMonoMessage(PhotonNetworkingMessage.OnUpdatedFriendList);
1348 break;
1349
1350 case OperationCode.WebRpc:
1351 SendMonoMessage(PhotonNetworkingMessage.OnWebRpcResponse, operationResponse);
1352 break;
1353
1354 default:
1355 Debug.LogWarning(string.Format("OperationResponse unhandled: {0}", operationResponse.ToString()));
1356 break;
1357 }
1358
1359 this.externalListener.OnOperationResponse(operationResponse);
1360 }
File name: NetworkingPeer.cs
Copy
1631 public void OnEvent(EventData photonEvent)
1632 {
1633 if (PhotonNetwork.logLevel >= PhotonLogLevel.Informational)
1634 Debug.Log(string.Format("OnEvent: {0}", photonEvent.ToString()));
1635
1636 int actorNr = -1;
1637 PhotonPlayer originatingPlayer = null;
1638
1639 if (photonEvent.Parameters.ContainsKey(ParameterCode.ActorNr))
1640 {
1641 actorNr = (int)photonEvent[ParameterCode.ActorNr];
1642 if (this.mActors.ContainsKey(actorNr))
1643 {
1644 originatingPlayer = (PhotonPlayer)this.mActors[actorNr];
1645 }
1646 //else
1647 //{
1648 // // the actor sending this event is not in actorlist. this is usually no problem
1649 // if (photonEvent.Code != (byte)LiteOpCode.Join)
1650 // {
1651 // Debug.LogWarning("Received event, but we do not have this actor: " + actorNr);
1652 // }
1653 //}
1654 }
1655
1656 switch (photonEvent.Code)
1657 {
1658 case PunEvent.OwnershipRequest:
1659 {
1660 int[] requestValues = (int[]) photonEvent.Parameters[ParameterCode.CustomEventContent];
1661 int requestedViewId = requestValues[0];
1662 int currentOwner = requestValues[1];
1663 Debug.Log("Ev OwnershipRequest: " + photonEvent.Parameters.ToStringFull() + " ViewID: " + requestedViewId + " from: " + currentOwner + " Time: " + Environment.TickCount%1000);
1664
1665 PhotonView requestedView = PhotonView.Find(requestedViewId);
1666 if (requestedView == null)
1667 {
1668 Debug.LogWarning("Can't find PhotonView of incoming OwnershipRequest. ViewId not found: " + requestedViewId);
1669 break;
1670 }
1671
1672 Debug.Log("Ev OwnershipRequest PhotonView.ownershipTransfer: " + requestedView.ownershipTransfer + " .ownerId: " + requestedView.ownerId + " isOwnerActive: " + requestedView.isOwnerActive + ". This client's player: " + PhotonNetwork.player.ToStringFull());
1673
1674 switch (requestedView.ownershipTransfer)
1675 {
1676 case OwnershipOption.Fixed:
1677 Debug.LogWarning("Ownership mode == fixed. Ignoring request.");
1678 break;
1679 case OwnershipOption.Takeover:
1680 if (currentOwner == requestedView.ownerId)
1681 {
1682 // a takeover is successful automatically, if taken from current owner
1683 requestedView.ownerId = actorNr;
1684 }
1685 break;
1686 case OwnershipOption.Request:
1687 if (currentOwner == PhotonNetwork.player.ID || PhotonNetwork.player.isMasterClient)
1688 {
1689 if ((requestedView.ownerId == PhotonNetwork.player.ID) || (PhotonNetwork.player.isMasterClient && !requestedView.isOwnerActive))
1690 {
1691 SendMonoMessage(PhotonNetworkingMessage.OnOwnershipRequest, new object[] {requestedView, originatingPlayer});
1692 }
1693 }
1694 break;
1695 default:
1696 break;
1697 }
1698 }
1699 break;
1700
1701 case PunEvent.OwnershipTransfer:
1702 {
1703 int[] transferViewToUserID = (int[]) photonEvent.Parameters[ParameterCode.CustomEventContent];
1704 Debug.Log("Ev OwnershipTransfer. ViewID " + transferViewToUserID[0] + " to: " + transferViewToUserID[1] + " Time: " + Environment.TickCount%1000);
1705
1706 int requestedViewId = transferViewToUserID[0];
1707 int newOwnerId = transferViewToUserID[1];
1708
1709 PhotonView pv = PhotonView.Find(requestedViewId);
1710 pv.ownerId = newOwnerId;
1711
1712 break;
1713 }
1714 case EventCode.GameList:
1715 {
1716 this.mGameList = new Dictionary
1717 Hashtable games = (Hashtable)photonEvent[ParameterCode.GameList];
1718 foreach (DictionaryEntry game in games)
1719 {
1720 string gameName = (string)game.Key;
1721 this.mGameList[gameName] = new RoomInfo(gameName, (Hashtable)game.Value);
1722 }
1723 mGameListCopy = new RoomInfo[mGameList.Count];
1724 mGameList.Values.CopyTo(mGameListCopy, 0);
1725 SendMonoMessage(PhotonNetworkingMessage.OnReceivedRoomListUpdate);
1726 break;
1727 }
1728
1729 case EventCode.GameListUpdate:
1730 {
1731 Hashtable games = (Hashtable)photonEvent[ParameterCode.GameList];
1732 foreach (DictionaryEntry room in games)
1733 {
1734 string gameName = (string)room.Key;
1735 RoomInfo game = new RoomInfo(gameName, (Hashtable)room.Value);
1736 if (game.removedFromList)
1737 {
1738 this.mGameList.Remove(gameName);
1739 }
1740 else
1741 {
1742 this.mGameList[gameName] = game;
1743 }
1744 }
1745 this.mGameListCopy = new RoomInfo[this.mGameList.Count];
1746 this.mGameList.Values.CopyTo(this.mGameListCopy, 0);
1747 SendMonoMessage(PhotonNetworkingMessage.OnReceivedRoomListUpdate);
1748 break;
1749 }
1750
1751 case EventCode.QueueState:
1752 // not used anymore
1753 break;
1754
1755 case EventCode.AppStats:
1756 // Debug.LogInfo("Received stats!");
1757 this.mPlayersInRoomsCount = (int)photonEvent[ParameterCode.PeerCount];
1758 this.mPlayersOnMasterCount = (int)photonEvent[ParameterCode.MasterPeerCount];
1759 this.mGameCount = (int)photonEvent[ParameterCode.GameCount];
1760 break;
1761
1762 case EventCode.Join:
1763 // actorNr is fetched out of event above
1764 Hashtable actorProperties = (Hashtable)photonEvent[ParameterCode.PlayerProperties];
1765 if (originatingPlayer == null)
1766 {
1767 bool isLocal = this.mLocalActor.ID == actorNr;
1768 this.AddNewPlayer(actorNr, new PhotonPlayer(isLocal, actorNr, actorProperties));
1769 this.ResetPhotonViewsOnSerialize(); // This sets the correct OnSerializeState for Reliable OnSerialize
1770 }
1771
1772 if (actorNr == this.mLocalActor.ID)
1773 {
1774 // in this player's 'own' join event, we get a complete list of players in the room, so check if we know all players
1775 int[] actorsInRoom = (int[])photonEvent[ParameterCode.ActorList];
1776 foreach (int actorNrToCheck in actorsInRoom)
1777 {
1778 if (this.mLocalActor.ID != actorNrToCheck && !this.mActors.ContainsKey(actorNrToCheck))
1779 {
1780 this.AddNewPlayer(actorNrToCheck, new PhotonPlayer(false, actorNrToCheck, string.Empty));
1781 }
1782 }
1783
1784 // joinWithCreateOnDemand can turn an OpJoin into creating the room. Then actorNumber is 1 and callback: OnCreatedRoom()
1785 if (this.mLastJoinType == JoinType.JoinOrCreateOnDemand && this.mLocalActor.ID == 1)
1786 {
1787 SendMonoMessage(PhotonNetworkingMessage.OnCreatedRoom);
1788 }
1789 SendMonoMessage(PhotonNetworkingMessage.OnJoinedRoom); //Always send OnJoinedRoom
1790
1791 }
1792 else
1793 {
1794 SendMonoMessage(PhotonNetworkingMessage.OnPhotonPlayerConnected, this.mActors[actorNr]);
1795 }
1796 break;
1797
1798 case EventCode.Leave:
1799 this.HandleEventLeave(actorNr);
1800 break;
1801
1802 case EventCode.PropertiesChanged:
1803 int targetActorNr = (int)photonEvent[ParameterCode.TargetActorNr];
1804 Hashtable gameProperties = null;
1805 Hashtable actorProps = null;
1806 if (targetActorNr == 0)
1807 {
1808 gameProperties = (Hashtable)photonEvent[ParameterCode.Properties];
1809 }
1810 else
1811 {
1812 actorProps = (Hashtable)photonEvent[ParameterCode.Properties];
1813 }
1814
1815 this.ReadoutProperties(gameProperties, actorProps, targetActorNr);
1816 break;
1817
1818 case PunEvent.RPC:
1819 //ts: each event now contains a single RPC. execute this
1820 // Debug.Log("Ev RPC from: " + originatingPlayer);
1821 this.ExecuteRPC(photonEvent[ParameterCode.Data] as Hashtable, originatingPlayer);
1822 break;
1823
1824 case PunEvent.SendSerialize:
1825 case PunEvent.SendSerializeReliable:
1826 Hashtable serializeData = (Hashtable)photonEvent[ParameterCode.Data];
1827 //Debug.Log(serializeData.ToStringFull());
1828
1829 int remoteUpdateServerTimestamp = (int)serializeData[(byte)0];
1830 short remoteLevelPrefix = -1;
1831 short initialDataIndex = 1;
1832 if (serializeData.ContainsKey((byte)1))
1833 {
1834 remoteLevelPrefix = (short)serializeData[(byte)1];
1835 initialDataIndex = 2;
1836 }
1837
1838 for (short s = initialDataIndex; s < serializeData.Count; s++)
1839 {
1840 this.OnSerializeRead(serializeData[s] as Hashtable, originatingPlayer, remoteUpdateServerTimestamp, remoteLevelPrefix);
1841 }
1842 break;
1843
1844 case PunEvent.Instantiation:
1845 this.DoInstantiate((Hashtable)photonEvent[ParameterCode.Data], originatingPlayer, null);
1846 break;
1847
1848 case PunEvent.CloseConnection:
1849 // MasterClient "requests" a disconnection from us
1850 if (originatingPlayer == null || !originatingPlayer.isMasterClient)
1851 {
1852 Debug.LogError("Error: Someone else(" + originatingPlayer + ") then the masterserver requests a disconnect!");
1853 }
1854 else
1855 {
1856 PhotonNetwork.LeaveRoom();
1857 }
1858
1859 break;
1860
1861 case PunEvent.DestroyPlayer:
1862 Hashtable evData = (Hashtable)photonEvent[ParameterCode.Data];
1863 int targetPlayerId = (int)evData[(byte)0];
1864 if (targetPlayerId >= 0)
1865 {
1866 this.DestroyPlayerObjects(targetPlayerId, true);
1867 }
1868 else
1869 {
1870 if (this.DebugOut >= DebugLevel.INFO) Debug.Log("Ev DestroyAll! By PlayerId: " + actorNr);
1871 this.DestroyAll(true);
1872 }
1873 break;
1874
1875 case PunEvent.Destroy:
1876 evData = (Hashtable)photonEvent[ParameterCode.Data];
1877 int instantiationId = (int)evData[(byte)0];
1878 // 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.mLocalActor.ID));
1879
1880
1881 PhotonView pvToDestroy = null;
1882 if (this.photonViewList.TryGetValue(instantiationId, out pvToDestroy))
1883 {
1884 this.RemoveInstantiatedGO(pvToDestroy.gameObject, true);
1885 }
1886 else
1887 {
1888 if (this.DebugOut >= DebugLevel.ERROR) Debug.LogError("Ev Destroy Failed. Could not find PhotonView with instantiationId " + instantiationId + ". Sent by actorNr: " + actorNr);
1889 }
1890
1891 break;
1892
1893 case PunEvent.AssignMaster:
1894 evData = (Hashtable)photonEvent[ParameterCode.Data];
1895 int newMaster = (int)evData[(byte)1];
1896 this.SetMasterClient(newMaster, false);
1897 break;
1898
1899 default:
1900 if (photonEvent.Code < 200 && PhotonNetwork.OnEventCall != null)
1901 {
1902 object content = photonEvent[ParameterCode.Data];
1903 PhotonNetwork.OnEventCall(photonEvent.Code, content, actorNr);
1904 }
1905 else
1906 {
1907 // actorNr might be null. it is fetched out of event on top of method
1908 // Hashtable eventContent = (Hashtable) photonEvent[ParameterCode.Data];
1909 // this.mListener.customEventAction(actorNr, eventCode, eventContent);
1910 Debug.LogError("Error. Unhandled event: " + photonEvent);
1911 }
1912 break;
1913 }
1914
1915 this.externalListener.OnEvent(photonEvent);
1916 }
File name: PhotonClasses.cs
Copy
668 public virtual void OnPhotonPlayerPropertiesChanged(object[] playerAndUpdatedProps)
669 {
670 }
File name: PhotonPlayer.cs
Copy
184 public void SetCustomProperties(Hashtable propertiesToSet)
185 {
186 if (propertiesToSet == null)
187 {
188 return;
189 }
190
191 // merge (delete null-values)
192 this.customProperties.MergeStringKeys(propertiesToSet); // includes a Equals check (simplifying things)
193 this.customProperties.StripKeysWithNullValues();
194
195 // send (sync) these new values
196 Hashtable customProps = propertiesToSet.StripToStringKeys() as Hashtable;
197 if (this.actorID > 0 && !PhotonNetwork.offlineMode)
198 {
199 PhotonNetwork.networkingPeer.OpSetCustomPropertiesOfActor(this.actorID, customProps, true, 0);
200 }
201 NetworkingPeer.SendMonoMessage(PhotonNetworkingMessage.OnPhotonPlayerPropertiesChanged, this, propertiesToSet);
202 }
PlayerProperties 127 lượt xem
Gõ tìm kiếm nhanh...