//FitsRequirements checks if the player fits the requirement to be added to the given slot in the lobby func (l *Lobby) FitsRequirements(player *player.Player, slot int) (bool, error) { //BUG(vibhavp): FitsRequirements doesn't check reliability var req *Requirement slotReq, err := l.GetSlotRequirement(slot) if err == nil { req = slotReq } db.DB.Preload("Stats").First(player, player.ID) if time.Since(player.ProfileUpdatedAt) < time.Hour*time.Duration(req.Hours-player.GameHours) { //update player info only if the number of hours needed > the number of hours //passed since player info was last updated err = player.UpdatePlayerInfo() if err != nil { logrus.Error(err) } } if player.GameHours < req.Hours { return false, ErrReqHours } if player.Stats.TotalLobbies() < req.Lobbies { return false, ErrReqLobbies } return true, nil }
// Return a new ChatMessage sent from specficied player func NewChatMessage(message string, room int, player *player.Player) *ChatMessage { player.SetPlayerSummary() record := &ChatMessage{ PlayerID: player.ID, Room: room, Message: message, } return record }
func AfterLobbyJoin(so *wsevent.Client, lob *lobby.Lobby, player *player.Player) { room := fmt.Sprintf("%s_private", GetLobbyRoom(lob.ID)) //make all sockets join the private room, given the one the player joined the lobby on //might close, so lobbyStart and lobbyReadyUp can be sent to other tabs sockets, _ := sessions.GetSockets(player.SteamID) for _, so := range sockets { socket.AuthServer.Join(so, room) } if lob.State == lobby.InProgress { // player is a substitute lob.AfterPlayerNotInGameFunc(player, 5*time.Minute, func() { // if player doesn't join game server in 5 minutes, // substitute them message := player.Alias() + " has been reported for not joining the game within 5 minutes" chat.SendNotification(message, int(lob.ID)) lob.Substitute(player) }) } broadcaster.SendMessage(player.SteamID, "lobbyJoined", lobby.DecorateLobbyData(lob, false)) }
//AddPlayer adds the given player to lobby, If the player occupies a slot in the lobby already, switch slots. //If the player is in another lobby, removes them from that lobby before adding them. func (lobby *Lobby) AddPlayer(p *player.Player, slot int, password string) error { /* Possible errors while joining * Slot has been filled * Player has already joined a lobby * anything else? */ //Check if player is banned if lobby.IsPlayerBanned(p) { return ErrLobbyBan } if slot >= 2*format.NumberOfClassesMap[lobby.Type] || slot < 0 { return ErrBadSlot } isSubstitution := lobby.SlotNeedsSubstitute(slot) //Check whether the slot is occupied if !isSubstitution && lobby.IsSlotOccupied(slot) { return ErrFilled } if lobby.HasSlotRequirement(slot) { //check if player fits the requirements for the slot if ok, err := lobby.FitsRequirements(p, slot); !ok { return err } req, _ := lobby.GetSlotRequirement(slot) if password != req.Password { return ErrInvalidPassword } } var slotChange bool //Check if the player is currently in another lobby if currLobbyID, err := p.GetLobbyID(false); err == nil { if currLobbyID != lobby.ID { //if the player is in a different lobby, remove them from that lobby //plus substitute them curLobby, _ := GetLobbyByID(currLobbyID) if curLobby.State == InProgress { curLobby.Substitute(p) } else { curLobby.Lock() db.DB.Where("player_id = ? AND lobby_id = ?", p.ID, curLobby.ID).Delete(&LobbySlot{}) curLobby.Unlock() } } else { //player is in the same lobby, they're changing their slots //assign the player to a new slot if isSubstitution { //the slot needs a substitute (which happens when the lobby is in progress), //so players already in the lobby cannot fill it. return ErrNeedsSub } lobby.Lock() db.DB.Where("player_id = ? AND lobby_id = ?", p.ID, lobby.ID).Delete(&LobbySlot{}) lobby.Unlock() slotChange = true } } if !slotChange { //check if the player is in the steam group whitelist url := fmt.Sprintf(`http://steamcommunity.com/groups/%s/memberslistxml/?xml=1`, lobby.PlayerWhitelist) if lobby.PlayerWhitelist != "" && !helpers.IsWhitelisted(p.SteamID, url) { return ErrNotWhitelisted } //check if player has been subbed to the twitch channel (if any) //allow channel owners if lobby.TwitchChannel != "" && p.TwitchName != lobby.TwitchChannel { //check if player has connected their twitch account if p.TwitchAccessToken == "" { return errors.New("You need to connect your Twitch Account first to join the lobby.") } if lobby.TwitchRestriction == TwitchSubscribers && !p.IsSubscribed(lobby.TwitchChannel) { return fmt.Errorf("You aren't subscribed to %s", lobby.TwitchChannel) } if lobby.TwitchRestriction == TwitchFollowers && !p.IsFollowing(lobby.TwitchChannel) { return fmt.Errorf("You aren't following %s", lobby.TwitchChannel) } } } // Check if player is a substitute (the slot needs a subtitute) if isSubstitution { //get previous slot, to kick them from game prevPlayerID, _ := lobby.GetPlayerIDBySlot(slot) prevPlayer, _ := player.GetPlayerByID(prevPlayerID) lobby.Lock() db.DB.Where("lobby_id = ? AND slot = ?", lobby.ID, slot).Delete(&LobbySlot{}) lobby.Unlock() go func() { //kicks previous slot occupant if they're in-game, resets their !rep count, removes them from the lobby rpc.DisallowPlayer(lobby.ID, prevPlayer.SteamID, prevPlayer.ID) BroadcastSubList() //since the sub slot has been deleted, broadcast the updated substitute list //notify players in game server of subtitute class, team, _ := format.GetSlotTeamClass(lobby.Type, slot) rpc.Say(lobby.ID, fmt.Sprintf("Substitute found for %s %s: %s (%s)", team, class, p.Name, p.SteamID)) }() //allow player in mumble } //try to remove them from spectators lobby.RemoveSpectator(p, true) newSlotObj := &LobbySlot{ PlayerID: p.ID, LobbyID: lobby.ID, Slot: slot, } lobby.Lock() db.DB.Create(newSlotObj) lobby.Unlock() if !slotChange { if p.TwitchName != "" { rpc.TwitchBotAnnouce(p.TwitchName, lobby.ID) } } lobby.OnChange(true) p.SetMumbleUsername(lobby.Type, slot) return nil }