mirror of
https://github.com/JogmansonReal/Radicade.git
synced 2026-10-26 07:29:00 -07:00
204 lines
7.3 KiB
C#
204 lines
7.3 KiB
C#
using Microsoft.EntityFrameworkCore;
|
|
using RadicadeServer.API.Notifications;
|
|
using RadicadeServer.API.Storefront;
|
|
using RadicadeServer.DB;
|
|
using RadicadeServer.Extensions;
|
|
using RadicadeServer.RecNet.Enums.Messages;
|
|
using RadicadeServer.RecNet.Enums.Store;
|
|
using RadicadeServer.RecNet.Notifications;
|
|
using RadicadeServer.RecNet.Progression;
|
|
|
|
namespace RadicadeServer.Utils
|
|
{
|
|
public static class RoomProgressionService
|
|
{
|
|
public const int XpPerInterval = 10;
|
|
|
|
public static readonly TimeSpan Interval = TimeSpan.FromMinutes(5);
|
|
|
|
public const int RoomXpCap = 60;
|
|
|
|
public const int DailyXpCap = 150;
|
|
|
|
public static readonly TimeSpan DailyCapCooldown = TimeSpan.FromHours(24);
|
|
|
|
public const string ProgressionLevelUpdateNotificationId = "PlayerProgressionLevelUpdate";
|
|
|
|
public static async Task<int> AwardRoomXpAsync(RecDBContext db, long playerId, long roomId, bool isPublicRoom)
|
|
{
|
|
if (playerId <= 0 || roomId <= 0 || !isPublicRoom) return 0;
|
|
|
|
var progression = await db.Progression.FirstOrDefaultAsync(x => x.PlayerId == playerId);
|
|
if (progression == null)
|
|
{
|
|
progression = new ProgressionData { PlayerId = playerId };
|
|
await db.Progression.AddAsync(progression);
|
|
}
|
|
|
|
var json = progression.GetProgressionJson() ?? new ProgressionJson();
|
|
var now = DateTime.UtcNow;
|
|
|
|
if (json.XpEarnedTodayDate != now.Date)
|
|
{
|
|
json.XpEarnedToday = 0;
|
|
json.XpEarnedTodayDate = now.Date;
|
|
json.XpDailyCapReachedAt = null;
|
|
}
|
|
|
|
if (json.XpEarnedToday >= DailyXpCap)
|
|
{
|
|
if (json.XpDailyCapReachedAt is { } reachedAt && now >= reachedAt.Add(DailyCapCooldown))
|
|
{
|
|
json.XpEarnedToday = 0;
|
|
json.XpEarnedTodayDate = now.Date;
|
|
json.XpDailyCapReachedAt = null;
|
|
}
|
|
else
|
|
{
|
|
json.XpDailyCapReachedAt ??= now;
|
|
progression.Progress = json.ToJson();
|
|
await db.SaveChangesAsync();
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
if (json.RoomXpRoomId != roomId)
|
|
{
|
|
json.RoomXpRoomId = roomId;
|
|
json.RoomXpEarned = 0;
|
|
json.RoomXpLastGrantAt = now;
|
|
progression.Progress = json.ToJson();
|
|
await db.SaveChangesAsync();
|
|
return 0;
|
|
}
|
|
|
|
if (json.RoomXpEarned >= RoomXpCap)
|
|
{
|
|
progression.Progress = json.ToJson();
|
|
await db.SaveChangesAsync();
|
|
return 0;
|
|
}
|
|
|
|
json.RoomXpLastGrantAt ??= now;
|
|
|
|
int granted = 0;
|
|
while (now - json.RoomXpLastGrantAt.Value >= Interval)
|
|
{
|
|
int roomHeadroom = RoomXpCap - (json.RoomXpEarned + granted);
|
|
int dailyHeadroom = DailyXpCap - (json.XpEarnedToday + granted);
|
|
int instalment = Math.Min(XpPerInterval, Math.Min(roomHeadroom, dailyHeadroom));
|
|
if (instalment <= 0) break;
|
|
|
|
granted += instalment;
|
|
json.RoomXpLastGrantAt = json.RoomXpLastGrantAt.Value.Add(Interval);
|
|
}
|
|
|
|
if (granted == 0 && now - json.RoomXpLastGrantAt.Value >= Interval)
|
|
json.RoomXpLastGrantAt = now;
|
|
|
|
if (granted == 0)
|
|
{
|
|
progression.Progress = json.ToJson();
|
|
await db.SaveChangesAsync();
|
|
return 0;
|
|
}
|
|
|
|
int applied = (int)Math.Min(granted, int.MaxValue);
|
|
|
|
json.RoomXpEarned += applied;
|
|
json.XpEarnedToday += applied;
|
|
json.XpEarnedTodayDate = now.Date;
|
|
json.LastXpEarnedAt = now;
|
|
if (json.XpEarnedToday >= DailyXpCap)
|
|
json.XpDailyCapReachedAt ??= now;
|
|
|
|
int oldLevel = progression.Level;
|
|
progression.XP = (int)Math.Min(progression.XP + applied, int.MaxValue);
|
|
progression.Progress = json.ToJson();
|
|
await db.SaveChangesAsync();
|
|
|
|
await StorefrontShared.SendXpBalanceUpdateAsync(playerId,
|
|
LevelUpGiftService.XpIntoCurrentLevel(progression), applied,
|
|
StorefrontBalanceAddTypes.DirectBalanceWithMultiplier);
|
|
|
|
int computedLevel = LevelUpGiftService.ComputeLevel(LevelUpGiftService.ParseMap(), progression.XP);
|
|
if (computedLevel > progression.Level) progression.Level = computedLevel;
|
|
|
|
await LevelUpGiftService.DeliverLevelUpGiftsAsync(db, playerId,
|
|
recomputeFromXp: true, fromLevel: oldLevel, notify: true);
|
|
|
|
await SendProgressionLevelUpdateAsync(db, playerId, progression);
|
|
|
|
if (progression.Level > oldLevel)
|
|
{
|
|
await PushProgressionUpdateAsync(db, playerId);
|
|
}
|
|
|
|
return applied;
|
|
}
|
|
|
|
public static async Task SendProgressionLevelUpdateAsync(RecDBContext db, long playerId,
|
|
ProgressionData? progression = null)
|
|
{
|
|
if (playerId <= 0) return;
|
|
|
|
try
|
|
{
|
|
progression ??= await db.Progression.AsNoTracking()
|
|
.FirstOrDefaultAsync(x => x.PlayerId == playerId);
|
|
if (progression == null) return;
|
|
|
|
var notification = new Notification
|
|
{
|
|
Id = ProgressionLevelUpdateNotificationId,
|
|
Msg = new PlayerProgressionLevelUpdateNotification(progression)
|
|
};
|
|
|
|
await Notify.SendNotify(playerId, notification);
|
|
|
|
await Notify.SendToSubscribers(playerId, notification);
|
|
}
|
|
catch (Exception)
|
|
{
|
|
}
|
|
}
|
|
|
|
public static async Task PushProgressionUpdateAsync(RecDBContext db, long playerId)
|
|
{
|
|
await SendProgressionLevelUpdateAsync(db, playerId);
|
|
|
|
try
|
|
{
|
|
var profile = await db.Profiles.AsNoTracking().FirstOrDefaultAsync(x => x.accountId == playerId);
|
|
if (profile == null) return;
|
|
|
|
var plrData = await db.Players.AsNoTracking().FirstOrDefaultAsync(x => x.AccountId == playerId);
|
|
|
|
var progression = await db.Progression.AsNoTracking().FirstOrDefaultAsync(x => x.PlayerId == playerId);
|
|
if (progression != null)
|
|
await StorefrontShared.SendXpBalanceUpdateAsync(playerId,
|
|
LevelUpGiftService.XpIntoCurrentLevel(progression), 0,
|
|
StorefrontBalanceAddTypes.LevelUp);
|
|
|
|
await Notify.SendNotify(playerId, new Notification
|
|
{
|
|
Id = "AccountUpdate",
|
|
Msg = profile
|
|
});
|
|
|
|
await Notify.UpdateSubscriptions(playerId, Notifs.SubscriptionUpdateProfile, profile);
|
|
|
|
if (plrData != null)
|
|
await Notify.SendNotify(playerId, new Notification
|
|
{
|
|
Id = "SelfAccountUpdate",
|
|
Msg = PlayerUtils.BuildSelfAccount(profile, plrData)
|
|
});
|
|
}
|
|
catch (Exception)
|
|
{
|
|
}
|
|
}
|
|
}
|
|
}
|