mirror of
https://github.com/RYDE-WORK/ballistica.git
synced 2026-01-31 19:53:17 +08:00
A bit of tidying for co-op server mode
This commit is contained in:
parent
14ed8d24cb
commit
6ff2b30933
1
.idea/dictionaries/ericf.xml
generated
1
.idea/dictionaries/ericf.xml
generated
@ -1598,6 +1598,7 @@
|
||||
<w>outpath</w>
|
||||
<w>outputter</w>
|
||||
<w>outval</w>
|
||||
<w>outvals</w>
|
||||
<w>outvalue</w>
|
||||
<w>ouya</w>
|
||||
<w>overloadsigs</w>
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
### 1.6.5 (20388)
|
||||
- Added co-op support to server builds (thanks Dliwk!)
|
||||
|
||||
### 1.6.4 (20382)
|
||||
- Some cleanups in the Favorites tab of the gather window.
|
||||
|
||||
@ -112,8 +112,9 @@ class Activity(DependencyComponent, Generic[PlayerType, TeamType]):
|
||||
# transitions).
|
||||
inherits_tint = False
|
||||
|
||||
# Whether players should be allowed to join in the middle of
|
||||
# activity.
|
||||
# Whether players should be allowed to join in the middle of this
|
||||
# activity. Note that Sessions may not allow mid-activity-joins even
|
||||
# if the activity says its ok.
|
||||
allow_mid_activity_joins: bool = True
|
||||
|
||||
# If the activity fades or transitions in, it should set the length of
|
||||
|
||||
@ -166,51 +166,44 @@ class CoopSession(Session):
|
||||
from ba._general import WeakCall
|
||||
super().on_player_leave(sessionplayer)
|
||||
|
||||
_ba.timer(2.0, WeakCall(self._check_end_game))
|
||||
_ba.timer(2.0, WeakCall(self._handle_empty_activity))
|
||||
|
||||
def _check_end_game(self) -> None:
|
||||
if not _ba.app.server:
|
||||
self._end_session_if_empty()
|
||||
def _handle_empty_activity(self) -> None:
|
||||
"""Handle cases where all players have left the current activity."""
|
||||
|
||||
activity = self.getactivity()
|
||||
if activity is None:
|
||||
return # Probably everything is already broken, why do something?
|
||||
|
||||
if [player for player in activity.players if player.is_alive()]:
|
||||
return
|
||||
|
||||
with _ba.Context(activity):
|
||||
from ba._gameactivity import GameActivity
|
||||
|
||||
if isinstance(activity, GameActivity):
|
||||
activity.end_game()
|
||||
|
||||
def _end_session_if_empty(self) -> None:
|
||||
from ba._gameactivity import GameActivity
|
||||
activity = self.getactivity()
|
||||
if activity is None:
|
||||
return # Hmm what should we do in this case?
|
||||
|
||||
# If there's still players in the current activity, we're good.
|
||||
# If there are still players in the current activity, we're good.
|
||||
if activity.players:
|
||||
return
|
||||
|
||||
# If there's *no* players left in the current activity but there *is*
|
||||
# in the session, restart the activity to pull them into the game
|
||||
# (or quit if they're just in the lobby).
|
||||
# If there are *not* players in the current activity but there
|
||||
# *are* in the session:
|
||||
if not activity.players and self.sessionplayers:
|
||||
|
||||
# Special exception for tourney games; don't auto-restart these.
|
||||
if self.tournament_id is not None:
|
||||
self.end()
|
||||
else:
|
||||
# Don't restart joining activities; this probably means there's
|
||||
# someone with a chooser up in that case.
|
||||
if not activity.is_joining_activity:
|
||||
# If we're in a game, we should restart to pull in players
|
||||
# currently waiting in the session.
|
||||
if isinstance(activity, GameActivity):
|
||||
|
||||
# Never restart tourney games however; just end the session
|
||||
# if all players are gone.
|
||||
if self.tournament_id is not None:
|
||||
self.end()
|
||||
else:
|
||||
self.restart()
|
||||
|
||||
# Hmm; no players anywhere. lets just end the session.
|
||||
# Hmm; no players anywhere. Let's end the entire session if we're
|
||||
# running a GUI (or just the current game if we're running headless).
|
||||
else:
|
||||
self.end()
|
||||
if not _ba.app.headless_mode:
|
||||
self.end()
|
||||
else:
|
||||
if isinstance(activity, GameActivity):
|
||||
with _ba.Context(activity):
|
||||
activity.end_game()
|
||||
|
||||
def _on_tournament_restart_menu_press(
|
||||
self, resume_callback: Callable[[], Any]) -> None:
|
||||
@ -274,9 +267,10 @@ class CoopSession(Session):
|
||||
else:
|
||||
outcome = '' if results is None else results.get('outcome', '')
|
||||
|
||||
# If at any point we have no in-game players, quit out of the session
|
||||
# (this can happen if someone leaves in the tutorial for instance).
|
||||
if isinstance(activity, TutorialActivity):
|
||||
# If we're running with a gui and at any point we have no
|
||||
# in-game players, quit out of the session (this can happen if
|
||||
# someone leaves in the tutorial for instance).
|
||||
if not _ba.app.headless_mode:
|
||||
active_players = [p for p in self.sessionplayers if p.in_game]
|
||||
if not active_players:
|
||||
self.end()
|
||||
|
||||
@ -36,6 +36,10 @@ class Level:
|
||||
self._index: Optional[int] = None
|
||||
self._score_version_string: Optional[str] = None
|
||||
|
||||
def __repr__(self) -> str:
|
||||
cls = type(self)
|
||||
return f"<{cls.__module__}.{cls.__name__} '{self._name}'>"
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
"""The unique name for this Level."""
|
||||
|
||||
@ -98,8 +98,6 @@ class ServerController:
|
||||
self._playlist_fetch_got_response = False
|
||||
self._playlist_fetch_code = -1
|
||||
|
||||
self._coop_game_name = self._config.coop_game_name
|
||||
|
||||
# Now sit around doing any pre-launch prep such as waiting for
|
||||
# account sign-in or fetching playlists; this will kick off the
|
||||
# session once done.
|
||||
@ -349,11 +347,9 @@ class ServerController:
|
||||
appcfg['Team Tournament Playlist Randomize'] = (
|
||||
self._config.playlist_shuffle)
|
||||
elif sessiontype is CoopSession:
|
||||
gamename = self._coop_game_name or 'Default:Onslaught Training'
|
||||
campaignname, levelname = gamename.split(':')
|
||||
app.coop_session_args = {
|
||||
'campaign': campaignname,
|
||||
'level': levelname,
|
||||
'campaign': self._config.coop_campaign,
|
||||
'level': self._config.coop_level,
|
||||
}
|
||||
else:
|
||||
raise RuntimeError(f'Unknown session type {sessiontype}')
|
||||
|
||||
@ -206,11 +206,12 @@ class Session:
|
||||
return node
|
||||
|
||||
def should_allow_mid_activity_joins(self, activity: ba.Activity) -> bool:
|
||||
"""Returned value is used by the Session to determine
|
||||
whether to allow players to join in the middle of activity.
|
||||
"""Ask ourself if we should allow joins during an Activity.
|
||||
|
||||
Activity.allow_mid_activity_joins is also required to allow these
|
||||
joins."""
|
||||
Note that for a join to be allowed, both the Session and Activity
|
||||
have to be ok with it (via this function and the
|
||||
Activity.allow_mid_activity_joins property.
|
||||
"""
|
||||
del activity # Unused.
|
||||
return True
|
||||
|
||||
|
||||
@ -561,7 +561,7 @@ class RunaroundGame(ba.CoopGameActivity[Player, Team]):
|
||||
fail_message = None
|
||||
else:
|
||||
score = None
|
||||
fail_message = 'Reach wave 2 to rank.'
|
||||
fail_message = ba.Lstr(resource='reachWave2Text')
|
||||
|
||||
self.end(delay=delay,
|
||||
results={
|
||||
|
||||
@ -766,6 +766,7 @@
|
||||
<w>outpath</w>
|
||||
<w>outputter</w>
|
||||
<w>outval</w>
|
||||
<w>outvals</w>
|
||||
<w>outvalue</w>
|
||||
<w>ouya</w>
|
||||
<w>ovld</w>
|
||||
|
||||
@ -1837,11 +1837,11 @@ is pressed.</p>
|
||||
<dt><h4><a name="method_ba_CoopSession__should_allow_mid_activity_joins">should_allow_mid_activity_joins()</a></dt></h4><dd>
|
||||
<p><span>should_allow_mid_activity_joins(self, activity: <a href="#class_ba_Activity">ba.Activity</a>) -> bool</span></p>
|
||||
|
||||
<p>Returned value is used by the Session to determine
|
||||
whether to allow players to join in the middle of activity.</p>
|
||||
<p>Ask ourself if we should allow joins during an Activity.</p>
|
||||
|
||||
<p>Activity.allow_mid_activity_joins is also required to allow these
|
||||
joins.</p>
|
||||
<p>Note that for a join to be allowed, both the Session and Activity
|
||||
have to be ok with it (via this function and the
|
||||
Activity.allow_mid_activity_joins property.</p>
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
@ -5263,11 +5263,11 @@ session.setactivity(foo) and then <a href="#function_ba_newnode">ba.newnode</a>(
|
||||
<dt><h4><a name="method_ba_Session__should_allow_mid_activity_joins">should_allow_mid_activity_joins()</a></dt></h4><dd>
|
||||
<p><span>should_allow_mid_activity_joins(self, activity: <a href="#class_ba_Activity">ba.Activity</a>) -> bool</span></p>
|
||||
|
||||
<p>Returned value is used by the Session to determine
|
||||
whether to allow players to join in the middle of activity.</p>
|
||||
<p>Ask ourself if we should allow joins during an Activity.</p>
|
||||
|
||||
<p>Activity.allow_mid_activity_joins is also required to allow these
|
||||
joins.</p>
|
||||
<p>Note that for a join to be allowed, both the Session and Activity
|
||||
have to be ok with it (via this function and the
|
||||
Activity.allow_mid_activity_joins property.</p>
|
||||
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
@ -55,10 +55,7 @@ class ServerConfig:
|
||||
# This value is ignored if you supply a playlist_code (see below).
|
||||
session_type: str = 'ffa'
|
||||
|
||||
# There are unavailable co-op playlists now, so if you want to host a co-op
|
||||
# game, pass level name here.
|
||||
coop_game_name: Optional[str] = None
|
||||
|
||||
# Playlist-code for teams or free-for-all mode sessions.
|
||||
# To host your own custom playlists, use the 'share' functionality in the
|
||||
# playlist editor in the regular version of the game.
|
||||
# This will give you a numeric code you can enter here to host that
|
||||
@ -76,6 +73,15 @@ class ServerConfig:
|
||||
# (teams mode only).
|
||||
auto_balance_teams: bool = True
|
||||
|
||||
# The campaign used when in co-op session mode.
|
||||
# Do print(ba.app.campaigns) to see available campaign names.
|
||||
coop_campaign: str = 'Easy'
|
||||
|
||||
# The level name within the campaign used in co-op session mode.
|
||||
# For campaign name FOO, do print(ba.app.campaigns['FOO'].levels) to see
|
||||
# available level names.
|
||||
coop_level: str = 'Onslaught Training'
|
||||
|
||||
# Whether to enable telnet access.
|
||||
# IMPORTANT: This option is no longer available, as it was being used
|
||||
# for exploits. Live access to the running server is still possible through
|
||||
|
||||
@ -742,10 +742,14 @@ def _get_server_config_template_yaml(projroot: str) -> str:
|
||||
continue
|
||||
|
||||
if line != '' and not line.startswith('#'):
|
||||
vname, _vtype, veq, vval_raw = line.split()
|
||||
before_equal_sign, vval_raw = line.split('=', 1)
|
||||
before_equal_sign = before_equal_sign.strip()
|
||||
vval_raw = vval_raw.strip()
|
||||
# vname, _vtype, veq, vval_raw = line.split()
|
||||
vname, _vtype = before_equal_sign.split()
|
||||
assert vname.endswith(':')
|
||||
vname = vname[:-1]
|
||||
assert veq == '='
|
||||
# assert veq == '='
|
||||
vval: Any
|
||||
if vval_raw == 'field(default_factory=list)':
|
||||
vval = []
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user