/// <summary> /// Sends a request to room, to retrieve an access to it for a specified peer, /// with some extra properties /// </summary> public void GetAccess(IPeer peer, Dictionary <string, string> properties, GetAccessCallback callback) { // If request is already pending if (_requestsInProgress.Contains(peer.Id)) { callback.Invoke(null, "You've already requested an access to this room"); return; } // If player is already in the game if (_players.ContainsKey(peer.Id)) { callback.Invoke(null, "You are already in this room"); return; } // If player has already received an access and didn't claim it // but is requesting again - send him the old one var currentAccess = _unconfirmedAccesses.Values.FirstOrDefault(v => v.Peer == peer); if (currentAccess != null) { // Restore the timeout currentAccess.Timeout = DateTime.Now.AddSeconds(Options.AccessTimeoutPeriod); callback.Invoke(currentAccess.Access, null); return; } // If there's a player limit if (Options.MaxPlayers != 0) { var playerSlotsTaken = _requestsInProgress.Count + _accessesInUse.Count + _unconfirmedAccesses.Count; if (playerSlotsTaken >= Options.MaxPlayers) { callback.Invoke(null, "Room is already full"); return; } } var packet = new RoomAccessProvideCheckPacket() { PeerId = peer.Id, RoomId = RoomId }; // Add the username if available var userExt = peer.GetExtension <IUserExtension>(); if (userExt != null && !string.IsNullOrEmpty(userExt.Username)) { packet.Username = userExt.Username; } // Add to pending list _requestsInProgress.Add(peer.Id); Peer.SendMessage((short)MsfOpCodes.ProvideRoomAccessCheck, packet, (status, response) => { // Remove from pending list _requestsInProgress.Remove(peer.Id); if (status != ResponseStatus.Success) { callback.Invoke(null, response.AsString("Unknown Error")); return; } var accessData = response.Deserialize(new RoomAccessPacket()); var access = new RoomAccessData() { Access = accessData, Peer = peer, Timeout = DateTime.Now.AddSeconds(Options.AccessTimeoutPeriod) }; // Save the access _unconfirmedAccesses[access.Access.Token] = access; callback.Invoke(access.Access, null); }); }