//OnDisconnect is connected when a player with a given socketID disconnects func OnDisconnect(socketID string, token *jwt.Token) { if token != nil { //player was logged in player := chelpers.GetPlayer(token) if player == nil { return } sessions.RemoveSocket(socketID, player.SteamID) id, _ := sessions.GetSpectating(socketID) if id != 0 { lob, _ := lobby.GetLobbyByID(id) lob.RemoveSpectator(player, true) } id, _ = player.GetLobbyID(true) //if player is in a waiting lobby, and hasn't connected for > 30 seconds, //remove him from it. Here, connected = player isn't connected from any tab/window if id != 0 && sessions.ConnectedSockets(player.SteamID) == 0 { sessions.AfterDisconnectedFunc(player.SteamID, time.Second*30, func() { lob, _ := lobby.GetLobbyByID(id) if lob.State == lobby.Waiting { lob.RemovePlayer(player) } }) } } }
func playerConn(steamID string, lobbyID uint) { player, _ := playerpackage.GetPlayerBySteamID(steamID) lobby, _ := lobbypackage.GetLobbyByID(lobbyID) lobby.SetInGame(player) chat.SendNotification(fmt.Sprintf("%s has connected to the server.", player.Alias()), int(lobby.ID)) }
func removePlayerFromLobby(lobbyId uint, steamId string) (*lobby.Lobby, *player.Player, error) { player, err := player.GetPlayerBySteamID(steamId) if err != nil { return nil, nil, err } lob, err := lobby.GetLobbyByID(lobbyId) if err != nil { return nil, nil, err } switch lob.State { case lobby.InProgress: lob.Substitute(player) return lob, player, lob.AddSpectator(player) case lobby.Ended: return lob, player, errors.New("Lobby has closed.") } _, err = lob.GetPlayerSlot(player) if err != nil { return lob, player, errors.New("Player not playing") } if err := lob.RemovePlayer(player); err != nil { return lob, player, err } return lob, player, lob.AddSpectator(player) }
func TwitchBadge(w http.ResponseWriter, r *http.Request) { if !reValidPath.MatchString(r.URL.Path) { http.NotFound(w, r) return } matches := reValidPath.FindStringSubmatch(r.URL.Path) steamid := matches[1] player, err := player.GetPlayerBySteamID(steamid) if err != nil { //player not found http.Error(w, "Player with given SteamID not found", http.StatusNotFound) return } id, err := player.GetLobbyID(false) if err != nil { //player not in lobby right now, just serve a page that refreshes every 5 seconds w.Write([]byte(emptyPage)) return } lobby, _ := lobby.GetLobbyByID(id) err = twitchBadge.Execute(w, lobby) }
func (Player) PlayerNotReady(so *wsevent.Client, _ struct{}) interface{} { player := chelpers.GetPlayer(so.Token) lobbyid, tperr := player.GetLobbyID(false) if tperr != nil { return tperr } lob, err := lobby.GetLobbyByID(lobbyid) if err != nil { return err } if lob.State != lobby.ReadyingUp { return errors.New("Lobby hasn't been filled up yet.") } err = lob.UnreadyPlayer(player) lob.RemovePlayer(player) hooks.AfterLobbyLeave(lob, player, false, false) if spec := sessions.IsSpectating(so.ID, lob.ID); spec { // IsSpectating checks if the player has joined the lobby's public room lob.AddSpectator(player) } if tperr != nil { return tperr } lob.SetState(lobby.Waiting) lob.UnreadyAllPlayers() lobby.BroadcastLobby(lob) return emptySuccess }
func (Lobby) LobbyChangeOwner(so *wsevent.Client, args struct { ID *uint `json:"id"` SteamID *string `json:"steamid"` }) interface{} { lob, err := lobby.GetLobbyByID(*args.ID) if err != nil { return err } // current owner player1 := chelpers.GetPlayer(so.Token) if lob.CreatedBySteamID != player1.SteamID { return errors.New("You aren't authorized to change lobby owner.") } // to be owner player2, err := player.GetPlayerBySteamID(*args.SteamID) if err != nil { return err } lob.CreatedBySteamID = player2.SteamID lob.Save() lobby.BroadcastLobby(lob) lobby.BroadcastLobbyList() chat.NewBotMessage(fmt.Sprintf("Lobby leader changed to %s", player2.Alias()), int(*args.ID)).Send() return emptySuccess }
func (Player) PlayerSettingsSet(so *wsevent.Client, args struct { Key *string `json:"key"` Value *string `json:"value"` }) interface{} { player := chelpers.GetPlayer(so.Token) switch *args.Key { case "siteAlias": if len(*args.Value) > 32 { return errors.New("Site alias must be under 32 characters long.") } player.SetSetting(*args.Key, *args.Value) player.SetPlayerProfile() so.EmitJSON(helpers.NewRequest("playerProfile", player)) if lobbyID, _ := player.GetLobbyID(true); lobbyID != 0 { lob, _ := lobby.GetLobbyByID(lobbyID) slot, _ := lob.GetPlayerSlot(player) player.SetMumbleUsername(lob.Type, slot) lobby.BroadcastLobby(lob) } default: player.SetSetting(*args.Key, *args.Value) } return emptySuccess }
func (Lobby) LobbyServerReset(so *wsevent.Client, args struct { ID *uint `json:"id"` }) interface{} { player := chelpers.GetPlayer(so.Token) lob, tperr := lobby.GetLobbyByID(*args.ID) if player.SteamID != lob.CreatedBySteamID && (player.Role != helpers.RoleAdmin && player.Role != helpers.RoleMod) { return errors.New("You are not authorized to reset server.") } if tperr != nil { return tperr } if lob.State == lobby.Ended { return errors.New("Lobby has ended") } if err := rpc.ReExecConfig(lob.ID, false); err != nil { return err } return emptySuccess }
func (Lobby) LobbySetTeamName(so *wsevent.Client, args struct { Id uint `json:"id"` Team string `json:"team"` NewName string `json:"name"` }) interface{} { player := chelpers.GetPlayer(so.Token) lob, err := lobby.GetLobbyByID(args.Id) if err != nil { return err } if player.SteamID != lob.CreatedBySteamID && (player.Role != helpers.RoleAdmin && player.Role != helpers.RoleMod) { return errors.New("You aren't authorized to do this.") } if len(args.NewName) == 0 || len(args.NewName) > 12 { return errors.New("team name must be between 1-12 characters long.") } if args.Team == "red" { lob.RedTeamName = args.NewName } else if args.Team == "blu" { lob.BluTeamName = args.NewName } else { return errors.New("team must be red or blu.") } lob.Save() lobby.BroadcastLobby(lob) return emptySuccess }
func (Lobby) LobbySetRequirement(so *wsevent.Client, args struct { ID *uint `json:"id"` // lobby ID Slot *int `json:"slot"` // -1 if to set for all slots Type *string `json:"type"` Value *json.Number `json:"value"` Password *string `json:"password" empty:"-"` }) interface{} { lob, err := lobby.GetLobbyByID(*args.ID) if err != nil { return err } player := chelpers.GetPlayer(so.Token) if lob.CreatedBySteamID != player.SteamID { return errors.New("Only lobby owners can change requirements.") } if !(*args.Slot >= 0 && *args.Slot < 2*format.NumberOfClassesMap[lob.Type]) { return errors.New("Invalid slot.") } req, err := lob.GetSlotRequirement(*args.Slot) if err != nil { //requirement doesn't exist. create one req.Slot = *args.Slot req.LobbyID = *args.ID } var n int64 var f float64 switch *args.Type { case "hours": n, err = args.Value.Int64() req.Hours = int(n) case "lobbies": n, err = args.Value.Int64() req.Lobbies = int(n) case "reliability": f, err = args.Value.Float64() req.Reliability = f case "password": req.Password = *args.Password default: return errors.New("Invalid requirement type.") } if err != nil { return errors.New("Invalid requirement.") } req.Save() lobby.BroadcastLobby(lob) lobby.BroadcastLobbyList() return emptySuccess }
func mumbleLeft(playerID uint) { player, _ := playerpackage.GetPlayerByID(playerID) id, _ := player.GetLobbyID(false) if id == 0 { // player joined mumble lobby for closed channel return } lobby, _ := lobbypackage.GetLobbyByID(id) lobby.SetNotInMumble(player) }
func playerDisc(steamID string, lobbyID uint) { player, _ := playerpackage.GetPlayerBySteamID(steamID) lobby, _ := lobbypackage.GetLobbyByID(lobbyID) lobby.SetNotInGame(player) chat.SendNotification(fmt.Sprintf("%s has disconected from the server.", player.Alias()), int(lobby.ID)) lobby.AfterPlayerNotInGameFunc(player, 5*time.Minute, func() { lobby.Substitute(player) player.NewReport(playerpackage.Substitute, lobby.ID) chat.SendNotification(fmt.Sprintf("%s has been reported for not joining the game in 5 minutes", player.Alias()), int(lobby.ID)) }) }
func playerCanKick(lobbyId uint, steamId string) (bool, error) { lob, err := lobby.GetLobbyByID(lobbyId) if err != nil { return false, err } player, err := player.GetPlayerBySteamID(steamId) if err != nil { return false, err } if steamId != lob.CreatedBySteamID && player.Role != helpers.RoleAdmin { return false, errors.New("Not authorized to kick players") } return true, nil }
func (Unauth) LobbySpectatorJoin(so *wsevent.Client, args struct { ID *uint `json:"id"` }) interface{} { lob, err := lobby.GetLobbyByID(*args.ID) if err != nil { return err } hooks.AfterLobbySpec(socket.UnauthServer, so, nil, lob) so.EmitJSON(helpers.NewRequest("lobbyData", lobby.DecorateLobbyData(lob, true))) return emptySuccess }
func AfterLobbySpec(server *wsevent.Server, so *wsevent.Client, player *player.Player, lob *lobby.Lobby) { //remove socket from room of the previous lobby the socket was spectating (if any) lobbyID, ok := sessions.GetSpectating(so.ID) if ok { server.Leave(so, fmt.Sprintf("%d_public", lobbyID)) sessions.RemoveSpectator(so.ID) if player != nil { prevLobby, _ := lobby.GetLobbyByID(lobbyID) prevLobby.RemoveSpectator(player, true) } } server.Join(so, fmt.Sprintf("%d_public", lob.ID)) chelpers.BroadcastScrollback(so, lob.ID) sessions.SetSpectator(so.ID, lob.ID) }
func playersList(players []TF2RconWrapper.Player) { for _, player := range players { commid, _ := steamid.SteamIdToCommId(player.SteamID) player, err := playerpackage.GetPlayerBySteamID(commid) if err != nil { continue } id, _ := player.GetLobbyID(false) if id == 0 { continue } lobby, _ := lobbypackage.GetLobbyByID(id) if !lobby.IsPlayerInGame(player) { lobby.SetInGame(player) } } }
func playerSub(steamID string, lobbyID uint, self bool) { player, _ := playerpackage.GetPlayerBySteamID(steamID) lobby, err := lobbypackage.GetLobbyByID(lobbyID) if err != nil { logrus.Error(err) return } lobby.Substitute(player) if self { player.NewReport(playerpackage.Substitute, lobby.ID) } else { // ban player from joining lobbies for 30 minutes player.NewReport(playerpackage.Vote, lobby.ID) } chat.SendNotification(fmt.Sprintf("%s has been reported.", player.Alias()), int(lobby.ID)) }
func (Lobby) LobbySpectatorJoin(so *wsevent.Client, args struct { Id *uint `json:"id"` }) interface{} { lob, err := lobby.GetLobbyByID(*args.Id) if err != nil { return err } player := chelpers.GetPlayer(so.Token) var specSameLobby bool arr, tperr := player.GetSpectatingIds() if len(arr) != 0 { for _, id := range arr { if id == *args.Id { specSameLobby = true continue } //a socket should only spectate one lobby, remove socket from //any other lobby room //multiple sockets from one player can spectatte multiple lobbies socket.AuthServer.Leave(so, fmt.Sprintf("%d_public", id)) } } // If the player is already in the lobby (either joined a slot or is spectating), don't add them. // Just Broadcast the lobby to them, so the frontend displays it. if id, _ := player.GetLobbyID(false); id != *args.Id && !specSameLobby { tperr = lob.AddSpectator(player) if tperr != nil { return tperr } } hooks.AfterLobbySpec(socket.AuthServer, so, player, lob) lobby.BroadcastLobbyToUser(lob, player.SteamID) return emptySuccess }
func (Lobby) LobbySpectatorLeave(so *wsevent.Client, args struct { Id *uint `json:"id"` }) interface{} { player := chelpers.GetPlayer(so.Token) lob, tperr := lobby.GetLobbyByID(*args.Id) if tperr != nil { return tperr } if !player.IsSpectatingID(lob.ID) { if id, _ := player.GetLobbyID(false); id == *args.Id { hooks.AfterLobbySpecLeave(so, lob) return emptySuccess } } lob.RemoveSpectator(player, true) hooks.AfterLobbySpecLeave(so, lob) return emptySuccess }
func (Lobby) LobbyRemoveSteamRestriction(so *wsevent.Client, args struct { ID uint `json:"id"` }) interface{} { player := chelpers.GetPlayer(so.Token) lob, err := lobby.GetLobbyByID(args.ID) if err != nil { return err } if player.SteamID != lob.CreatedBySteamID && (player.Role != helpers.RoleAdmin && player.Role != helpers.RoleMod) { return errors.New("You aren't authorized to do this.") } lob.PlayerWhitelist = "" lob.Save() lobby.BroadcastLobby(lob) lobby.BroadcastLobbyList() return emptySuccess }
func (Lobby) LobbyShuffle(so *wsevent.Client, args struct { Id uint `json:"id"` }) interface{} { player := chelpers.GetPlayer(so.Token) lob, err := lobby.GetLobbyByID(args.Id) if err != nil { return err } if player.SteamID != lob.CreatedBySteamID && (player.Role != helpers.RoleAdmin && player.Role != helpers.RoleMod) { return errors.New("You aren't authorized to shuffle this lobby.") } if err = lob.ShuffleAllSlots(); err != nil { return err } room := fmt.Sprintf("%s_private", hooks.GetLobbyRoom(args.Id)) broadcaster.SendMessageToRoom(room, "lobbyShuffled", args) chat.NewBotMessage(fmt.Sprintf("Lobby shuffled by %s", player.Alias()), int(args.Id)).Send() return emptySuccess }
func (Lobby) LobbyJoin(so *wsevent.Client, args struct { Id *uint `json:"id"` Class *string `json:"class"` Team *string `json:"team" valid:"red,blu"` Password *string `json:"password" empty:"-"` }) interface{} { p := chelpers.GetPlayer(so.Token) if banned, until := p.IsBannedWithTime(player.BanJoin); banned { ban, _ := p.GetActiveBan(player.BanJoin) return fmt.Errorf("You have been banned from joining lobbies till %s (%s)", until.Format(time.RFC822), ban.Reason) } //logrus.Debug("id %d class %s team %s", *args.Id, *args.Class, *args.Team) lob, tperr := lobby.GetLobbyByID(*args.Id) if tperr != nil { return tperr } if lob.Mumble { if banned, until := p.IsBannedWithTime(player.BanJoinMumble); banned { ban, _ := p.GetActiveBan(player.BanJoinMumble) return fmt.Errorf("You have been banned from joining Mumble lobbies till %s (%s)", until.Format(time.RFC822), ban.Reason) } } if lob.State == lobby.Ended { return errors.New("Cannot join a closed lobby.") } if lob.State == lobby.Initializing { return errors.New("Lobby is being setup right now.") } if lob.RegionLock { region, _ := helpers.GetRegion(chelpers.GetIPAddr(so.Request)) if region != lob.RegionCode { return errors.New("This lobby is region locked.") } } //Check if player is in the same lobby var sameLobby bool if id, err := p.GetLobbyID(false); err == nil && id == *args.Id { sameLobby = true } slot, tperr := format.GetSlot(lob.Type, *args.Team, *args.Class) if tperr != nil { return tperr } if prevId, _ := p.GetLobbyID(false); prevId != 0 && !sameLobby { lob, _ := lobby.GetLobbyByID(prevId) hooks.AfterLobbyLeave(lob, p, false, false) } tperr = lob.AddPlayer(p, slot, *args.Password) if tperr != nil { return tperr } if !sameLobby { hooks.AfterLobbyJoin(so, lob, p) } playersCnt := lob.GetPlayerNumber() lastNotif, timerExists := lobbyJoinLastNotif[lob.ID] if playersCnt >= notifThreshold[lob.Type] && !lob.IsEnoughPlayers(playersCnt) && (!timerExists || time.Since(lastNotif).Minutes() > 5) { lob.DiscordNotif(fmt.Sprintf("Almost ready [%d/%d]", playersCnt, lob.RequiredPlayers())) lobbyJoinLastNotif[lob.ID] = time.Now() } //check if lobby isn't already in progress (which happens when the player is subbing) lob.Lock() if lob.IsEnoughPlayers(playersCnt) && lob.State != lobby.InProgress && lob.State != lobby.ReadyingUp { lob.State = lobby.ReadyingUp lob.ReadyUpTimestamp = time.Now().Unix() + 30 lob.Save() helpers.GlobalWait.Add(1) time.AfterFunc(time.Second*30, func() { state := lob.CurrentState() //if all player's haven't readied up, //remove unreadied players and unready the //rest. //don't do this when: // lobby.State == Waiting (someone already unreadied up, so all players have been unreadied) // lobby.State == InProgress (all players have readied up, so the lobby has started) // lobby.State == Ended (the lobby has been closed) if state != lobby.Waiting && state != lobby.InProgress && state != lobby.Ended { lob.SetState(lobby.Waiting) removeUnreadyPlayers(lob) lob.UnreadyAllPlayers() //get updated lobby object lob, _ = lobby.GetLobbyByID(lob.ID) lobby.BroadcastLobby(lob) } helpers.GlobalWait.Done() }) room := fmt.Sprintf("%s_private", hooks.GetLobbyRoom(lob.ID)) broadcaster.SendMessageToRoom(room, "lobbyReadyUp", struct { Timeout int `json:"timeout"` }{30}) lobby.BroadcastLobbyList() } lob.Unlock() if lob.State == lobby.InProgress { //this happens when the player is a substitute db.DB.Preload("ServerInfo").First(lob, lob.ID) so.EmitJSON(helpers.NewRequest("lobbyStart", lobby.DecorateLobbyConnect(lob, p, slot))) } return emptySuccess }
func reservationEnded(lobbyID uint) { lobby, _ := lobbypackage.GetLobbyByID(lobbyID) lobby.Close(false, false) chat.SendNotification("Lobby Closed (serveme.tf reservation ended)", int(lobby.ID)) }