Refactor room data blob handling and permissions

- Updated the RoomsController to utilize synthetic CDN keys for data blobs.
- Introduced methods for determining current or synthetic data blob names.
- Adjusted room role permissions to align with new game role definitions.
- Enhanced the SanitizeController with a new endpoint for purity checks.
- Modified Match and PlayerPresence services to handle deferred presence commits.
- Improved RoomDataBlobService to support new game role and tool tag settings.
- Added support for boot dorm grace period in PlayerPresenceService.
- Updated protobuf definitions to reflect new room role and game role structures.

You are now able to go into dorm and the rec center!
This commit is contained in:
Alexa
2026-06-24 12:02:13 +03:00
parent 5274da03b4
commit 323c17bedb
11 changed files with 733 additions and 81 deletions
+11 -5
View File
@@ -19,7 +19,7 @@ public sealed class JoinTimeoutService(
{
if (room is null) return;
if (IsDorm(room))
if (IsDorm(room) && !deferPresenceCommit)
{
ClearForPlayer(playerId, "dorm");
return;
@@ -40,6 +40,12 @@ public sealed class JoinTimeoutService(
_ = WatchAsync(playerId, pending);
}
public (RoomInstanceDto TargetRoom, bool DeferPresenceCommit)? GetPending(long playerId)
{
if (!_pending.TryGetValue(playerId, out var pending)) return null;
return (pending.TargetRoom, pending.DeferPresenceCommit);
}
public (RoomInstanceDto TargetRoom, bool DeferPresenceCommit)? MarkCompleted(long playerId, long instanceId, string outcome)
{
if (!_pending.TryGetValue(playerId, out var pending) || pending.InstanceId != instanceId)
@@ -55,7 +61,7 @@ public sealed class JoinTimeoutService(
return (pending.TargetRoom, pending.DeferPresenceCommit);
}
public async Task MarkFailedAsync(long playerId, long instanceId, string outcome)
public Task MarkFailedAsync(long playerId, long instanceId, string outcome)
{
var completed = MarkCompleted(playerId, instanceId, outcome);
@@ -66,14 +72,14 @@ public sealed class JoinTimeoutService(
logger.LogInformation(
"[join-watchdog] failure ignored player={PlayerId} instance={InstanceId} current={CurrentInstance}",
playerId, instanceId, current?.RoomInstanceId);
return;
return Task.CompletedTask;
}
presence.Clear(playerId);
await notifications.KickPlayerAsync(playerId, "Room join failed. Returning to dorm.");
logger.LogWarning(
"[join-watchdog] kicked failed join player={PlayerId} room={RoomId}/{RoomName} instance={InstanceId} outcome={Outcome}",
"[join-watchdog] cleared failed join player={PlayerId} room={RoomId}/{RoomName} instance={InstanceId} outcome={Outcome}",
playerId, failedRoom.RoomId, failedRoom.Name, instanceId, outcome);
return Task.CompletedTask;
}
private async Task WatchAsync(long playerId, PendingJoin pending)