inventions: resolve real creator ids for a room (creatorIds)

api/inventions/v1/creatorIds was a stub returning an empty list, so the
2020.03 watch's GetCreatorIdsOfInventionsInRoom never learned which
creators it must request invention permissions for before spawning a
room's invention-based geometry. Resolve the real set from
InventionEntity.CreationRoomId via a shared ResolveRoomInventionsAsync
helper: direct matches (created in-place) unioned with the imported
cluster (most-frequent non-local CreationRoomId among the room creator's
inventions, since zip-imported inventions keep their original Rec Room
room id). Returns List<int> of distinct creator account ids.
This commit is contained in:
Alexa
2026-05-31 15:32:16 +03:00
parent f6a4fdc5fb
commit b26ae93014
2 changed files with 51 additions and 6 deletions
@@ -165,13 +165,58 @@ public class InventionsController(
});
}
/// <summary>GET <c>api/inventions/v1/creatorIds</c> — the distinct
/// creator account ids of every invention placed in a room
/// (<c>GetCreatorIdsOfInventionsInRoom</c>, called by the 2020.03
/// watch on room load). It uses these to resolve which creators it
/// must request invention permissions for before spawning a room's
/// invention-based geometry. Returns <c>List&lt;int&gt;</c> — empty
/// when the room has no tracked inventions.</summary>
[HttpGet("api/inventions/v1/creatorIds")]
public IActionResult CreatorIdsInRoom([FromQuery] long roomId)
public async Task<IActionResult> CreatorIdsInRoom([FromQuery] long roomId)
{
// We don't yet track per-room invention placements; return
// empty list (correct shape: List<int>).
_ = roomId;
return Ok(Array.Empty<int>());
var inventions = await ResolveRoomInventionsAsync(roomId);
var creatorIds = inventions
.Select(i => (int)i.CreatorPlayerId)
.Distinct()
.ToList();
return Ok(creatorIds);
}
/// <summary>Resolve the inventions that belong to a room. Direct
/// matches are inventions whose
/// <see cref="InventionEntity.CreationRoomId"/> equals the room's
/// local id (RR-Originals, dorms, anything created in-place).
/// Zip-imported rooms instead carry each invention's ORIGINAL Rec
/// Room CreationRoomId, which won't equal our local id and can't be
/// reverse-resolved without an OriginalRoomId column; we approximate
/// that cluster as the most-frequent non-local CreationRoomId among
/// the room creator's inventions. The two sets are unioned so a room
/// with both kinds resolves fully.</summary>
private async Task<List<InventionEntity>> ResolveRoomInventionsAsync(long roomId)
{
var creatorId = await db.Rooms
.Where(r => r.Id == roomId)
.Select(r => (long?)r.CreatorPlayerId)
.FirstOrDefaultAsync();
long? importedRoomId = null;
if (creatorId is long creator)
{
importedRoomId = await db.Inventions
.Where(i => !i.IsDeleted && i.CreatorPlayerId == creator
&& i.CreationRoomId != null && i.CreationRoomId != roomId)
.GroupBy(i => i.CreationRoomId)
.OrderByDescending(g => g.Count())
.Select(g => g.Key)
.FirstOrDefaultAsync();
}
return await db.Inventions
.Where(i => !i.IsDeleted
&& (i.CreationRoomId == roomId
|| (importedRoomId != null && i.CreationRoomId == importedRoomId)))
.ToListAsync();
}
// ── Single fetch ─────────────────────────────────────────────────────