Merge pull request #640 from EraOSBeta/master

QoL for Teams Sessions, FFA Sessions, and Servers
This commit is contained in:
Eric Froemling 2024-03-01 20:08:55 -08:00 committed by GitHub
commit 1f811a2f52
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 81 additions and 21 deletions

View File

@ -37,12 +37,12 @@
- Added feature - Added feature
### Vishal332008 ### Vishal332008
- Bug Fixer - QoL and Bug Fixer
- Modder - Modder
### Era0S ### Era0S
- Community Suggestions Implementer - Community Suggestions Implementer
- Bug Fixer - QoL and Bug Fixer
- Modder - Modder
### VinniTR ### VinniTR
@ -52,6 +52,7 @@
- Created the original "reject_recently_left_players" plugin - Created the original "reject_recently_left_players" plugin
### Temp (3alTemp) ### Temp (3alTemp)
- Original idea for customizable series length on GUI builds
- Modder & Bug Fixer - Modder & Bug Fixer
### brostos ### brostos

View File

@ -406,6 +406,10 @@ class ServerController:
else: else:
raise RuntimeError(f'Unknown session type {sessiontype}') raise RuntimeError(f'Unknown session type {sessiontype}')
appcfg['Teams Series Length'] = self._config.teams_series_length
appcfg['FFA Series Length'] = self._config.ffa_series_length
# deprecated, left here in order to not break mods
classic.teams_series_length = self._config.teams_series_length classic.teams_series_length = self._config.teams_series_length
classic.ffa_series_length = self._config.ffa_series_length classic.ffa_series_length = self._config.ffa_series_length
@ -427,6 +431,10 @@ class ServerController:
self._config.player_rejoin_cooldown self._config.player_rejoin_cooldown
) )
bascenev1.set_max_players_override(
self._config.session_max_players_override
)
# And here.. we.. go. # And here.. we.. go.
if self._config.stress_test_players is not None: if self._config.stress_test_players is not None:
# Special case: run a stress test. # Special case: run a stress test.

View File

@ -103,8 +103,8 @@ class ClassicSubsystem(babase.AppSubsystem):
self.maps: dict[str, type[bascenev1.Map]] = {} self.maps: dict[str, type[bascenev1.Map]] = {}
# Gameplay. # Gameplay.
self.teams_series_length = 7 self.teams_series_length = 7 # deprecated, left for old mods
self.ffa_series_length = 24 self.ffa_series_length = 24 # deprecated, left for old mods
self.coop_session_args: dict = {} self.coop_session_args: dict = {}
# UI. # UI.

View File

@ -231,7 +231,9 @@ from bascenev1._settings import (
IntSetting, IntSetting,
Setting, Setting,
) )
from bascenev1._session import Session, set_player_rejoin_cooldown from bascenev1._session import (
Session, set_player_rejoin_cooldown, set_max_players_override
)
from bascenev1._stats import PlayerScoredMessage, PlayerRecord, Stats from bascenev1._stats import PlayerScoredMessage, PlayerRecord, Stats
from bascenev1._team import SessionTeam, Team, EmptyTeam from bascenev1._team import SessionTeam, Team, EmptyTeam
from bascenev1._teamgame import TeamGameActivity from bascenev1._teamgame import TeamGameActivity
@ -426,6 +428,7 @@ __all__ = [
'set_public_party_queue_enabled', 'set_public_party_queue_enabled',
'set_public_party_stats_url', 'set_public_party_stats_url',
'set_player_rejoin_cooldown', 'set_player_rejoin_cooldown',
'set_max_players_override',
'set_replay_speed_exponent', 'set_replay_speed_exponent',
'set_touchscreen_editing', 'set_touchscreen_editing',
'setmusic', 'setmusic',

View File

@ -67,8 +67,8 @@ class MultiTeamSession(Session):
max_players=self.get_max_players(), max_players=self.get_max_players(),
) )
self._series_length: int = classic.teams_series_length self._series_length: int = int(cfg.get('Teams Series Length', 7))
self._ffa_series_length: int = classic.ffa_series_length self._ffa_series_length: int = int(cfg.get('FFA Series Length', 24))
show_tutorial = cfg.get('Show Tutorial', True) show_tutorial = cfg.get('Show Tutorial', True)

View File

@ -23,6 +23,9 @@ if TYPE_CHECKING:
# such as skipping respawn waits. # such as skipping respawn waits.
_g_player_rejoin_cooldown: float = 0.0 _g_player_rejoin_cooldown: float = 0.0
# overrides the session's decision of max_players
_max_players_override: int | None = None
def set_player_rejoin_cooldown(cooldown: float) -> None: def set_player_rejoin_cooldown(cooldown: float) -> None:
"""Set the cooldown for individual players rejoining after leaving.""" """Set the cooldown for individual players rejoining after leaving."""
@ -30,6 +33,12 @@ def set_player_rejoin_cooldown(cooldown: float) -> None:
_g_player_rejoin_cooldown = max(0.0, cooldown) _g_player_rejoin_cooldown = max(0.0, cooldown)
def set_max_players_override(max_players: int | None) -> None:
"""Set the override for how many players can join a session"""
global _max_players_override # pylint: disable=global-statement
_max_players_override = max_players
class Session: class Session:
"""Defines a high level series of bascenev1.Activity-es. """Defines a high level series of bascenev1.Activity-es.
@ -161,7 +170,11 @@ class Session:
self.sessionteams = [] self.sessionteams = []
self.sessionplayers = [] self.sessionplayers = []
self.min_players = min_players self.min_players = min_players
self.max_players = max_players self.max_players = (
max_players
if _max_players_override is None
else _max_players_override
)
self.customdata = {} self.customdata = {}
self._in_set_activity = False self._in_set_activity = False
@ -255,7 +268,7 @@ class Session:
babase.app.classic is not None babase.app.classic is not None
and babase.app.classic.stress_test_update_timer is None and babase.app.classic.stress_test_update_timer is None
): ):
if len(self.sessionplayers) >= self.max_players: if len(self.sessionplayers) >= self.max_players >= 0:
# Print a rejection message *only* to the client trying to # Print a rejection message *only* to the client trying to
# join (prevents spamming everyone else in the game). # join (prevents spamming everyone else in the game).
_bascenev1.getsound('error').play() _bascenev1.getsound('error').play()

View File

@ -94,6 +94,8 @@ class ConfigNumberEdit:
changesound: bool = True, changesound: bool = True,
textscale: float = 1.0, textscale: float = 1.0,
as_percent: bool = False, as_percent: bool = False,
fallback_value: float = 0.0,
f: int = 1,
): ):
if displayname is None: if displayname is None:
displayname = configkey displayname = configkey
@ -103,8 +105,12 @@ class ConfigNumberEdit:
self._maxval = maxval self._maxval = maxval
self._increment = increment self._increment = increment
self._callback = callback self._callback = callback
self._value = bui.app.config.resolve(configkey) try:
self._value = bui.app.config.resolve(configkey)
except ValueError:
self._value = bui.app.config.get(configkey, fallback_value)
self._as_percent = as_percent self._as_percent = as_percent
self._f = f
self.nametext = bui.textwidget( self.nametext = bui.textwidget(
parent=parent, parent=parent,
@ -171,5 +177,5 @@ class ConfigNumberEdit:
if self._as_percent: if self._as_percent:
val = f'{round(self._value*100.0)}%' val = f'{round(self._value*100.0)}%'
else: else:
val = f'{self._value:.1f}' val = f'{self._value:.{self._f}f}'
bui.textwidget(edit=self.valuetext, text=val) bui.textwidget(edit=self.valuetext, text=val)

View File

@ -33,6 +33,7 @@ class PlayOptionsWindow(PopupWindow):
# pylint: disable=too-many-locals # pylint: disable=too-many-locals
from bascenev1 import filter_playlist, get_map_class from bascenev1 import filter_playlist, get_map_class
from bauiv1lib.playlist import PlaylistTypeVars from bauiv1lib.playlist import PlaylistTypeVars
from bauiv1lib.config import ConfigNumberEdit
self._r = 'gameListWindow' self._r = 'gameListWindow'
self._delegate = delegate self._delegate = delegate
@ -52,7 +53,7 @@ class PlayOptionsWindow(PopupWindow):
self._playlist = playlist self._playlist = playlist
self._width = 500.0 self._width = 500.0
self._height = 330.0 - 50.0 self._height = 370.0 - 50.0
# In teams games, show the custom names/colors button. # In teams games, show the custom names/colors button.
if self._sessiontype is bs.DualTeamSession: if self._sessiontype is bs.DualTeamSession:
@ -275,13 +276,37 @@ class PlayOptionsWindow(PopupWindow):
texture=bui.gettexture('lock'), texture=bui.gettexture('lock'),
) )
y_offs = 50 if show_shuffle_check_box else 0
# Series Length
y_offs2 = 40 if self._sessiontype is bs.DualTeamSession else 0
self._series_length_numedit = ConfigNumberEdit(
parent=self.root_widget,
position=(100, 200 + y_offs + y_offs2),
configkey=(
'FFA' if self._sessiontype is bs.FreeForAllSession else 'Teams'
) + ' Series Length',
displayname=bui.Lstr(
resource=self._r + (
'.pointsToWinText'
if self._sessiontype is bs.FreeForAllSession
else '.seriesLengthText'
)
),
minval=1.0,
increment=1.0 if self._sessiontype is bs.FreeForAllSession else 2.0,
fallback_value=(
24 if self._sessiontype is bs.FreeForAllSession else 7
),
f=0,
)
# Team names/colors. # Team names/colors.
self._custom_colors_names_button: bui.Widget | None self._custom_colors_names_button: bui.Widget | None
if self._sessiontype is bs.DualTeamSession: if self._sessiontype is bs.DualTeamSession:
y_offs = 50 if show_shuffle_check_box else 0
self._custom_colors_names_button = bui.buttonwidget( self._custom_colors_names_button = bui.buttonwidget(
parent=self.root_widget, parent=self.root_widget,
position=(100, 200 + y_offs), position=(100, 195 + y_offs),
size=(290, 35), size=(290, 35),
on_activate_call=bui.WeakCall(self._custom_colors_names_press), on_activate_call=bui.WeakCall(self._custom_colors_names_press),
autoselect=True, autoselect=True,

View File

@ -47,10 +47,14 @@ class ServerConfig:
# Max devices in the party. Note that this does *NOT* mean max players. # Max devices in the party. Note that this does *NOT* mean max players.
# Any device in the party can have more than one player on it if they have # Any device in the party can have more than one player on it if they have
# multiple controllers. Also, this number currently includes the server so # multiple controllers. Also, this number currently includes the server so
# generally make it 1 bigger than you need. Max-players is not currently # generally make it 1 bigger than you need.
# exposed but I'll try to add that soon.
max_party_size: int = 6 max_party_size: int = 6
# Max players that can join a session. If present this will override the
# session's preferred max_players. if a value below 0 is given player limit
# will be removed.
session_max_players_override: int | None = None
# Options here are 'ffa' (free-for-all), 'teams' and 'coop' (cooperative) # Options here are 'ffa' (free-for-all), 'teams' and 'coop' (cooperative)
# This value is ignored if you supply a playlist_code (see below). # This value is ignored if you supply a playlist_code (see below).
session_type: str = 'ffa' session_type: str = 'ffa'