using Microsoft.EntityFrameworkCore; using RadicadeServer.API.Notifications; using RadicadeServer.API.Storefront; using RadicadeServer.DB; using RadicadeServer.Extensions; using RadicadeServer.RecNet.Avatar; using RadicadeServer.RecNet.Enums.Store; using RadicadeServer.RecNet.Notifications; namespace RadicadeServer.Utils { public static class QuestRewardDelivery { private const string ManualConsumedNotificationId = "gift.manualconsumed"; public static async Task DeliverOnArrivalAsync(RecDBContext db, long playerId, long enteredRoomId) { try { return await DeliverAsync(db, playerId, enteredRoomId); } catch (Exception) { return 0; } } private static async Task DeliverAsync(RecDBContext db, long playerId, long enteredRoomId) { var boxes = await StorefrontShared.GetPendingGiftsAsync(db, playerId); if (!boxes.Any(box => RroRewardPools.IsQuestContext(box.Context))) return 0; var roomName = await db.Rooms .AsNoTracking() .Where(x => x.RoomId == enteredRoomId) .Select(x => x.Name) .FirstOrDefaultAsync(); var openableHere = RroRewardPools.ContextsForRoom(roomName).Values.ToList(); var stranded = boxes .Where(box => RroRewardPools.IsQuestContext(box.Context) && !openableHere.Contains(box.Context)) .ToList(); if (stranded.Count == 0) return 0; var progression = await db.Progression.FirstOrDefaultAsync(x => x.PlayerId == playerId); var json = progression?.GetProgressionJson(); var delivered = 0; foreach (var box in stranded) { var gift = box.Clone(); if (gift.GiftDropId == 0) gift.GiftDropId = StorefrontShared.NewGiftDropId(); var grant = await StorefrontShared.GrantGiftAsync(db, playerId, gift); await StorefrontShared.RemovePendingGiftAsync(db, playerId, box.GiftDropId); var source = json?.PendingGameRewards?.FirstOrDefault(r => r.ConsumedGiftDropId == box.GiftDropId || (!r.Consumed && r.GiftContext == box.Context)); if (source != null && !source.Consumed) { source.Consumed = true; source.ConsumedGiftDropId = box.GiftDropId; source.ConsumedAt = DateTime.UtcNow; } delivered++; RewardTrace.Log(playerId, $"stage=DeliveredOnLeaving activity={RroRewardPools.RoomForContext(box.Context) ?? ""} " + $"entered={roomName ?? ""} box={RewardTrace.Box(gift)} " + $"selectionId={source?.RewardSelectionId.ToString() ?? ""} " + "the quest box could no longer be opened, so the reward it already held was granted to the locker."); if (grant != null) await StorefrontShared.SendBalanceUpdateAsync(playerId, grant.CurrencyType, grant.Balance, grant.Granted, StorefrontBalanceAddTypes.FromGiftBox); await Notify.SendNotify(playerId, new Notification { Id = ManualConsumedNotificationId, Msg = gift.ForClient() }); } if (progression != null && json != null) progression.Progress = json.ToJson(); await db.SaveChangesAsync(); return delivered; } } }