From df75c4d4e6d068dbd1dbdb68dd5818619040b9f6 Mon Sep 17 00:00:00 2001 From: Tiger Date: Sat, 21 Oct 2023 07:19:21 +0200 Subject: [PATCH] Added Habbo subscriptions and subscription purchasing --- .../Catalog/GetClubOffersMessageEvent.cs | 38 ++++++++ .../Catalog/PurchaseFromCatalogEvent.cs | 43 +++++++++ .../Subscription/UserSubscriptionEvent.cs | 34 ++++++++ .../Catalog/HabboClubOffersMessageComposer.cs | 45 ++++++++++ .../NotEnoughBalanceMessageComposer.cs | 26 ++++++ .../Subscription/UserSubscriptionComposer.cs | 32 +++++++ Game/Achievements/AchievementManager.cs | 12 ++- Game/Catalogue/CatalogueManager.cs | 87 ++++++++++++++++++- Game/Catalogue/ClubOffer.cs | 12 +++ Game/Catalogue/ClubOfferMap.cs | 18 ++++ Game/Catalogue/ICatalogueManager.cs | 5 ++ Game/Habbos/Habbo.cs | 29 +++++++ Game/Habbos/HabboMap.cs | 2 +- Game/Habbos/HabboSubscription.cs | 14 +++ Game/Habbos/HabboSubscriptionMap.cs | 17 ++++ Program.cs | 1 + 16 files changed, 408 insertions(+), 7 deletions(-) create mode 100644 Communication/Messages/Incoming/Catalog/GetClubOffersMessageEvent.cs create mode 100644 Communication/Messages/Incoming/Catalog/PurchaseFromCatalogEvent.cs create mode 100644 Communication/Messages/Incoming/Inventory/Subscription/UserSubscriptionEvent.cs create mode 100644 Communication/Messages/Outgoing/Catalog/HabboClubOffersMessageComposer.cs create mode 100644 Communication/Messages/Outgoing/Catalog/NotEnoughBalanceMessageComposer.cs create mode 100644 Communication/Messages/Outgoing/Inventory/Subscription/UserSubscriptionComposer.cs create mode 100644 Game/Catalogue/ClubOffer.cs create mode 100644 Game/Catalogue/ClubOfferMap.cs create mode 100644 Game/Habbos/HabboSubscription.cs create mode 100644 Game/Habbos/HabboSubscriptionMap.cs diff --git a/Communication/Messages/Incoming/Catalog/GetClubOffersMessageEvent.cs b/Communication/Messages/Incoming/Catalog/GetClubOffersMessageEvent.cs new file mode 100644 index 0000000..dfa9c85 --- /dev/null +++ b/Communication/Messages/Incoming/Catalog/GetClubOffersMessageEvent.cs @@ -0,0 +1,38 @@ +using Tiger.Communication.Messages.Interfaces; +using Tiger.Communication.Messages.Outgoing.Catalog; +using Tiger.Communication.Messages.Types; +using Tiger.Game.Catalogue; +using Tiger.Networking.Game.Sessions; + +namespace Tiger.Communication.Messages.Incoming.Catalog; + +public class GetClubOffersMessageEvent : IMessageEvent +{ + private readonly ICatalogueManager _catalogueManager; + private readonly IGameSessionManager _gameSessionManager; + + public GetClubOffersMessageEvent(ICatalogueManager catalogueManager, IGameSessionManager gameSessionManager) + { + _catalogueManager = catalogueManager; + _gameSessionManager = gameSessionManager; + } + + public IncomingHeaders Header => IncomingHeaders.GetClubOffers; + public async Task HandleAsync(GameSession gameSession, ClientMessage request) + { + if (gameSession.Habbo == null) + { + await _gameSessionManager.CloseAsync("Not logged in", gameSession); + return; + } + + var currentSubscription = gameSession.Habbo.GetActiveSubscription(); + + await gameSession.SendComposerAsync(new HabboClubOffersMessageComposer( + _catalogueManager.ClubOffers.Values.Where(co => + co.DiscountExtension == currentSubscription is + { + MonthsLeft: 0, DaysInMonthLeft: <= 5 and > 0 + }).ToList(), currentSubscription)); + } +} \ No newline at end of file diff --git a/Communication/Messages/Incoming/Catalog/PurchaseFromCatalogEvent.cs b/Communication/Messages/Incoming/Catalog/PurchaseFromCatalogEvent.cs new file mode 100644 index 0000000..1099f57 --- /dev/null +++ b/Communication/Messages/Incoming/Catalog/PurchaseFromCatalogEvent.cs @@ -0,0 +1,43 @@ +using Tiger.Communication.Messages.Interfaces; +using Tiger.Communication.Messages.Types; +using Tiger.Game.Catalogue; +using Tiger.Networking.Game.Sessions; + +namespace Tiger.Communication.Messages.Incoming.Catalog; + +public class PurchaseFromCatalogEvent : IMessageEvent +{ + private readonly ICatalogueManager _catalogueManager; + private readonly IGameSessionManager _gameSessionManager; + + public PurchaseFromCatalogEvent(ICatalogueManager catalogueManager, IGameSessionManager gameSessionManager) + { + _catalogueManager = catalogueManager; + _gameSessionManager = gameSessionManager; + } + + public IncomingHeaders Header => IncomingHeaders.CatalogPurchase; + public async Task HandleAsync(GameSession gameSession, ClientMessage request) + { + if (gameSession.Habbo == null) + { + await _gameSessionManager.CloseAsync("Not logged in", gameSession); + return; + } + + var pageId = request.ReadInt32(); + var offerId = request.ReadInt32(); + var extraData = request.ReadString(); + var amount = request.ReadInt32(); + + if (amount < 0 || !_catalogueManager.Pages.TryGetValue(pageId, out var page)) + { + return; + } + + if (page.Layout.Equals("vip_buy")) + { + await _catalogueManager.PurchaseClubOffer(offerId, gameSession); + } + } +} \ No newline at end of file diff --git a/Communication/Messages/Incoming/Inventory/Subscription/UserSubscriptionEvent.cs b/Communication/Messages/Incoming/Inventory/Subscription/UserSubscriptionEvent.cs new file mode 100644 index 0000000..2aee46d --- /dev/null +++ b/Communication/Messages/Incoming/Inventory/Subscription/UserSubscriptionEvent.cs @@ -0,0 +1,34 @@ +using Tiger.Communication.Messages.Interfaces; +using Tiger.Communication.Messages.Outgoing.Inventory.Subscription; +using Tiger.Communication.Messages.Types; +using Tiger.Game.Achievements; +using Tiger.Networking.Game.Sessions; + +namespace Tiger.Communication.Messages.Incoming.Inventory.Subscription; + +public class UserSubscriptionEvent : IMessageEvent +{ + private readonly IGameSessionManager _gameSessionManager; + private readonly IAchievementManager _achievementManager; + + public UserSubscriptionEvent(IGameSessionManager gameSessionManager, IAchievementManager achievementManager) + { + _gameSessionManager = gameSessionManager; + _achievementManager = achievementManager; + } + + public IncomingHeaders Header => IncomingHeaders.UserSubscription; + public async Task HandleAsync(GameSession gameSession, ClientMessage request) + { + if (gameSession.Habbo == null) + { + await _gameSessionManager.CloseAsync("Not logged in", gameSession); + return; + } + + _achievementManager.UpdateAchievementAsync("ACH_HC", ((gameSession.Habbo.GetPastSubscriptionDays() / 31)), gameSession); + + await gameSession.SendComposerAsync(new UserSubscriptionComposer(gameSession.Habbo.GetActiveSubscription(), + gameSession.Habbo.GetPastSubscriptionDays())); + } +} \ No newline at end of file diff --git a/Communication/Messages/Outgoing/Catalog/HabboClubOffersMessageComposer.cs b/Communication/Messages/Outgoing/Catalog/HabboClubOffersMessageComposer.cs new file mode 100644 index 0000000..1ba3655 --- /dev/null +++ b/Communication/Messages/Outgoing/Catalog/HabboClubOffersMessageComposer.cs @@ -0,0 +1,45 @@ +using Tiger.Communication.Messages.Interfaces; +using Tiger.Communication.Messages.Types; +using Tiger.Game.Catalogue; +using Tiger.Game.Habbos; + +namespace Tiger.Communication.Messages.Outgoing.Catalog; + +public class HabboClubOffersMessageComposer : IMessageComposer +{ + private readonly ICollection _clubOffers; + private readonly HabboSubscription? _habboSubscription; + + public HabboClubOffersMessageComposer(ICollection clubOffers, HabboSubscription? habboSubscription) + { + _clubOffers = clubOffers; + _habboSubscription = habboSubscription; + } + + public OutgoingHeaders Header => OutgoingHeaders.ClubOffers; + public void Compose(ServerMessage message) + { + message.AppendInt32(_clubOffers.Count); + + foreach (var clubOffer in _clubOffers) + { + var end = _habboSubscription is not null + ? _habboSubscription.Expires.AddDays(clubOffer.Days) + : DateTime.Now.AddMonths(1); + message.AppendInt32(clubOffer.Id); + message.AppendString(clubOffer.Name); + message.AppendBoolean(false); // does absolutely NOTHING + message.AppendInt32(clubOffer.PriceCredits); + message.AppendInt32(clubOffer.PriceActivitypoints); + message.AppendInt32(clubOffer.ActivitypointsType); + message.AppendBoolean(true); // always vip + message.AppendInt32(0); // months + message.AppendInt32(clubOffer.Days); // extra days + message.AppendBoolean(true); // gift-able + message.AppendInt32(0); // days left after purchase + message.AppendInt32(end.Year); + message.AppendInt32(end.Month); + message.AppendInt32(end.Day); + } + } +} \ No newline at end of file diff --git a/Communication/Messages/Outgoing/Catalog/NotEnoughBalanceMessageComposer.cs b/Communication/Messages/Outgoing/Catalog/NotEnoughBalanceMessageComposer.cs new file mode 100644 index 0000000..7ee722e --- /dev/null +++ b/Communication/Messages/Outgoing/Catalog/NotEnoughBalanceMessageComposer.cs @@ -0,0 +1,26 @@ +using Tiger.Communication.Messages.Interfaces; +using Tiger.Communication.Messages.Types; + +namespace Tiger.Communication.Messages.Outgoing.Catalog; + +public class NotEnoughBalanceMessageComposer : IMessageComposer +{ + private readonly bool _notEnoughCredits; + private readonly bool _notEnoughActivityPoints; + private readonly int _activityPointsType; + + public NotEnoughBalanceMessageComposer(bool notEnoughCredits, bool notEnoughActivityPoints, int activityPointsType) + { + _notEnoughCredits = notEnoughCredits; + _notEnoughActivityPoints = notEnoughActivityPoints; + _activityPointsType = activityPointsType; + } + + public OutgoingHeaders Header => OutgoingHeaders.NotEnoughBalance; + public void Compose(ServerMessage message) + { + message.AppendBoolean(_notEnoughCredits); + message.AppendBoolean(_notEnoughActivityPoints); + message.AppendInt32(_activityPointsType); + } +} \ No newline at end of file diff --git a/Communication/Messages/Outgoing/Inventory/Subscription/UserSubscriptionComposer.cs b/Communication/Messages/Outgoing/Inventory/Subscription/UserSubscriptionComposer.cs new file mode 100644 index 0000000..fbcb3d3 --- /dev/null +++ b/Communication/Messages/Outgoing/Inventory/Subscription/UserSubscriptionComposer.cs @@ -0,0 +1,32 @@ +using Tiger.Communication.Messages.Interfaces; +using Tiger.Communication.Messages.Types; +using Tiger.Game.Habbos; + +namespace Tiger.Communication.Messages.Outgoing.Inventory.Subscription; + +public class UserSubscriptionComposer : IMessageComposer +{ + private readonly HabboSubscription? _habboSubscription; + private readonly int _pastSubscriptionDays; + + public UserSubscriptionComposer(HabboSubscription? habboSubscription, int pastSubscriptionDays) + { + _habboSubscription = habboSubscription; + _pastSubscriptionDays = pastSubscriptionDays; + } + + public OutgoingHeaders Header => OutgoingHeaders.UserSubscription; + public void Compose(ServerMessage message) + { + message.AppendString(_habboSubscription?.SubscriptionType ?? string.Empty); + message.AppendInt32(_habboSubscription?.DaysInMonthLeft ?? 0); + message.AppendInt32(_habboSubscription?.MonthsLeft ?? 0); + message.AppendInt32(0); // periods subscribed ahead but why is this different than above? + message.AppendInt32(0); // response type + message.AppendBoolean(_pastSubscriptionDays > 0); + message.AppendBoolean(true); // vip but always vip? + message.AppendInt32(0); // past club days but is always vip so below is used + message.AppendInt32(_pastSubscriptionDays); + message.AppendInt32((int)(_habboSubscription?.MinutesLeft ?? 0)); + } +} \ No newline at end of file diff --git a/Game/Achievements/AchievementManager.cs b/Game/Achievements/AchievementManager.cs index cb3663d..a47c73f 100644 --- a/Game/Achievements/AchievementManager.cs +++ b/Game/Achievements/AchievementManager.cs @@ -94,19 +94,23 @@ public class AchievementManager : IAchievementManager } } - await _badgesRepository.SaveAsync(badge); + _badgesRepository.SaveAsync(badge); session.Habbo.AchievementScore += achievementLevel.Points; - session.Habbo.UpdateCurrency(achievementLevel.RewardType, achievementLevel.RewardAmount); + + if (achievementLevel.RewardAmount > 0) + { + session.Habbo.UpdateCurrency(achievementLevel.RewardType, achievementLevel.RewardAmount); + session.SendComposerAsync(new ActivityPointNotificationMessageComposer(session.Habbo.Activitypoints[achievementLevel.RewardType].Amount, achievementLevel.RewardAmount, achievementLevel.RewardType)); + } // session.CurrentRoom?.SendMessage(new UserChangeMessageComposer(session.RoomUser.VirtualId, session.User)); session.SendComposerAsync(new AchievementsScoreComposer(session.Habbo.AchievementScore)); - session.SendComposerAsync(new ActivityPointNotificationMessageComposer(session.Habbo.Activitypoints[achievementLevel.RewardType].Amount, achievementLevel.RewardAmount, achievementLevel.RewardType)); session.SendComposerAsync(new AchievementNotificationMessageComposer(habboAchievement, badge.Id)); } - await _habboRepository.SaveAsync(session.Habbo); + _habboRepository.SaveAsync(session.Habbo); await session.SendComposerAsync(new AchievementComposer(achievement, habboAchievement)); } diff --git a/Game/Catalogue/CatalogueManager.cs b/Game/Catalogue/CatalogueManager.cs index 44c84ae..c6cffa4 100644 --- a/Game/Catalogue/CatalogueManager.cs +++ b/Game/Catalogue/CatalogueManager.cs @@ -1,4 +1,11 @@ using Microsoft.Extensions.Logging; +using Tiger.Communication.Messages.Outgoing.Catalog; +using Tiger.Communication.Messages.Outgoing.Inventory.Currency; +using Tiger.Communication.Messages.Outgoing.Inventory.Subscription; +using Tiger.Communication.Messages.Outgoing.Notifications; +using Tiger.Game.Achievements; +using Tiger.Game.Habbos; +using Tiger.Networking.Game.Sessions; using Tiger.Storage; namespace Tiger.Game.Catalogue; @@ -8,18 +15,27 @@ public class CatalogueManager : ICatalogueManager private readonly IRepository _pagesRepository; private readonly ILogger _logger; private readonly IRepository _featuredPagesRepository; + private readonly IRepository _clubOfferRepository; + private readonly IRepository _habboSubscriptionRepository; + private readonly IAchievementManager _achievementManager; public IDictionary Pages { get; private set; } public IDictionary FeaturedPages { get; private set; } + public IDictionary ClubOffers { get; private set; } public CatalogueManager(IRepository pagesRepository, ILogger logger, - IRepository featuredPagesRepository) + IRepository featuredPagesRepository, IRepository clubOfferRepository, + IRepository habboSubscriptionRepository, IAchievementManager achievementManager) { _pagesRepository = pagesRepository; _logger = logger; _featuredPagesRepository = featuredPagesRepository; + _clubOfferRepository = clubOfferRepository; + _habboSubscriptionRepository = habboSubscriptionRepository; + _achievementManager = achievementManager; Pages = new Dictionary(); FeaturedPages = new Dictionary(); + ClubOffers = new Dictionary(); } public async Task LoadPagesAsync() @@ -31,9 +47,76 @@ public class CatalogueManager : ICatalogueManager public async Task LoadFeaturedPagesAsync() { - FeaturedPages =(await _featuredPagesRepository.FindByAsync()) + FeaturedPages = (await _featuredPagesRepository.FindByAsync()) .ToDictionary(p => p.SlotId, p => p); _logger.LogInformation("Loaded {Count} catalogue featured pages", FeaturedPages.Count); } + + public async Task LoadClubOffersAsync() + { + ClubOffers = (await _clubOfferRepository.FindByAsync()) + .ToDictionary(co => co.Id); + + _logger.LogInformation("Loaded {Count} club offers", ClubOffers.Count); + } + + public async Task PurchaseClubOffer(int offerId, GameSession gameSession) + { + if (!ClubOffers.TryGetValue(offerId, out var clubOffer) || gameSession.Habbo == null) + { + return; + } + + var tooShortOnCoins = clubOffer.PriceCredits > 0 && clubOffer.PriceCredits > gameSession.Habbo.Credits; + var tooShortOnActivityPoints = clubOffer.PriceActivitypoints > 0 && clubOffer.PriceActivitypoints > + gameSession.Habbo.GetActivityPoints(clubOffer.ActivitypointsType); + + if (tooShortOnCoins || tooShortOnActivityPoints) + { + await gameSession.SendComposerAsync(new NotEnoughBalanceMessageComposer(tooShortOnCoins, + tooShortOnActivityPoints, clubOffer.ActivitypointsType)); + return; + } + + if (clubOffer.PriceCredits > 0) + { + gameSession.Habbo.Credits -= clubOffer.PriceCredits; + gameSession.SendComposerAsync(new UserCreditsComposer(gameSession.Habbo.Credits)); + } + + if (clubOffer.PriceActivitypoints > 0) + { + gameSession.Habbo.UpdateCurrency(clubOffer.ActivitypointsType, -clubOffer.PriceActivitypoints); + gameSession.SendComposerAsync(new ActivityPointNotificationMessageComposer( + gameSession.Habbo.GetActivityPoints(clubOffer.ActivitypointsType), -clubOffer.PriceActivitypoints, + clubOffer.ActivitypointsType)); + } + + var currentSubscription = gameSession.Habbo.GetActiveSubscription(); + + if (currentSubscription != null) + { + currentSubscription.Expires = currentSubscription.Expires.AddDays(clubOffer.Days); + currentSubscription.Habbo.Credits -= clubOffer.PriceCredits; + currentSubscription.Habbo.UpdateCurrency(clubOffer.ActivitypointsType, -clubOffer.PriceActivitypoints); + _habboSubscriptionRepository.SaveAsync(currentSubscription); + gameSession.SendComposerAsync(new UserSubscriptionComposer(currentSubscription, + gameSession.Habbo.GetPastSubscriptionDays())); + } + else + { + var subscription = new HabboSubscription + { + Expires = DateTime.Now.AddDays(clubOffer.Days), + SubscriptionType = "habbo_club", + Started = DateTime.Now, + Habbo = gameSession.Habbo + }; + _habboSubscriptionRepository.SaveAsync(subscription); + gameSession.SendComposerAsync(new UserSubscriptionComposer(subscription, + gameSession.Habbo.GetPastSubscriptionDays())); + _achievementManager.UpdateAchievementAsync("ACH_HC", 1, gameSession); + } + } } \ No newline at end of file diff --git a/Game/Catalogue/ClubOffer.cs b/Game/Catalogue/ClubOffer.cs new file mode 100644 index 0000000..a039fb3 --- /dev/null +++ b/Game/Catalogue/ClubOffer.cs @@ -0,0 +1,12 @@ +namespace Tiger.Game.Catalogue; + +public class ClubOffer +{ + public virtual int Id { get; set; } + public virtual string Name { get; set; } = null!; + public virtual int PriceCredits { get; set; } + public virtual int PriceActivitypoints { get; set; } + public virtual int ActivitypointsType { get; set; } + public virtual int Days { get; set; } + public virtual bool DiscountExtension { get; set; } +} \ No newline at end of file diff --git a/Game/Catalogue/ClubOfferMap.cs b/Game/Catalogue/ClubOfferMap.cs new file mode 100644 index 0000000..e87bfa9 --- /dev/null +++ b/Game/Catalogue/ClubOfferMap.cs @@ -0,0 +1,18 @@ +using FluentNHibernate.Mapping; + +namespace Tiger.Game.Catalogue; + +public class ClubOfferMap : ClassMap +{ + public ClubOfferMap() + { + Table("catalogue_club_offers"); + Id(co => co.Id).Column("id").GeneratedBy.Identity(); + Map(co => co.Name).Column("name").Not.Nullable(); + Map(co => co.PriceCredits).Column("price_credits").Not.Nullable(); + Map(co => co.PriceActivitypoints).Column("price_activitypoints").Not.Nullable(); + Map(co => co.ActivitypointsType).Column("activitypoints_type").Not.Nullable(); + Map(co => co.Days).Column("days").Not.Nullable(); + Map(co => co.DiscountExtension).Column("discount_extension").Not.Nullable(); + } +} \ No newline at end of file diff --git a/Game/Catalogue/ICatalogueManager.cs b/Game/Catalogue/ICatalogueManager.cs index b9e1987..c4aa6aa 100644 --- a/Game/Catalogue/ICatalogueManager.cs +++ b/Game/Catalogue/ICatalogueManager.cs @@ -1,9 +1,14 @@ +using Tiger.Networking.Game.Sessions; + namespace Tiger.Game.Catalogue; public interface ICatalogueManager { public IDictionary Pages { get; } public IDictionary FeaturedPages { get; } + public IDictionary ClubOffers { get; } Task LoadPagesAsync(); Task LoadFeaturedPagesAsync(); + Task LoadClubOffersAsync(); + Task PurchaseClubOffer(int offerId, GameSession gameSession); } \ No newline at end of file diff --git a/Game/Habbos/Habbo.cs b/Game/Habbos/Habbo.cs index d101605..19491bf 100644 --- a/Game/Habbos/Habbo.cs +++ b/Game/Habbos/Habbo.cs @@ -21,7 +21,12 @@ public class Habbo public virtual ICollection Badges { get; set; } = new List(); public virtual IDictionary Achievements { get; set; } = new Dictionary(); + public virtual ICollection Subscriptions { get; set; } = new List(); + public virtual int GetActivityPoints(int type) + { + return Activitypoints.TryGetValue(type, out var activityPoints) ? activityPoints.Amount : 0; + } public virtual void UpdateCurrency(int type, int amount) { if (!Activitypoints.ContainsKey(type)) @@ -37,4 +42,28 @@ public class Habbo Activitypoints[type].Amount += amount; } + + public virtual HabboSubscription? GetActiveSubscription() + { + return Subscriptions.Where(s => s.Expires > DateTime.Now).MaxBy(s => s.Expires); + } + + public virtual int GetPastSubscriptionDays() + { + int totalDays = 0; + + foreach (var subscription in Subscriptions) + { + if(subscription.Expires < DateTime.Now) // If subscription has ended + { + totalDays += (subscription.Expires - subscription.Started).Days; + } + else if(subscription.Started < DateTime.Now) // If subscription is ongoing + { + totalDays += (DateTime.Now - subscription.Started).Days; + } + } + + return totalDays; + } } \ No newline at end of file diff --git a/Game/Habbos/HabboMap.cs b/Game/Habbos/HabboMap.cs index 113575f..3137509 100644 --- a/Game/Habbos/HabboMap.cs +++ b/Game/Habbos/HabboMap.cs @@ -30,11 +30,11 @@ public class HabboMap : ClassMap .KeyColumn("habbo_id") .Component(comp => { - // comp.References(x => x.Achievement, "achievement_id"); comp.Map(x => x.Level); comp.Map(x => x.Progress); }) .AsMap("achievement_id") .Cascade.All(); + HasMany(h => h.Subscriptions).Cascade.All().Inverse(); } } \ No newline at end of file diff --git a/Game/Habbos/HabboSubscription.cs b/Game/Habbos/HabboSubscription.cs new file mode 100644 index 0000000..098c70c --- /dev/null +++ b/Game/Habbos/HabboSubscription.cs @@ -0,0 +1,14 @@ +namespace Tiger.Game.Habbos; + +public class HabboSubscription +{ + public virtual int Id { get; set; } + public virtual Habbo Habbo { get; set; } = null!; + public virtual string SubscriptionType { get; set; }= null!; + public virtual DateTime Started { get; set; } + public virtual DateTime Expires { get; set; } + + public virtual int DaysInMonthLeft => (int)(Expires - DateTime.Now).TotalDays % 31; + public virtual int MonthsLeft => (int)(Expires - DateTime.Now).TotalDays / 31; + public virtual double MinutesLeft => (Expires - DateTime.Now).TotalMinutes; +} \ No newline at end of file diff --git a/Game/Habbos/HabboSubscriptionMap.cs b/Game/Habbos/HabboSubscriptionMap.cs new file mode 100644 index 0000000..9e9d5db --- /dev/null +++ b/Game/Habbos/HabboSubscriptionMap.cs @@ -0,0 +1,17 @@ +using FluentNHibernate.Mapping; + +namespace Tiger.Game.Habbos; + +public class HabboSubscriptionMap : ClassMap +{ + public HabboSubscriptionMap() + { + Table("habbo_subscriptions"); + LazyLoad(); + Id(hs => hs.Id).Column("id").GeneratedBy.Identity(); + Map(hs => hs.SubscriptionType).Column("subscription_type").Not.Nullable(); + Map(hs => hs.Started).Column("started").Not.Nullable(); + Map(hs => hs.Expires).Column("expires").Not.Nullable(); + References(x => x.Habbo).Column("habbo_id").Not.Nullable(); + } +} \ No newline at end of file diff --git a/Program.cs b/Program.cs index da21388..b26960b 100644 --- a/Program.cs +++ b/Program.cs @@ -55,6 +55,7 @@ var provider = collection.BuildServiceProvider(); await provider.GetRequiredService().ReloadSettingsAsync(); await provider.GetRequiredService().LoadPagesAsync(); await provider.GetRequiredService().LoadFeaturedPagesAsync(); +await provider.GetRequiredService().LoadClubOffersAsync(); provider.GetRequiredService(); await provider.GetRequiredService().LoadPromoArticlesAsync(); await provider.GetRequiredService().LoadAchievementsAsync();