mirror of
https://github.com/DorkSquadRR/DorkNet.git
synced 2026-10-25 23:18:44 -07:00
fix: address review on the notification pushes
- Force-join's RoomUpdate carries the room's role grants, so it no longer wipes them from the client's cached room. - The consumable push reports IsTransferable the same as the inventory list does. - A rejected private-instance join sends the owner at most one "wants to join" message per requester and instance every 5 minutes. - SubscribeToPlayers ignores sets over 5,000 ids and keeps the current subscriptions. - The subscriber exclusion list looks up online friends' connections in one pipelined Redis batch instead of one call per friend.
This commit is contained in:
@@ -463,7 +463,9 @@ public class InventoryController(
|
||||
CreatedAt = inv.AcquiredAt,
|
||||
ActiveDurationMinutes = (int?)null,
|
||||
inv.IsActive,
|
||||
IsTransferable = true,
|
||||
// Same as GET api/consumables/v2/getUnlocked, so a push never flips
|
||||
// what the inventory list says.
|
||||
IsTransferable = false,
|
||||
};
|
||||
|
||||
private static object ToConsumableWire(PlayerInventoryEntity inv, StoreItemEntity item)
|
||||
|
||||
@@ -3520,9 +3520,15 @@ public class AdminController(
|
||||
.Where(sc => sc.RoomId == room.Id)
|
||||
.OrderBy(sc => sc.OrderIndex)
|
||||
.ToListAsync();
|
||||
// With every role grant: the client replaces its cached room with
|
||||
// this, so a payload without them would drop everyone's roles.
|
||||
var forceJoinRoles = await db.RoomRoles
|
||||
.Where(r => r.RoomId == room.Id)
|
||||
.ToListAsync();
|
||||
await notifications.NotifyAsync(id,
|
||||
PushNotificationId.SubscriptionUpdateRoom,
|
||||
DorkNet.Server.Controllers.API.Rooms.V2.RoomsController.BuildRoomServerDetails(room, forceJoinScenes));
|
||||
DorkNet.Server.Controllers.API.Rooms.V2.RoomsController.BuildRoomServerDetails(
|
||||
room, forceJoinScenes, roles: forceJoinRoles));
|
||||
|
||||
await LogAsync("force_join", "player", id,
|
||||
$"room={body.RoomId} sub={subRoomId} instance={roomInstanceId} photon={photonRoomId}");
|
||||
|
||||
@@ -880,8 +880,11 @@ public class GoToController(
|
||||
callerId, playerId, theirRoom.RoomInstanceId);
|
||||
// Tell the OWNER someone tried to follow them in, as the
|
||||
// client's own "wants to join" message (RequestGameInvite,
|
||||
// from the caller), so they can send an invite.
|
||||
if (callerId is long requester)
|
||||
// from the caller), so they can send an invite. At most once
|
||||
// per requester, owner and instance per cooldown, so retrying
|
||||
// doesn't fill the owner's inbox.
|
||||
if (callerId is long requester
|
||||
&& JoinRequestCooldown.TryStart(requester, playerId, theirRoom.RoomInstanceId))
|
||||
await systemNotifications.SendAsync(playerId,
|
||||
SystemNotificationService.MessageType.RequestGameInvite, fromPlayerId: requester);
|
||||
return Ok(new MatchmakingResponseDto
|
||||
@@ -1670,3 +1673,35 @@ public class RoomInstanceDto
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Rate limit for "wants to join" messages: one per (requester,
|
||||
/// owner, room instance) per <see cref="Window"/>. Later retries and other
|
||||
/// instances still go through. Per replica, which is enough to stop a
|
||||
/// retry loop from flooding an inbox.</summary>
|
||||
internal static class JoinRequestCooldown
|
||||
{
|
||||
public static readonly TimeSpan Window = TimeSpan.FromMinutes(5);
|
||||
private static readonly System.Collections.Concurrent.ConcurrentDictionary<(long, long, long), DateTime> Last = new();
|
||||
|
||||
/// <summary>True when no request for this key was sent within the window
|
||||
/// (and records this one); false while it is cooling down.</summary>
|
||||
public static bool TryStart(long requester, long owner, long roomInstanceId)
|
||||
{
|
||||
var now = DateTime.UtcNow;
|
||||
if (Last.Count > 10_000)
|
||||
foreach (var (key, at) in Last)
|
||||
if (now - at > Window) Last.TryRemove(key, out _);
|
||||
|
||||
var k = (requester, owner, roomInstanceId);
|
||||
while (true)
|
||||
{
|
||||
if (!Last.TryGetValue(k, out var prev))
|
||||
{
|
||||
if (Last.TryAdd(k, now)) return true;
|
||||
continue;
|
||||
}
|
||||
if (now - prev < Window) return false;
|
||||
if (Last.TryUpdate(k, now, prev)) return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user