mirror of
https://github.com/JogmansonReal/Radicade.git
synced 2026-10-25 23:18:56 -07:00
161 lines
6.7 KiB
C#
161 lines
6.7 KiB
C#
using Microsoft.EntityFrameworkCore;
|
|
using RadicadeServer.API.Storefront;
|
|
using RadicadeServer.DB;
|
|
using RadicadeServer.Extensions;
|
|
using RadicadeServer.RecNet.Avatar;
|
|
using RadicadeServer.RecNet.Enums.Store;
|
|
using RadicadeServer.RecNet.Progression;
|
|
using RadicadeServer.RecNet.Rooms;
|
|
using RadicadeServer.RecNet.Storefront;
|
|
using RadicadeServer.Utils;
|
|
using Xunit;
|
|
|
|
namespace RadicadeServer.Tests;
|
|
|
|
/// <summary>
|
|
/// What happens to a quest's reward box when the player walks away from it.
|
|
///
|
|
/// A quest's reward is not a choice and is not openable anywhere else - the server picked one unowned
|
|
/// item out of the run's rank pool when the reward was generated, and the box is only the delivery of
|
|
/// that item. Leaving the quest with the box still shut therefore has to deliver it, not strand it,
|
|
/// not re-roll it, and not pay tokens for it. These tests cover the delivery, and the three things
|
|
/// the delivery must not touch: a box for the quest the player is standing in, a box that is no
|
|
/// quest's, and the item's identity.
|
|
/// </summary>
|
|
public class QuestRewardDeliveryTests
|
|
{
|
|
private const long PlayerId = 4411;
|
|
|
|
private static RecDBContext NewDb() =>
|
|
new(TestDbOptions.Create()
|
|
.UseInMemoryDatabase(Guid.NewGuid().ToString())
|
|
.Options);
|
|
|
|
private static async Task<RoomData> SeedRoomAsync(RecDBContext db, string name)
|
|
{
|
|
var room = new RoomData { Name = name };
|
|
db.Rooms.Add(room);
|
|
await db.SaveChangesAsync();
|
|
return room;
|
|
}
|
|
|
|
private static Gift QuestBox(GiftContext context = GiftContext.StuntRunner_TheMainEvent_C) => new()
|
|
{
|
|
GiftDropId = 8801,
|
|
FriendlyName = "Runner Harness (Green)",
|
|
Tooltip = "Stunt Runner: The Main Event",
|
|
AvatarItemDesc = "d2d3264b-fbf6-40b5-9f10-c85ec737d112,1ba65dd5-9df9-4ff3-be96-f83a7abf67b3",
|
|
CurrencyType = CurrencyType.Invalid,
|
|
Currency = 0,
|
|
Rarity = Rarity.Uncommon,
|
|
Context = context
|
|
};
|
|
|
|
private static async Task SeedRewardAsync(RecDBContext db, Gift box, bool consumed = false)
|
|
{
|
|
var reward = new GameReward
|
|
{
|
|
RewardSelectionId = 5150,
|
|
Message = "Stunt Runner: The Main Event",
|
|
GiftContext = box.Context,
|
|
RewardType = RewardType.PostQuestActivity,
|
|
GiftDrop1 = box,
|
|
GiftDrop2 = box,
|
|
GiftDrop3 = box,
|
|
CreatedAt = DateTime.UtcNow.AddMinutes(-2),
|
|
Consumed = consumed,
|
|
ConsumedGiftDropId = consumed ? box.GiftDropId : 0
|
|
};
|
|
var json = new ProgressionJson { PendingGameRewards = new List<GameReward> { reward } };
|
|
db.Progression.Add(new ProgressionData { PlayerId = PlayerId, Progress = json.ToJson() });
|
|
await db.SaveChangesAsync();
|
|
}
|
|
|
|
/// <summary>
|
|
/// The player leaves the quest without opening the box: they get the item that was already inside
|
|
/// it, the box is taken back, and the reward is recorded as collected against that same box.
|
|
/// </summary>
|
|
[Fact]
|
|
public async Task LeavingTheQuestWithTheBoxUnopenedDeliversTheItemItAlreadyHeld()
|
|
{
|
|
await using var db = NewDb();
|
|
var recCenter = await SeedRoomAsync(db, "RecCenter");
|
|
var box = QuestBox();
|
|
await SeedRewardAsync(db, box);
|
|
await StorefrontShared.PersistGiftBoxAsync(db, PlayerId, box, notify: false);
|
|
|
|
var delivered = await QuestRewardDelivery.DeliverOnArrivalAsync(db, PlayerId, recCenter.RoomId);
|
|
|
|
Assert.Equal(1, delivered);
|
|
Assert.Empty(await StorefrontShared.GetPendingGiftsAsync(db, PlayerId));
|
|
|
|
var unlocks = await db.Unlocks.AsNoTracking().FirstOrDefaultAsync(x => x.AccountId == PlayerId);
|
|
var item = Assert.Single(unlocks!.GetAvatarItems(), x => x.AvatarItemDesc == box.AvatarItemDesc);
|
|
Assert.Equal("Runner Harness (Green)", item.FriendlyName);
|
|
|
|
var progression = await db.Progression.AsNoTracking().FirstAsync(x => x.PlayerId == PlayerId);
|
|
var saved = Assert.Single(progression.GetProgressionJson()!.PendingGameRewards);
|
|
Assert.True(saved.Consumed);
|
|
Assert.Equal(box.GiftDropId, saved.ConsumedGiftDropId);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Arriving back in the quest itself - a different instance of it, or a different rank of it -
|
|
/// leaves the box alone, because it is still openable there.
|
|
/// </summary>
|
|
[Fact]
|
|
public async Task ArrivingInTheQuest_KeepsTheBoxOpenable()
|
|
{
|
|
await using var db = NewDb();
|
|
var stuntRunner = await SeedRoomAsync(db, "StuntRunner");
|
|
var box = QuestBox();
|
|
await SeedRewardAsync(db, box);
|
|
await StorefrontShared.PersistGiftBoxAsync(db, PlayerId, box, notify: false);
|
|
|
|
var delivered = await QuestRewardDelivery.DeliverOnArrivalAsync(db, PlayerId, stuntRunner.RoomId);
|
|
|
|
Assert.Equal(0, delivered);
|
|
Assert.Single(await StorefrontShared.GetPendingGiftsAsync(db, PlayerId));
|
|
Assert.Null(await db.Unlocks.AsNoTracking().FirstOrDefaultAsync(x => x.AccountId == PlayerId));
|
|
}
|
|
|
|
/// <summary>
|
|
/// A box that is no quest's - a storefront purchase, a level-up box, a daily-challenge box - is
|
|
/// not the quest's special box and is left where it is: it can be opened anywhere.
|
|
/// </summary>
|
|
[Theory]
|
|
[InlineData(GiftContext.LevelUp)]
|
|
[InlineData(GiftContext.All_Daily_Challenges_Complete)]
|
|
[InlineData(GiftContext.Purchased_Gift_A)]
|
|
[InlineData(GiftContext.Dodgeball)]
|
|
public async Task ABoxThatIsNoQuestsIsLeftAlone(GiftContext context)
|
|
{
|
|
await using var db = NewDb();
|
|
var recCenter = await SeedRoomAsync(db, "RecCenter");
|
|
var box = QuestBox(context);
|
|
await StorefrontShared.PersistGiftBoxAsync(db, PlayerId, box, notify: false);
|
|
|
|
var delivered = await QuestRewardDelivery.DeliverOnArrivalAsync(db, PlayerId, recCenter.RoomId);
|
|
|
|
Assert.Equal(0, delivered);
|
|
Assert.Single(await StorefrontShared.GetPendingGiftsAsync(db, PlayerId));
|
|
}
|
|
|
|
/// <summary>Which contexts count as a quest's own, and which do not.</summary>
|
|
[Theory]
|
|
[InlineData(GiftContext.StuntRunner_TheMainEvent_C, true)]
|
|
[InlineData(GiftContext.StuntRunner_TheMainEvent_SS, true)]
|
|
[InlineData(GiftContext.Quest_Goblin_S, true)]
|
|
[InlineData(GiftContext.Quest_Pirate1_C, true)]
|
|
[InlineData(GiftContext.Dodgeball, false)]
|
|
[InlineData(GiftContext.Paintball_ClearCut, false)]
|
|
[InlineData(GiftContext.Lasertag, false)]
|
|
[InlineData(GiftContext.Reacquisition, false)]
|
|
[InlineData(GiftContext.LevelUp, false)]
|
|
[InlineData(GiftContext.GameRewards_Tokens, false)]
|
|
public void OnlyARankedQuestsContextIsAQuestContext(GiftContext context, bool expected)
|
|
{
|
|
Assert.Equal(expected, RroRewardPools.IsQuestContext(context));
|
|
}
|
|
}
|