func (s *Server) PlayerGlobalMessage(data TF2RconWrapper.PlayerData, text string) { switch { case strings.HasPrefix(text, "!rep"): s.report(data) case strings.HasPrefix(text, "!sub"): if rFirstSubArg.FindStringSubmatch(text) != nil { // If they tried to use !sub with an argument, they // probably meant to !rep s.rcon.Say("!sub is for replacing yourself, !rep reports others.") } else { commID, _ := steamid.SteamIdToCommId(data.SteamId) publishEvent(Event{ Name: PlayerSubstituted, LobbyID: s.LobbyId, SteamID: commID, Self: true}) say := fmt.Sprintf("Reporting player %s (%s)", data.Username, data.SteamId) s.rcon.Say(say) } case strings.HasPrefix(text, "!soapoff"): ExecFile("soap_off.cfg", s.rcon) case strings.HasPrefix(text, "!help"): s.rcon.Say(`Use !rep for reporting, !sub for substituting yourself.`) case strings.HasPrefix(text, "!kick"): } }
func (s *Server) PlayerDisconnected(data TF2RconWrapper.PlayerData) { commID, _ := steamid.SteamIdToCommId(data.SteamId) allowed, _ := database.IsAllowed(s.LobbyId, commID) if allowed { publishEvent(Event{ Name: PlayerDisconnected, LobbyID: s.LobbyId, SteamID: commID}) } }
func (s *Server) LogListener() { //Steam IDs used in Source logs are of the form [C:U:A] //We convert these into a 64-bit Steam Community ID, which //is what Helen uses (and is sent in RPC calls) for { message := <-s.ServerListener.Messages switch message.Parsed.Type { case TF2RconWrapper.WorldGameOver: PushEvent(EventMatchEnded, s.LobbyId) close(s.StopVerifier) return case TF2RconWrapper.PlayerGlobalMessage: text := message.Parsed.Data.Text if strings.HasPrefix(text, "!rep") { s.report(message.Parsed.Data) } else if strings.HasPrefix(text, "!sub") { commID, _ := steamid.SteamIdToCommId(message.Parsed.Data.SteamId) PushEvent(EventSubstitute, s.LobbyId, commID) say := fmt.Sprintf("Reporting player %s (%s)", message.Parsed.Data.Username, message.Parsed.Data.SteamId) s.Rcon.Say(say) } case TF2RconWrapper.WorldPlayerConnected: commID, _ := steamid.SteamIdToCommId(message.Parsed.Data.SteamId) if s.IsPlayerAllowed(commID) { PushEvent(EventPlayerConnected, s.LobbyId, commID) } else { s.Rcon.KickPlayerID(message.Parsed.Data.UserId, "[tf2stadium.com] You're not in the lobby...") } case TF2RconWrapper.WorldPlayerDisconnected: commID, _ := steamid.SteamIdToCommId(message.Parsed.Data.SteamId) if s.IsPlayerAllowed(commID) { PushEvent(EventPlayerConnected, s.LobbyId, commID) } } } }
// check if the given commId is in the server func (s *Server) IsPlayerInServer(playerCommId string) (bool, error) { for i := range s.Players { commId, idErr := steamid.SteamIdToCommId(s.Players[i].SteamID) if idErr != nil { return false, idErr } if playerCommId == commId { return true, nil } } return false, nil }
func (lobby *Lobby) UpdateHours(logsID int) error { db.DB.Model(&Lobby{}).Where("id = ?", lobby.ID).UpdateColumn("logstf_id", logsID) logs, err := logstf.GetLogs(logsID) if err != nil { return err } for steamID, playerStats := range logs.Players { commid, _ := steamid.SteamIdToCommId(steamID) player, err := player.GetPlayerWithStats(commid) if err != nil { logrus.Error("Couldn't find player with SteamID ", commid) continue } for _, class := range playerStats.ClassStats { totalTime := time.Second * time.Duration(class.TotalTime) switch class.Type { case "scout": player.Stats.ScoutHours += totalTime case "soldier": player.Stats.SoldierHours += totalTime case "demoman": player.Stats.DemoHours += totalTime case "heavyweapons": player.Stats.HeavyHours += totalTime case "pyro": player.Stats.PyroHours += totalTime case "engineer": player.Stats.EngineerHours += totalTime case "spy": player.Stats.SpyHours += totalTime case "sniper": player.Stats.SniperHours += totalTime case "medic": player.Stats.MedicHours += totalTime } } player.Stats.Save() } return nil }
// check if the given commId is in the server func (s *Server) IsPlayerInServer(playerCommId string) (bool, error) { s.Players.RLock() defer s.Players.RUnlock() for _, player := range s.Players.Slice { commId, idErr := steamid.SteamIdToCommId(player.SteamID) if idErr != nil { return false, idErr } if playerCommId == commId { return true, nil } } return false, nil }
func (s *Server) PlayerConnected(data TF2RconWrapper.PlayerData) { commID, _ := steamid.SteamIdToCommId(data.SteamId) allowed, reason := database.IsAllowed(s.LobbyId, commID) if allowed { publishEvent(Event{ Name: PlayerConnected, LobbyID: s.LobbyId, SteamID: commID, }) atomic.AddInt32(s.curplayers, 1) if int(atomic.LoadInt32(s.curplayers)) == 2*format.NumberOfClassesMap[s.Type] { ExecFile("soap_off.cfg", s.rcon) } } else { s.rcon.KickPlayerID(data.UserId, "[tf2stadium.com] "+reason) } }
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) } } }
// runs each 10 sec func (s *Server) Verify() { if config.Constants.ServerMockUp || s.Rcon == nil { return } helpers.Logger.Debug("[Server.Verify]: Verifing server -> [" + s.Info.Host + "] from lobby [" + fmt.Sprint(s.LobbyId) + "]") // check if all players in server are in lobby var err error s.Players, err = s.Rcon.GetPlayers() for err != nil { time.Sleep(time.Second) helpers.Logger.Warning("Failed to get players in server %s: %s", s.LobbyId, err.Error()) s.Players, err = s.Rcon.GetPlayers() } for i := range s.Players { if s.Players[i].SteamID != "BOT" { commId, idErr := steamid.SteamIdToCommId(s.Players[i].SteamID) if idErr != nil { helpers.Logger.Debug("[Server.Verify]: ERROR -> %s", idErr) } isPlayerAllowed := s.IsPlayerAllowed(commId) if isPlayerAllowed == false { helpers.Logger.Debug("[Server.Verify]: Kicking player not allowed -> Username [" + s.Players[i].Username + "] CommID [" + commId + "] SteamID [" + s.Players[i].SteamID + "] ") kickErr := s.Rcon.KickPlayer(s.Players[i], "[tf2stadium.com]: You're not in this lobby...") if kickErr != nil { helpers.Logger.Debug("[Server.Verify]: ERROR -> %s", kickErr) } } } } }
func (s *Server) report(data TF2RconWrapper.PlayerData) { var team string matches := rReport.FindStringSubmatch(data.Text) if len(matches) != 3 { s.rcon.Say("Usage: !rep our/their/red/blu " + slot(s.Type)) return } argTeam := strings.ToLower(matches[1]) argSlot := strings.ToLower(matches[2]) source, _ := steamid.SteamIdToCommId(data.SteamId) team = database.GetTeam(s.LobbyId, s.Type, source) // helpers.Logger.Debug(team) switch argTeam { case "their": if team == "red" { team = "blu" } else { team = "red" } case "our": // team = team case "blu", "red": team = argTeam case "blue": team = "blu" default: s.rcon.Say("Usage: !rep our/their/red/blu slotname") return } target, err := database.GetSteamIDFromSlot(team, argSlot, s.LobbyId, s.Type) if err != nil { var slots string s.rcon.Say("!rep: valid slots - " + slots) return } if database.IsReported(s.LobbyId, target) { s.rcon.Say("!rep: Player has already been reported") return } if target == source { // !rep'ing themselves publishEvent(Event{ Name: PlayerSubstituted, LobbyID: s.LobbyId, SteamID: source, Self: true}) say := fmt.Sprintf("Reporting player %s (%s)", data.Username, data.SteamId) s.rcon.Say(say) return } err = newReport(source, target, s.LobbyId) if err != nil { if _, ok := err.(*repError); ok { s.rcon.Say("!rep: You have already voted.") } else { s.rcon.Say(err.Error()) helpers.Logger.Errorf("#%d: %v", s.LobbyId, err) } return } curReps := countReports(target, s.LobbyId) name := database.GetNameFromSteamID(target) switch curReps { case repsNeeded[s.Type]: //Got needed number of reports, ask helen to substitute player publishEvent(Event{ Name: PlayerSubstituted, SteamID: target, LobbyID: s.LobbyId}) // tell timeout goroutine to stop (It is possible that the map // entry will not exist if only 1 report is needed (such as debug // lobbies)) s.mapMu.RLock() timer, ok := s.repTimer[team+argSlot] s.mapMu.RUnlock() if ok && timer.Stop() { s.mapMu.Lock() delete(s.repTimer, team+argSlot) s.mapMu.Unlock() } say := fmt.Sprintf("Reporting %s %s: %s", strings.ToUpper(team), strings.ToUpper(argSlot), name) s.rcon.Say(say) case 1: //first report happened, reset reps two minute later to 0, unless told to stop timer := time.AfterFunc(2*time.Minute, func() { ResetReportCount(target, s.LobbyId) say := fmt.Sprintf("Reporting %s %s failed, couldn't get enough votes in 2 minutes.", strings.ToUpper(team), strings.ToUpper(argSlot)) s.rcon.Say(say) }) s.mapMu.Lock() s.repTimer[team+argSlot] = timer s.mapMu.Unlock() } say := fmt.Sprintf("Got %d votes for reporting %s (%d needed)", curReps, name, repsNeeded[s.Type]) s.rcon.Say(say) return }