//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
}
Exemple #2
0
// 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
}
Exemple #3
0
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))
}
Exemple #4
0
//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
}