Add in-game chat, bot fill for casual, and borderless fullscreen

- In-game chat: T=all, Y=team (race doubles as team), server-relayed and
  team-filtered via new ChatManager autoload; last 10 messages shown
  bottom-left (chat/chat_box.gd).
- Bot fill for casual (bots/): keeps each of the match's 2 offered races
  at a minimum of 7 total humans+bots, spawning/despawning reactively as
  players join/leave. Bots always fly their race's fighter and use
  negative peer_ids so they ride the existing networked-ship stack
  (spawning, loadout sync, health/position sync, bullet attribution) with
  no special-casing. Casual matchmaking now forms with just 1 real player
  queued instead of waiting for a second (matchmaking-api/).
- Borderless fullscreen with stretch scaling disabled instead of scaling
  the Steam-Deck-matched 1280x800 canvas up to fill PC monitors (which
  read as zoomed in) — PC monitors now reveal more world/HUD at native
  size instead. Reworked main_menu/team_select/chat_box to position via
  anchors relative to the real window instead of hardcoded coordinates.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-13 17:02:12 -04:00
parent edcda92812
commit c0b5f421c5
28 changed files with 705 additions and 79 deletions
+16 -5
View File
@@ -65,13 +65,12 @@ class QueueManager:
tickets.sort(key=lambda t: t.queued_at)
return tickets
async def _try_form_match(self, mode: Mode, team_size: int, db: AsyncSession) -> None:
required = team_size * 2
async def _try_form_match(self, mode: Mode, required: int, cap: int, db: AsyncSession) -> None:
async with self._lock:
waiting = self._waiting(mode)
if len(waiting) < required:
return
group = waiting[:required]
group = waiting[:cap]
server = (
await db.execute(
@@ -99,8 +98,20 @@ class QueueManager:
while True:
await asyncio.sleep(2)
async with async_session() as db:
await self._try_form_match(Mode.casual, settings.casual_team_size, db)
await self._try_form_match(Mode.ranked, settings.ranked_team_size, db)
# Casual has bot fill (spacewar/bots/bot_manager.gd) — bots pad
# both teams up to GameConfig.bot_min_team_size, so a single
# queued player is enough to form a match. Still group in
# anyone else who queues in the same tick, up to the real
# casual_team_size*2 target, rather than capping at 1v1.
# Ranked has no bots, so it still needs the full
# ranked_team_size*2 real players queued before forming.
await self._try_form_match(Mode.casual, required=1, cap=settings.casual_team_size * 2, db=db)
await self._try_form_match(
Mode.ranked,
required=settings.ranked_team_size * 2,
cap=settings.ranked_team_size * 2,
db=db,
)
queue_manager = QueueManager()