示例#1
0
//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)
				}
			})
		}
	}

}
示例#2
0
文件: event.go 项目: TF2Stadium/Helen
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))
}
示例#3
0
文件: lobby.go 项目: TF2Stadium/Helen
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)
}
示例#4
0
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)
}
示例#5
0
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
}
示例#6
0
文件: lobby.go 项目: TF2Stadium/Helen
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
}
示例#7
0
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
}
示例#8
0
文件: lobby.go 项目: TF2Stadium/Helen
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
}
示例#9
0
文件: lobby.go 项目: TF2Stadium/Helen
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
}
示例#10
0
文件: lobby.go 项目: TF2Stadium/Helen
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
}
示例#11
0
文件: event.go 项目: TF2Stadium/Helen
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)
}
示例#12
0
文件: event.go 项目: TF2Stadium/Helen
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))
	})
}
示例#13
0
文件: lobby.go 项目: TF2Stadium/Helen
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
}
示例#14
0
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
}
示例#15
0
文件: lobby.go 项目: TF2Stadium/Helen
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)
}
示例#16
0
文件: event.go 项目: TF2Stadium/Helen
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)
		}
	}
}
示例#17
0
文件: event.go 项目: TF2Stadium/Helen
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))
}
示例#18
0
文件: lobby.go 项目: TF2Stadium/Helen
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
}
示例#19
0
文件: lobby.go 项目: TF2Stadium/Helen
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
}
示例#20
0
文件: lobby.go 项目: TF2Stadium/Helen
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
}
示例#21
0
文件: lobby.go 项目: TF2Stadium/Helen
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
}
示例#22
0
文件: lobby.go 项目: TF2Stadium/Helen
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
}
示例#23
0
文件: event.go 项目: TF2Stadium/Helen
func reservationEnded(lobbyID uint) {
	lobby, _ := lobbypackage.GetLobbyByID(lobbyID)
	lobby.Close(false, false)
	chat.SendNotification("Lobby Closed (serveme.tf reservation ended)", int(lobby.ID))
}