feat: Enhance UgcPurchasablesController to handle bulk requests with object arrays

- Updated Bulk method to parse incoming JSON object arrays for UGC item IDs.
- Introduced ReadBulkIdsAsync to handle both object arrays and flat GUID lists.
- Added synthetic placeholder responses for missing UGC items to prevent client errors.

feat: Implement MatchmakeRoom and MatchmakeSubRoom endpoints in GoToController

- Added MatchmakeRoom and MatchmakeSubRoom methods to facilitate joining public and sub-rooms by numeric ID.
- Enhanced ApplySubRoomMutation to ensure proper state transitions for sub-rooms.
- Improved logging for matchmaking actions.

fix: Refactor PlayerSettingsController to handle database save exceptions

- Introduced SaveSettingsChangesAsync to manage DbUpdateException for busy SQLite scenarios.
- Updated methods to call SaveSettingsChangesAsync instead of direct SaveChangesAsync.

chore: Update URL coverage documentation for new matchmaking endpoints

- Documented new MatchmakeRoom and MatchmakeSubRoom endpoints in url-coverage.md.

chore: Add default room data file for room loading

- Included default_room.room to serve as a fallback for missing room data.

fix: Improve SQLite concurrency handling in DatabaseBootstrap

- Configured SQLite to use WAL mode and set a busy timeout for better concurrency.

chore: Create SqliteErrors utility for handling SQLite exceptions

- Added SqliteErrors class to encapsulate logic for detecting busy SQLite exceptions.

refactor: Update RoomDataBlobService to serve default room data

- Modified GetDefaultBlob to load and serve a default room blob with proper role data.
This commit is contained in:
Alexa
2026-06-23 20:54:29 +03:00
parent 27e5e0064c
commit 02f7bc386d
18 changed files with 1327 additions and 170 deletions
+19
View File
@@ -0,0 +1,19 @@
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
namespace DorkNet.Server.Data;
internal static class SqliteErrors
{
public static bool IsBusy(DbUpdateException ex)
{
for (Exception? current = ex; current is not null; current = current.InnerException)
{
if (current is SqliteException sqlite &&
(sqlite.SqliteErrorCode == 5 || sqlite.SqliteErrorCode == 6))
return true;
}
return false;
}
}
Binary file not shown.
+4
View File
@@ -377,6 +377,10 @@ These all live on `match.rec.net` (locally: `match.localhost`).
| POST | `goto/player/{playerId}` | REAL | `Match.GoToController.GoToPlayer` — uses `PlayerPresenceService` to find where the target is and routes the caller there |
| POST | `goto/instance/{instanceId}` | REAL | `Match.GoToController.GoToInstance` — direct join to a specific room instance |
| POST | `goto/invite/{inviteId}` | REAL | `Match.GoToController.GoToInvite` — resolves an invite to its target room/instance |
| POST/GET | `matchmake/room/{roomId}` | REAL | `Match.GoToController.MatchmakeRoom` — the 2023 client's "join this public room" call (navigates by numeric id, not name). Reuses `BuildResponseAsync`; without it every public-room join 404s and the player bounces to dorm |
| POST/GET | `matchmake/room/{roomId}/{subRoomId}` | REAL | `Match.GoToController.MatchmakeSubRoom` — sub-room form; resolves the `RoomScenes` row by `OrderIndex` |
| POST | `matchmake/dorm` | REAL | `Match.MatchController.MatchmakeDorm` — builds the caller's personal-dorm `RoomInstance` |
| POST | `matchmake/none` | REAL | `Match.MatchController.MatchmakeNone` — returns the caller's current room (or dorm) without changing it |
| POST | `player/heartbeat` | REAL | `Match.MatchPlayerController.Heartbeat` — refreshes the caller's `PlayerPresenceService` entry; also has a duplicate in `ApiNamespaceStubsController.Heartbeat` for the api-host case |
## Catch-all wildcards (informational)