Skip to content

Commit

Permalink
Lobby setting bounds now adjustable via env config
Browse files Browse the repository at this point in the history
* 2 clients per ip is now the default setting
* 24 max players is now the default setting
* The fly.io deployment now defaults to 100 max players
  • Loading branch information
Bios-Marcel committed Nov 28, 2024
1 parent c5651bd commit 242c800
Show file tree
Hide file tree
Showing 10 changed files with 84 additions and 76 deletions.
3 changes: 3 additions & 0 deletions fly.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ dockerfile = "linux.Dockerfile"
[deploy]
strategy = "canary"

[env]
LOBBY_SETTING_BOUNDS_MAX_MAX_PLAYERS=100

[http_service]
internal_port = 8080
force_https = true
Expand Down
25 changes: 13 additions & 12 deletions internal/api/createparse.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"strconv"
"strings"

"github.com/scribble-rs/scribble.rs/internal/config"
"github.com/scribble-rs/scribble.rs/internal/game"
"golang.org/x/text/cases"
)
Expand Down Expand Up @@ -38,25 +39,25 @@ func ParseLanguage(value string) (*game.LanguageData, string, error) {
// ParseDrawingTime checks whether the given value is an integer between
// the lower and upper bound of drawing time. All other invalid
// input, including empty strings, will return an error.
func ParseDrawingTime(value string) (int, error) {
return parseIntValue(value, game.LobbySettingBounds.MinDrawingTime,
game.LobbySettingBounds.MaxDrawingTime, "drawing time")
func ParseDrawingTime(cfg *config.Config, value string) (int, error) {
return parseIntValue(value, cfg.LobbySettingBounds.MinDrawingTime,
cfg.LobbySettingBounds.MaxDrawingTime, "drawing time")
}

// ParseRounds checks whether the given value is an integer between
// the lower and upper bound of rounds played. All other invalid
// input, including empty strings, will return an error.
func ParseRounds(value string) (int, error) {
return parseIntValue(value, game.LobbySettingBounds.MinRounds,
game.LobbySettingBounds.MaxRounds, "rounds")
func ParseRounds(cfg *config.Config, value string) (int, error) {
return parseIntValue(value, cfg.LobbySettingBounds.MinRounds,
cfg.LobbySettingBounds.MaxRounds, "rounds")
}

// ParseMaxPlayers checks whether the given value is an integer between
// the lower and upper bound of maximum players per lobby. All other invalid
// input, including empty strings, will return an error.
func ParseMaxPlayers(value string) (int, error) {
return parseIntValue(value, game.LobbySettingBounds.MinMaxPlayers,
game.LobbySettingBounds.MaxMaxPlayers, "max players amount")
func ParseMaxPlayers(cfg *config.Config, value string) (int, error) {
return parseIntValue(value, cfg.LobbySettingBounds.MinMaxPlayers,
cfg.LobbySettingBounds.MaxMaxPlayers, "max players amount")
}

// ParseCustomWords checks whether the given value is a string containing comma
Expand Down Expand Up @@ -88,9 +89,9 @@ func ParseCustomWords(lowercaser cases.Caser, value string) ([]string, error) {
// ParseClientsPerIPLimit checks whether the given value is an integer between
// the lower and upper bound of maximum clients per IP. All other invalid
// input, including empty strings, will return an error.
func ParseClientsPerIPLimit(value string) (int, error) {
return parseIntValue(value, game.LobbySettingBounds.MinClientsPerIPLimit,
game.LobbySettingBounds.MaxClientsPerIPLimit, "clients per IP limit")
func ParseClientsPerIPLimit(cfg *config.Config, value string) (int, error) {
return parseIntValue(value, cfg.LobbySettingBounds.MinClientsPerIPLimit,
cfg.LobbySettingBounds.MaxClientsPerIPLimit, "clients per IP limit")
}

// ParseCustomWordsPerTurn checks whether the given value is an integer between
Expand Down
7 changes: 4 additions & 3 deletions internal/api/createparse_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"reflect"
"testing"

"github.com/scribble-rs/scribble.rs/internal/config"
"golang.org/x/text/cases"
"golang.org/x/text/language"
)
Expand Down Expand Up @@ -60,7 +61,7 @@ func Test_parseDrawingTime(t *testing.T) {
t.Run(testCase.name, func(t *testing.T) {
t.Parallel()

got, err := ParseDrawingTime(testCase.value)
got, err := ParseDrawingTime(&config.Default, testCase.value)
if (err != nil) != testCase.wantErr {
t.Errorf("parseDrawingTime() error = %v, wantErr %v", err, testCase.wantErr)
return
Expand Down Expand Up @@ -93,7 +94,7 @@ func Test_parseRounds(t *testing.T) {
t.Run(testCase.name, func(t *testing.T) {
t.Parallel()

got, err := ParseRounds(testCase.value)
got, err := ParseRounds(&config.Default, testCase.value)
if (err != nil) != testCase.wantErr {
t.Errorf("parseRounds() error = %v, wantErr %v", err, testCase.wantErr)
return
Expand Down Expand Up @@ -126,7 +127,7 @@ func Test_parseMaxPlayers(t *testing.T) {
t.Run(testCase.name, func(t *testing.T) {
t.Parallel()

got, err := ParseMaxPlayers(testCase.value)
got, err := ParseMaxPlayers(&config.Default, testCase.value)
if (err != nil) != testCase.wantErr {
t.Errorf("parseMaxPlayers() error = %v, wantErr %v", err, testCase.wantErr)
return
Expand Down
24 changes: 12 additions & 12 deletions internal/api/v1.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,11 +105,11 @@ func (handler *V1Handler) postLobby(writer http.ResponseWriter, request *http.Re
}

languageData, languageKey, languageInvalid := ParseLanguage(request.Form.Get("language"))
drawingTime, drawingTimeInvalid := ParseDrawingTime(request.Form.Get("drawing_time"))
rounds, roundsInvalid := ParseRounds(request.Form.Get("rounds"))
maxPlayers, maxPlayersInvalid := ParseMaxPlayers(request.Form.Get("max_players"))
drawingTime, drawingTimeInvalid := ParseDrawingTime(handler.cfg, request.Form.Get("drawing_time"))
rounds, roundsInvalid := ParseRounds(handler.cfg, request.Form.Get("rounds"))
maxPlayers, maxPlayersInvalid := ParseMaxPlayers(handler.cfg, request.Form.Get("max_players"))
customWordsPerTurn, customWordsPerTurnInvalid := ParseCustomWordsPerTurn(request.Form.Get("custom_words_per_turn"))
clientsPerIPLimit, clientsPerIPLimitInvalid := ParseClientsPerIPLimit(request.Form.Get("clients_per_ip_limit"))
clientsPerIPLimit, clientsPerIPLimitInvalid := ParseClientsPerIPLimit(handler.cfg, request.Form.Get("clients_per_ip_limit"))
publicLobby, publicLobbyInvalid := ParseBoolean("public", request.Form.Get("public"))

var lowercaser cases.Caser
Expand Down Expand Up @@ -174,7 +174,7 @@ func (handler *V1Handler) postLobby(writer http.ResponseWriter, request *http.Re

SetUsersessionCookie(writer, player)

lobbyData := CreateLobbyData(lobby)
lobbyData := CreateLobbyData(handler.cfg, lobby)

if started, _, err := easyjson.MarshalToHTTPResponseWriter(lobbyData, writer); err != nil {
if !started {
Expand Down Expand Up @@ -221,7 +221,7 @@ func (handler *V1Handler) postPlayer(writer http.ResponseWriter, request *http.R
player.SetLastKnownAddress(GetIPAddressFromRequest(request))
}

lobbyData = CreateLobbyData(lobby)
lobbyData = CreateLobbyData(handler.cfg, lobby)
})

if lobbyData != nil {
Expand Down Expand Up @@ -280,11 +280,11 @@ func (handler *V1Handler) patchLobby(writer http.ResponseWriter, request *http.R
}

// Editable properties
maxPlayers, maxPlayersInvalid := ParseMaxPlayers(request.Form.Get("max_players"))
drawingTime, drawingTimeInvalid := ParseDrawingTime(request.Form.Get("drawing_time"))
rounds, roundsInvalid := ParseRounds(request.Form.Get("rounds"))
maxPlayers, maxPlayersInvalid := ParseMaxPlayers(handler.cfg, request.Form.Get("max_players"))
drawingTime, drawingTimeInvalid := ParseDrawingTime(handler.cfg, request.Form.Get("drawing_time"))
rounds, roundsInvalid := ParseRounds(handler.cfg, request.Form.Get("rounds"))
customWordsPerTurn, customWordsPerTurnInvalid := ParseCustomWordsPerTurn(request.Form.Get("custom_words_per_turn"))
clientsPerIPLimit, clientsPerIPLimitInvalid := ParseClientsPerIPLimit(request.Form.Get("clients_per_ip_limit"))
clientsPerIPLimit, clientsPerIPLimitInvalid := ParseClientsPerIPLimit(handler.cfg, request.Form.Get("clients_per_ip_limit"))
publicLobby, publicLobbyInvalid := ParseBoolean("public", request.Form.Get("public"))

owner := lobby.Owner
Expand Down Expand Up @@ -389,9 +389,9 @@ type LobbyData struct {

// CreateLobbyData creates a ready to use LobbyData object containing data
// from the passed Lobby.
func CreateLobbyData(lobby *game.Lobby) *LobbyData {
func CreateLobbyData(cfg *config.Config, lobby *game.Lobby) *LobbyData {
return &LobbyData{
SettingBounds: game.LobbySettingBounds,
SettingBounds: cfg.LobbySettingBounds,
EditableLobbySettings: lobby.EditableLobbySettings,
LobbyID: lobby.LobbyID,
DrawingBoardBaseWidth: game.DrawingBoardBaseWidth,
Expand Down
18 changes: 16 additions & 2 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"time"

"github.com/caarlos0/env/v10"
"github.com/scribble-rs/scribble.rs/internal/game"
"github.com/subosito/gotenv"
)

Expand Down Expand Up @@ -53,6 +54,7 @@ type Config struct {
// creation page. It doesn't affect the default values of lobbies created
// via the API.
LobbySettingDefaults LobbySettingDefaults `envPrefix:"LOBBY_SETTING_DEFAULTS_"`
LobbySettingBounds game.SettingBounds `envPrefix:"LOBBY_SETTING_BOUNDS_"`
Port uint16 `env:"PORT"`
CORS CORS `envPrefix:"CORS_"`
LobbyCleanup LobbyCleanup `envPrefix:"LOBBY_CLEANUP_"`
Expand All @@ -64,11 +66,23 @@ var Default = Config{
Public: "false",
DrawingTime: "120",
Rounds: "4",
MaxPlayers: "12",
MaxPlayers: "24",
CustomWordsPerTurn: "3",
ClientsPerIPLimit: "1",
ClientsPerIPLimit: "2",
Language: "english",
},
LobbySettingBounds: game.SettingBounds{
MinDrawingTime: 60,
MaxDrawingTime: 300,
MinRounds: 1,
MaxRounds: 20,
MinMaxPlayers: 2,
MaxMaxPlayers: 24,
MinClientsPerIPLimit: 1,
MaxClientsPerIPLimit: 24,
MinCustomWordsPerTurn: 1,
MaxCustomWordsPerTurn: 3,
},
CORS: CORS{
AllowedOrigins: []string{"*"},
AllowCredentials: false,
Expand Down
12 changes: 6 additions & 6 deletions internal/frontend/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ func (handler *SSRHandler) homePageHandler(writer http.ResponseWriter, request *
func (handler *SSRHandler) createDefaultLobbyCreatePageData() *LobbyCreatePageData {
return &LobbyCreatePageData{
BasePageConfig: handler.basePageConfig,
SettingBounds: game.LobbySettingBounds,
SettingBounds: handler.cfg.LobbySettingBounds,
Languages: game.SupportedLanguages,
LobbySettingDefaults: handler.cfg.LobbySettingDefaults,
}
Expand All @@ -105,11 +105,11 @@ func (handler *SSRHandler) ssrCreateLobby(writer http.ResponseWriter, request *h
}

languageData, languageKey, languageInvalid := api.ParseLanguage(request.Form.Get("language"))
drawingTime, drawingTimeInvalid := api.ParseDrawingTime(request.Form.Get("drawing_time"))
rounds, roundsInvalid := api.ParseRounds(request.Form.Get("rounds"))
maxPlayers, maxPlayersInvalid := api.ParseMaxPlayers(request.Form.Get("max_players"))
drawingTime, drawingTimeInvalid := api.ParseDrawingTime(handler.cfg, request.Form.Get("drawing_time"))
rounds, roundsInvalid := api.ParseRounds(handler.cfg, request.Form.Get("rounds"))
maxPlayers, maxPlayersInvalid := api.ParseMaxPlayers(handler.cfg, request.Form.Get("max_players"))
customWordsPerTurn, customWordsPerTurnInvalid := api.ParseCustomWordsPerTurn(request.Form.Get("custom_words_per_turn"))
clientsPerIPLimit, clientsPerIPLimitInvalid := api.ParseClientsPerIPLimit(request.Form.Get("clients_per_ip_limit"))
clientsPerIPLimit, clientsPerIPLimitInvalid := api.ParseClientsPerIPLimit(handler.cfg, request.Form.Get("clients_per_ip_limit"))
publicLobby, publicLobbyInvalid := api.ParseBoolean("public", request.Form.Get("public"))

var lowercaser cases.Caser
Expand All @@ -123,7 +123,7 @@ func (handler *SSRHandler) ssrCreateLobby(writer http.ResponseWriter, request *h
// Prevent resetting the form, since that would be annoying as hell.
pageData := LobbyCreatePageData{
BasePageConfig: handler.basePageConfig,
SettingBounds: game.LobbySettingBounds,
SettingBounds: handler.cfg.LobbySettingBounds,
LobbySettingDefaults: config.LobbySettingDefaults{
Public: request.Form.Get("public"),
DrawingTime: request.Form.Get("drawing_time"),
Expand Down
4 changes: 2 additions & 2 deletions internal/frontend/lobby.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func (handler *SSRHandler) ssrEnterLobby(writer http.ResponseWriter, request *ht
if !(strings.Contains(userAgent, "gecko") || strings.Contains(userAgent, "chrome") || strings.Contains(userAgent, "opera") || strings.Contains(userAgent, "safari")) {
err := pageTemplates.ExecuteTemplate(writer, "robot-page", &robotPageData{
BasePageConfig: handler.basePageConfig,
LobbyData: api.CreateLobbyData(lobby),
LobbyData: api.CreateLobbyData(handler.cfg, lobby),
})
if err != nil {
log.Printf("error templating robot page: %d\n", err)
Expand Down Expand Up @@ -76,7 +76,7 @@ func (handler *SSRHandler) ssrEnterLobby(writer http.ResponseWriter, request *ht

pageData = &lobbyPageData{
BasePageConfig: handler.basePageConfig,
LobbyData: api.CreateLobbyData(lobby),
LobbyData: api.CreateLobbyData(handler.cfg, lobby),
Translation: translation,
Locale: locale,
}
Expand Down
9 changes: 6 additions & 3 deletions internal/frontend/lobby_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,18 @@ import (
"testing"

"github.com/scribble-rs/scribble.rs/internal/api"
"github.com/scribble-rs/scribble.rs/internal/config"
"github.com/scribble-rs/scribble.rs/internal/game"
)

func TestCreateLobby(t *testing.T) {
t.Parallel()

data := api.CreateLobbyData(&game.Lobby{
LobbyID: "TEST",
})
data := api.CreateLobbyData(
&config.Default,
&game.Lobby{
LobbyID: "TEST",
})

var previousSize uint8
for _, suggestedSize := range data.SuggestedBrushSizes {
Expand Down
2 changes: 1 addition & 1 deletion internal/frontend/templating_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ func Test_templateLobbyPage(t *testing.T) {
CacheBust: "lol",
},
LobbyData: &api.LobbyData{
SettingBounds: game.LobbySettingBounds,
SettingBounds: config.Default.LobbySettingBounds,
},
Translation: translations.DefaultTranslation,
})
Expand Down
56 changes: 21 additions & 35 deletions internal/game/lobby.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,31 +20,17 @@ import (
"github.com/gofrs/uuid/v5"
)

var (
LobbySettingBounds = SettingBounds{
MinDrawingTime: 60,
MaxDrawingTime: 300,
MinRounds: 1,
MaxRounds: 20,
MinMaxPlayers: 2,
MaxMaxPlayers: 24,
MinClientsPerIPLimit: 1,
MaxClientsPerIPLimit: 24,
MinCustomWordsPerTurn: 1,
MaxCustomWordsPerTurn: 3,
}
SupportedLanguages = map[string]string{
"english_gb": "English (GB)",
"english": "English (US)",
"italian": "Italian",
"german": "German",
"french": "French",
"dutch": "Dutch",
"ukrainian": "Ukrainian",
"russian": "Russian",
"polish": "Polish",
}
)
var SupportedLanguages = map[string]string{
"english_gb": "English (GB)",
"english": "English (US)",
"italian": "Italian",
"german": "German",
"french": "French",
"dutch": "Dutch",
"ukrainian": "Ukrainian",
"russian": "Russian",
"polish": "Polish",
}

const (
DrawingBoardBaseWidth = 1600
Expand All @@ -59,16 +45,16 @@ const (
// SettingBounds defines the lower and upper bounds for the user-specified
// lobby creation input.
type SettingBounds struct {
MinDrawingTime int `json:"minDrawingTime"`
MaxDrawingTime int `json:"maxDrawingTime"`
MinRounds int `json:"minRounds"`
MaxRounds int `json:"maxRounds"`
MinMaxPlayers int `json:"minMaxPlayers"`
MaxMaxPlayers int `json:"maxMaxPlayers"`
MinClientsPerIPLimit int `json:"minClientsPerIpLimit"`
MaxClientsPerIPLimit int `json:"maxClientsPerIpLimit"`
MinCustomWordsPerTurn int `json:"minCustomWordsPerTurn"`
MaxCustomWordsPerTurn int `json:"maxCustomWordsPerTurn"`
MinDrawingTime int `json:"minDrawingTime" env:"MIN_DRAWING_TIME"`
MaxDrawingTime int `json:"maxDrawingTime" env:"MAX_DRAWING_TIME"`
MinRounds int `json:"minRounds" env:"MIN_ROUNDS"`
MaxRounds int `json:"maxRounds" env:"MAX_ROUNDS"`
MinMaxPlayers int `json:"minMaxPlayers" env:"MIN_MAX_PLAYERS"`
MaxMaxPlayers int `json:"maxMaxPlayers" env:"MAX_MAX_PLAYERS"`
MinClientsPerIPLimit int `json:"minClientsPerIpLimit" env:"MIN_CLIENTS_PER_IP_LIMIT"`
MaxClientsPerIPLimit int `json:"maxClientsPerIpLimit" env:"MAX_CLIENTS_PER_IP_LIMIT"`
MinCustomWordsPerTurn int `json:"minCustomWordsPerTurn" env:"MIN_CUSTOM_WORDS_PER_TURN"`
MaxCustomWordsPerTurn int `json:"maxCustomWordsPerTurn" env:"MAX_CUSTOM_WORDS_PER_TURN"`
}

func (lobby *Lobby) HandleEvent(eventType string, payload []byte, player *Player) error {
Expand Down

0 comments on commit 242c800

Please sign in to comment.