diff --git a/Communication/Messages/Incoming/Handshake/SsoTicketEvent.cs b/Communication/Messages/Incoming/Handshake/SsoTicketEvent.cs index 336b3cb..2e809b0 100644 --- a/Communication/Messages/Incoming/Handshake/SsoTicketEvent.cs +++ b/Communication/Messages/Incoming/Handshake/SsoTicketEvent.cs @@ -3,6 +3,7 @@ using Tiger.Communication.Messages.Interfaces; using Tiger.Communication.Messages.Outgoing.Generic.Alerts; using Tiger.Communication.Messages.Outgoing.Handshake; using Tiger.Communication.Messages.Types; +using Tiger.Game.Achievements; using Tiger.Game.Habbos; using Tiger.Game.Settings; using Tiger.Networking.Game.Sessions; @@ -16,13 +17,15 @@ public class SsoTicketEvent : IMessageEvent private readonly IGameSessionManager _gameSessionManager; private readonly ISettingManager _settingManager; private readonly ILogger _logger; + private readonly IAchievementManager _achievementManager; - public SsoTicketEvent(IRepository habboRepository, IGameSessionManager gameSessionManager, ISettingManager settingManager, ILogger logger) + public SsoTicketEvent(IRepository habboRepository, IGameSessionManager gameSessionManager, ISettingManager settingManager, ILogger logger, IAchievementManager achievementManager) { _habboRepository = habboRepository; _gameSessionManager = gameSessionManager; _settingManager = settingManager; _logger = logger; + _achievementManager = achievementManager; } public IncomingHeaders Header => IncomingHeaders.SSoTicketEvent; @@ -49,7 +52,12 @@ public class SsoTicketEvent : IMessageEvent gameSession.Habbo.LastLogin = DateTime.Now; gameSession.Habbo.Online = true; _habboRepository.SaveAsync(gameSession.Habbo); - + + if (DateTime.Now.Hour == 15) + { + _achievementManager.UpdateAchievementAsync("ACH_HappyHour", 1, gameSession); + } + _logger.LogInformation("{User} logged in", gameSession.Habbo.Username); await gameSession.SendComposerAsync(new AuthenticationOkMessageComposer()); diff --git a/Communication/Messages/Incoming/Inventory/Achievements/GetAchievementsEvent.cs b/Communication/Messages/Incoming/Inventory/Achievements/GetAchievementsEvent.cs new file mode 100644 index 0000000..667a451 --- /dev/null +++ b/Communication/Messages/Incoming/Inventory/Achievements/GetAchievementsEvent.cs @@ -0,0 +1,33 @@ +using Tiger.Communication.Messages.Interfaces; +using Tiger.Communication.Messages.Outgoing.Inventory.Achievements; +using Tiger.Communication.Messages.Types; +using Tiger.Game.Achievements; +using Tiger.Networking.Game.Sessions; + +namespace Tiger.Communication.Messages.Incoming.Inventory.Achievements; + +public class GetAchievementsEvent : IMessageEvent +{ + private readonly IGameSessionManager _gameSessionManager; + private readonly IAchievementManager _achievementManager; + + public GetAchievementsEvent(IGameSessionManager gameSessionManager, IAchievementManager achievementManager) + { + _gameSessionManager = gameSessionManager; + _achievementManager = achievementManager; + } + + public IncomingHeaders Header => IncomingHeaders.GetAchievementsEvent; + public async Task HandleAsync(GameSession gameSession, ClientMessage request) + { + if (gameSession.Habbo == null) + { + await _gameSessionManager.CloseAsync("Not logged in", gameSession); + return; + } + + await gameSession.SendComposerAsync(new AchievementsScoreComposer(gameSession.Habbo.AchievementScore)); + await gameSession.SendComposerAsync(new AchievementsComposer(_achievementManager.Achievements.Values, + gameSession.Habbo)); + } +} \ No newline at end of file diff --git a/Communication/Messages/Incoming/Inventory/Badges/SetActivatedBadgesEvent.cs b/Communication/Messages/Incoming/Inventory/Badges/SetActivatedBadgesEvent.cs index a790e7b..e018c9e 100644 --- a/Communication/Messages/Incoming/Inventory/Badges/SetActivatedBadgesEvent.cs +++ b/Communication/Messages/Incoming/Inventory/Badges/SetActivatedBadgesEvent.cs @@ -27,15 +27,14 @@ public class SetActivatedBadgesEvent : IMessageEvent await _gameSessionManager.CloseAsync("Not logged in", gameSession); return; } - - if (gameSession.Habbo.Badges == null) - return; var wearingBadges = new Collection(); + var badgesToUpdate = new Dictionary(); var current = gameSession.Habbo.Badges.Where(b => b.Slot != 0); foreach (var currentBadge in current) { currentBadge.Slot = 0; + badgesToUpdate.Add(currentBadge.Id, currentBadge); } for (var i = 0; i < 5; i++) @@ -51,10 +50,11 @@ public class SetActivatedBadgesEvent : IMessageEvent badge.Slot = slotId.Value; wearingBadges.Add(badge); - - _badgeRepository.SaveAsync(badge); + + badgesToUpdate.TryAdd(badge.Id, badge); } + await _badgeRepository.SaveManyAsync(badgesToUpdate.Values); await gameSession.SendComposerAsync(new HabboUserBadgesMessageComposer(gameSession.Habbo.Id, wearingBadges)); } } \ No newline at end of file diff --git a/Communication/Messages/Incoming/Inventory/Purse/GetCreditsInfoEvent.cs b/Communication/Messages/Incoming/Inventory/Purse/GetCreditsInfoEvent.cs index 0e47365..172feb9 100644 --- a/Communication/Messages/Incoming/Inventory/Purse/GetCreditsInfoEvent.cs +++ b/Communication/Messages/Incoming/Inventory/Purse/GetCreditsInfoEvent.cs @@ -25,6 +25,6 @@ public class GetCreditsInfoEvent : IMessageEvent } await gameSession.SendComposerAsync(new CreditBalanceComposer(gameSession.Habbo.Credits)); - await gameSession.SendComposerAsync(new ActivityPointsComposer(gameSession.Habbo.Activitypoints ?? null)); + await gameSession.SendComposerAsync(new ActivityPointsComposer(gameSession.Habbo.Activitypoints.Values)); } } \ No newline at end of file diff --git a/Communication/Messages/Incoming/Register/UpdateFigureDataMessageEvent.cs b/Communication/Messages/Incoming/Register/UpdateFigureDataMessageEvent.cs index 28dabb5..3a75b7b 100644 --- a/Communication/Messages/Incoming/Register/UpdateFigureDataMessageEvent.cs +++ b/Communication/Messages/Incoming/Register/UpdateFigureDataMessageEvent.cs @@ -1,6 +1,7 @@ using Tiger.Communication.Messages.Interfaces; using Tiger.Communication.Messages.Outgoing.Avatar; using Tiger.Communication.Messages.Types; +using Tiger.Game.Achievements; using Tiger.Game.Figuredata; using Tiger.Game.Habbos; using Tiger.Networking.Game.Sessions; @@ -13,12 +14,14 @@ public class UpdateFigureDataMessageEvent : IMessageEvent private readonly IGameSessionManager _gameSessionManager; private readonly IFigureDataManager _figureDataManager; private readonly IRepository _habboRepository; + private readonly IAchievementManager _achievementManager; - public UpdateFigureDataMessageEvent(IGameSessionManager gameSessionManager, IFigureDataManager figureDataManager, IRepository habboRepository) + public UpdateFigureDataMessageEvent(IGameSessionManager gameSessionManager, IFigureDataManager figureDataManager, IRepository habboRepository, IAchievementManager achievementManager) { _gameSessionManager = gameSessionManager; _figureDataManager = figureDataManager; _habboRepository = habboRepository; + _achievementManager = achievementManager; } public IncomingHeaders Header => IncomingHeaders.UpdateFigureDataEvent; @@ -33,7 +36,7 @@ public class UpdateFigureDataMessageEvent : IMessageEvent var gender = request.ReadString()?.ToUpper(); var figure = request.ReadString(); - if (gender is null || figure is null || (gender != "M" && gender != "F") /*|| + if (figure is null || (gender != "M" && gender != "F") || (figure == gameSession.Habbo.Figure && gender == gameSession.Habbo.Gender.ToUpper()) /*|| !_figureDataManager.ValidateFigure(figure, gender, gameSession.Habbo)*/) { return; @@ -43,6 +46,8 @@ public class UpdateFigureDataMessageEvent : IMessageEvent gameSession.Habbo.Gender = gender; _habboRepository.SaveAsync(gameSession.Habbo); + _achievementManager.UpdateAchievementAsync("ACH_AvatarLooks", 1, gameSession); + await gameSession.SendComposerAsync(new FigureUpdateComposer(figure, gender)); } } \ No newline at end of file diff --git a/Communication/Messages/Outgoing/Inventory/Achievements/AchievementComposer.cs b/Communication/Messages/Outgoing/Inventory/Achievements/AchievementComposer.cs new file mode 100644 index 0000000..005556d --- /dev/null +++ b/Communication/Messages/Outgoing/Inventory/Achievements/AchievementComposer.cs @@ -0,0 +1,40 @@ +using Tiger.Communication.Messages.Interfaces; +using Tiger.Communication.Messages.Types; +using Tiger.Game.Achievements; +using Tiger.Game.Habbos; + +namespace Tiger.Communication.Messages.Outgoing.Inventory.Achievements; + +public class AchievementComposer : IMessageComposer +{ + private readonly Achievement _achievement; + private readonly HabboAchievement _habboAchievement; + + public AchievementComposer(Achievement achievement, HabboAchievement habboAchievement) + { + _achievement = achievement; + _habboAchievement = habboAchievement; + } + + public OutgoingHeaders Header => OutgoingHeaders.AchievementComposer; + public void Compose(ServerMessage message) + { + var targetLevel = _habboAchievement.Level == _achievement.Levels.Count + ? _habboAchievement.Level + : _habboAchievement.Level + 1; + + message.AppendInt32(_achievement.Id); + message.AppendInt32(targetLevel); + message.AppendString($"{_achievement.Badge}{targetLevel}"); + message.AppendInt32(_habboAchievement.Progress); + message.AppendInt32(_achievement.Levels[targetLevel].ProgressNeeded); + message.AppendInt32(_achievement.Levels[targetLevel].RewardAmount); + message.AppendInt32(_achievement.Levels[targetLevel].RewardType); + message.AppendInt32(_habboAchievement.Progress); + message.AppendBoolean(_habboAchievement.Level >= _achievement.Levels.Count); + message.AppendString(_achievement.Category); + message.AppendString(string.Empty); + message.AppendInt32(_achievement.Levels.Count); + message.AppendInt32(_habboAchievement.Level >= _achievement.Levels.Count ? 1 : 0); + } +} \ No newline at end of file diff --git a/Communication/Messages/Outgoing/Inventory/Achievements/AchievementsComposer.cs b/Communication/Messages/Outgoing/Inventory/Achievements/AchievementsComposer.cs new file mode 100644 index 0000000..b7764ef --- /dev/null +++ b/Communication/Messages/Outgoing/Inventory/Achievements/AchievementsComposer.cs @@ -0,0 +1,50 @@ +using Tiger.Communication.Messages.Interfaces; +using Tiger.Communication.Messages.Types; +using Tiger.Game.Achievements; +using Tiger.Game.Habbos; + +namespace Tiger.Communication.Messages.Outgoing.Inventory.Achievements; + +public class AchievementsComposer : IMessageComposer +{ + private readonly ICollection _achievements; + private readonly Habbo _habbo; + + public AchievementsComposer(ICollection achievements, Habbo habbo) + { + _achievements = achievements; + _habbo = habbo; + } + + public OutgoingHeaders Header => OutgoingHeaders.AchievementsComposer; + public void Compose(ServerMessage message) + { + message.AppendInt32(_achievements.Count); + + foreach (var achievement in _achievements) + { + var targetLevel = 1; + + if (_habbo.Achievements.TryGetValue(achievement.Id, out var habboAchievement)) + targetLevel = habboAchievement.Level == achievement.Levels.Count + ? habboAchievement.Level + : habboAchievement.Level + 1; + + message.AppendInt32(achievement.Id); + message.AppendInt32(targetLevel); + message.AppendString($"{achievement.Badge}{targetLevel}"); + message.AppendInt32(habboAchievement?.Progress ?? 0); + message.AppendInt32(achievement.Levels[targetLevel].ProgressNeeded); + message.AppendInt32(achievement.Levels[targetLevel].RewardAmount); + message.AppendInt32(achievement.Levels[targetLevel].RewardType); + message.AppendInt32(habboAchievement?.Progress ?? 0); + message.AppendBoolean((habboAchievement?.Level ?? 0) >= achievement.Levels.Count); + message.AppendString(achievement.Category); + message.AppendString(string.Empty); + message.AppendInt32(achievement.Levels.Count); + message.AppendInt32((habboAchievement?.Level ?? 0) >= achievement.Levels.Count ? 1 : 0); + } + + message.AppendString(string.Empty); + } +} \ No newline at end of file diff --git a/Communication/Messages/Outgoing/Inventory/Achievements/AchievementsScoreComposer.cs b/Communication/Messages/Outgoing/Inventory/Achievements/AchievementsScoreComposer.cs new file mode 100644 index 0000000..4c7d45d --- /dev/null +++ b/Communication/Messages/Outgoing/Inventory/Achievements/AchievementsScoreComposer.cs @@ -0,0 +1,20 @@ +using Tiger.Communication.Messages.Interfaces; +using Tiger.Communication.Messages.Types; + +namespace Tiger.Communication.Messages.Outgoing.Inventory.Achievements; + +public class AchievementsScoreComposer : IMessageComposer +{ + private readonly int _score; + + public AchievementsScoreComposer(int score) + { + _score = score; + } + + public OutgoingHeaders Header => OutgoingHeaders.AchievementsScoreComposer; + public void Compose(ServerMessage message) + { + message.AppendInt32(_score); + } +} \ No newline at end of file diff --git a/Communication/Messages/Outgoing/Notifications/AchievementNotificationMessageComposer.cs b/Communication/Messages/Outgoing/Notifications/AchievementNotificationMessageComposer.cs new file mode 100644 index 0000000..ad38cfc --- /dev/null +++ b/Communication/Messages/Outgoing/Notifications/AchievementNotificationMessageComposer.cs @@ -0,0 +1,34 @@ +using Tiger.Communication.Messages.Interfaces; +using Tiger.Communication.Messages.Types; +using Tiger.Game.Habbos; + +namespace Tiger.Communication.Messages.Outgoing.Notifications; + +public class AchievementNotificationMessageComposer : IMessageComposer +{ + private readonly HabboAchievement _habboAchievement; + private readonly int _badgeId; + + public AchievementNotificationMessageComposer(HabboAchievement habboAchievement, int badgeId) + { + _habboAchievement = habboAchievement; + _badgeId = badgeId; + } + + public OutgoingHeaders Header => OutgoingHeaders.AchievementNotificationMessageComposer; + public void Compose(ServerMessage message) + { + message.AppendInt32(_habboAchievement.Achievement.Id); + message.AppendInt32(_habboAchievement.Level); + message.AppendInt32(_badgeId); + message.AppendString($"{_habboAchievement.Achievement.Badge}{_habboAchievement.Level}"); + message.AppendInt32(0); // points? + message.AppendInt32(_habboAchievement.Achievement.Levels[_habboAchievement.Level].RewardAmount); + message.AppendInt32(_habboAchievement.Achievement.Levels[_habboAchievement.Level].RewardType); + message.AppendInt32(_habboAchievement.Achievement.Levels[_habboAchievement.Level].Points); + message.AppendInt32(_habboAchievement.Achievement.Id); + message.AppendString(_habboAchievement.Level > 1 ? $"{_habboAchievement.Achievement.Badge}{_habboAchievement.Level - 1}" : string.Empty); + message.AppendString(_habboAchievement.Achievement.Category); + message.AppendBoolean(true); + } +} \ No newline at end of file diff --git a/Communication/Messages/Outgoing/Notifications/ActivityPointNotificationMessageComposer.cs b/Communication/Messages/Outgoing/Notifications/ActivityPointNotificationMessageComposer.cs new file mode 100644 index 0000000..95b5c19 --- /dev/null +++ b/Communication/Messages/Outgoing/Notifications/ActivityPointNotificationMessageComposer.cs @@ -0,0 +1,26 @@ +using Tiger.Communication.Messages.Interfaces; +using Tiger.Communication.Messages.Types; + +namespace Tiger.Communication.Messages.Outgoing.Notifications; + +public class ActivityPointNotificationMessageComposer : IMessageComposer +{ + private readonly int _amount; + private readonly int _amountChanged; + private readonly int _type; + + public ActivityPointNotificationMessageComposer(int amount, int amountChanged, int type) + { + _amount = amount; + _amountChanged = amountChanged; + _type = type; + } + + public OutgoingHeaders Header => OutgoingHeaders.ActivityPointNotificationMessageComposer; + public void Compose(ServerMessage message) + { + message.AppendInt32(_amount); + message.AppendInt32(_amountChanged); + message.AppendInt32(_type); + } +} \ No newline at end of file diff --git a/Communication/Messages/Outgoing/Notifications/ActivityPointsComposer.cs b/Communication/Messages/Outgoing/Notifications/ActivityPointsComposer.cs index 314f310..96919c7 100644 --- a/Communication/Messages/Outgoing/Notifications/ActivityPointsComposer.cs +++ b/Communication/Messages/Outgoing/Notifications/ActivityPointsComposer.cs @@ -6,9 +6,9 @@ namespace Tiger.Communication.Messages.Outgoing.Notifications; public class ActivityPointsComposer : IMessageComposer { - private readonly IEnumerable? _activitypoints; + private readonly ICollection _activitypoints; - public ActivityPointsComposer(IEnumerable? activitypoints) + public ActivityPointsComposer(ICollection activitypoints) { _activitypoints = activitypoints; } @@ -16,9 +16,7 @@ public class ActivityPointsComposer : IMessageComposer public OutgoingHeaders Header => OutgoingHeaders.ActivityPointsMessageComposer; public void Compose(ServerMessage message) { - message.AppendInt32(_activitypoints?.Count() ?? 0); - - if (_activitypoints == null) return; + message.AppendInt32(_activitypoints.Count); foreach (var activitypoint in _activitypoints) { diff --git a/Communication/Messages/Outgoing/OutgoingHeaders.cs b/Communication/Messages/Outgoing/OutgoingHeaders.cs index 4ac66cb..45fd73d 100644 --- a/Communication/Messages/Outgoing/OutgoingHeaders.cs +++ b/Communication/Messages/Outgoing/OutgoingHeaders.cs @@ -192,8 +192,8 @@ public enum OutgoingHeaders GuildMembershipRejectedMessageComposer = 2445, GuildMembershipsMessageComposer = 420, GuildMembershipUpdatedMessageComposer = 265, - HabboAchievementNotificationMessageComposer = 806, - HabboActivityPointNotificationMessageComposer = 2275, + AchievementNotificationMessageComposer = 806, + ActivityPointNotificationMessageComposer = 2275, HabboBroadcastMessageComposer = 3801, HabboClubExtendOfferMessageComposer = 3964, HabboClubOffersMessageComposer = 2405, diff --git a/Game/Achievements/Achievement.cs b/Game/Achievements/Achievement.cs new file mode 100644 index 0000000..4e3a2cb --- /dev/null +++ b/Game/Achievements/Achievement.cs @@ -0,0 +1,9 @@ +namespace Tiger.Game.Achievements; + +public class Achievement +{ + public virtual int Id { get; set; } + public virtual string Badge { get; set; } = null!; + public virtual string Category { get; set; } = null!; + public virtual IDictionary Levels { get; set; } = new Dictionary(); +} \ No newline at end of file diff --git a/Game/Achievements/AchievementLevel.cs b/Game/Achievements/AchievementLevel.cs new file mode 100644 index 0000000..8ad96e9 --- /dev/null +++ b/Game/Achievements/AchievementLevel.cs @@ -0,0 +1,30 @@ +namespace Tiger.Game.Achievements; + +public class AchievementLevel +{ + public virtual Achievement Achievement { get; set; } = null!; + public virtual int Level { get; set; } + public virtual int RewardAmount { get; set; } + public virtual int RewardType { get; set; } + public virtual int Points { get; set; } + public virtual int ProgressNeeded { get; set; } + + public override bool Equals(object? obj) + { + if (obj is not AchievementLevel other) + return false; + + return Achievement.Id == other.Achievement.Id && Level == other.Level; + } + + public override int GetHashCode() + { + unchecked + { + var hash = 17; + hash = hash * 23 + Achievement.Id.GetHashCode(); + hash = hash * 23 + Level.GetHashCode(); + return hash; + } + } +} \ No newline at end of file diff --git a/Game/Achievements/AchievementLevelMap.cs b/Game/Achievements/AchievementLevelMap.cs new file mode 100644 index 0000000..1ee18f5 --- /dev/null +++ b/Game/Achievements/AchievementLevelMap.cs @@ -0,0 +1,19 @@ +using FluentNHibernate.Mapping; + +namespace Tiger.Game.Achievements; + +public class AchievementLevelMap : ClassMap +{ + public AchievementLevelMap() + { + Table("achievement_levels"); + LazyLoad(); + CompositeId() + .KeyProperty(al => al.Level, "level") + .KeyReference(al => al.Achievement, "achievement_id"); + Map(al => al.RewardAmount).Column("reward_amount").Not.Nullable(); + Map(al => al.RewardType).Column("reward_type").Not.Nullable(); + Map(al => al.ProgressNeeded).Column("progress_needed").Not.Nullable(); + Map(al => al.Points).Column("points").Not.Nullable(); + } +} \ No newline at end of file diff --git a/Game/Achievements/AchievementManager.cs b/Game/Achievements/AchievementManager.cs new file mode 100644 index 0000000..cb3663d --- /dev/null +++ b/Game/Achievements/AchievementManager.cs @@ -0,0 +1,113 @@ +using Microsoft.Extensions.Logging; +using Tiger.Communication.Messages.Outgoing.Inventory.Achievements; +using Tiger.Communication.Messages.Outgoing.Notifications; +using Tiger.Game.Habbos; +using Tiger.Networking.Game.Sessions; +using Tiger.Storage; + +namespace Tiger.Game.Achievements; + +public class AchievementManager : IAchievementManager +{ + private readonly IRepository _achievementRepository; + private readonly ILogger _logger; + private readonly IRepository _badgesRepository; + private readonly IRepository _habboRepository; + + public AchievementManager(IRepository achievementRepository, ILogger logger, IRepository badgesRepository, IRepository habboRepository) + { + _achievementRepository = achievementRepository; + _logger = logger; + _badgesRepository = badgesRepository; + _habboRepository = habboRepository; + } + + public IDictionary Achievements { get; private set; } = new Dictionary(); + + public async Task LoadAchievementsAsync() + { + Achievements = (await _achievementRepository.FindByAsync()).ToDictionary(a => a.Badge, a => a); + + _logger.LogInformation("Loaded {Count} Achievements", Achievements.Count); + } + + public async Task UpdateAchievementAsync(string achievementName, int progress, GameSession session) + { + if (session.Habbo is null) return; + + if (!Achievements.TryGetValue(achievementName, out var achievement)) return; + + if (progress == 0) return; + + if (!session.Habbo.Achievements.TryGetValue(achievement.Id, out var habboAchievement)) + { + habboAchievement = new HabboAchievement() + { + Level = 0, + Progress = 0, + Achievement = achievement, + Habbo = session.Habbo + }; + + session.Habbo.Achievements.Add(achievement.Id, habboAchievement); + } + + if (habboAchievement.Level == achievement.Levels.Count) return; + + var targetLevel = habboAchievement.Level + 1; + var achievementLevel = achievement.Levels[targetLevel]; + + habboAchievement.Progress += progress; + + if (habboAchievement.Progress >= achievementLevel.ProgressNeeded) + { + habboAchievement.Level++; + + Badge badge; + + if (habboAchievement.Level == 1) + { + badge = new Badge + { + Habbo = session.Habbo, + Code = $"{achievement.Badge}1" + }; + } + else + { + var currentBadge = + session.Habbo.Badges.SingleOrDefault(b => + b.Code == $"{achievement.Badge}{habboAchievement.Level - 1}"); + + if (currentBadge != null) + { + currentBadge.Code = $"{achievement.Badge}{habboAchievement.Level - 1}"; + badge = currentBadge; + } + else + { + badge = new Badge + { + Habbo = session.Habbo, + Code = $"{achievement.Badge}1" + }; + } + } + + await _badgesRepository.SaveAsync(badge); + + session.Habbo.AchievementScore += achievementLevel.Points; + session.Habbo.UpdateCurrency(achievementLevel.RewardType, achievementLevel.RewardAmount); + + // 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); + + await session.SendComposerAsync(new AchievementComposer(achievement, habboAchievement)); + } +} \ No newline at end of file diff --git a/Game/Achievements/AchievementMap.cs b/Game/Achievements/AchievementMap.cs new file mode 100644 index 0000000..2e7b4fb --- /dev/null +++ b/Game/Achievements/AchievementMap.cs @@ -0,0 +1,16 @@ +using FluentNHibernate.Mapping; + +namespace Tiger.Game.Achievements; + +public class AchievementMap : ClassMap +{ + public AchievementMap() + { + Table("achievements"); + LazyLoad(); + Id(a => a.Id).Column("id").GeneratedBy.Identity(); + Map(a => a.Badge).Column("badge").Not.Nullable(); + Map(a => a.Category).Column("category").Not.Nullable(); + HasMany(a => a.Levels).AsMap(al => al.Level).Cascade.All(); + } +} \ No newline at end of file diff --git a/Game/Achievements/IAchievementManager.cs b/Game/Achievements/IAchievementManager.cs new file mode 100644 index 0000000..92bc3d6 --- /dev/null +++ b/Game/Achievements/IAchievementManager.cs @@ -0,0 +1,10 @@ +using Tiger.Networking.Game.Sessions; + +namespace Tiger.Game.Achievements; + +public interface IAchievementManager +{ + IDictionary Achievements { get; } + Task LoadAchievementsAsync(); + Task UpdateAchievementAsync(string achievementName, int progress, GameSession session); +} \ No newline at end of file diff --git a/Game/Habbos/Habbo.cs b/Game/Habbos/Habbo.cs index 89a8c9d..d101605 100644 --- a/Game/Habbos/Habbo.cs +++ b/Game/Habbos/Habbo.cs @@ -17,6 +17,24 @@ public class Habbo public virtual int AchievementScore { get; set; } public virtual int? GroupId { get; set; } public virtual string? SsoTicket { get; set; } - public virtual IEnumerable? Activitypoints { get; set; } - public virtual IEnumerable? Badges { get; set; } + public virtual IDictionary Activitypoints { get; set; } = new Dictionary(); + public virtual ICollection Badges { get; set; } = new List(); + + public virtual IDictionary Achievements { get; set; } = new Dictionary(); + + public virtual void UpdateCurrency(int type, int amount) + { + if (!Activitypoints.ContainsKey(type)) + { + Activitypoints.Add(type, new Activitypoints + { + Habbo = this, + Amount = amount, + Type = type + }); + return; + } + + Activitypoints[type].Amount += amount; + } } \ No newline at end of file diff --git a/Game/Habbos/HabboAchievement.cs b/Game/Habbos/HabboAchievement.cs new file mode 100644 index 0000000..1aeec7c --- /dev/null +++ b/Game/Habbos/HabboAchievement.cs @@ -0,0 +1,30 @@ +using Tiger.Game.Achievements; + +namespace Tiger.Game.Habbos; + +public class HabboAchievement +{ + public virtual Habbo Habbo { get; set; } = null!; + public virtual Achievement Achievement { get; set; } = null!; + public virtual int Level { get; set; } + public virtual int Progress { get; set; } + + public override bool Equals(object? obj) + { + if (obj is not HabboAchievement other) + return false; + + return Habbo.Id == other.Habbo.Id && Achievement.Id == other.Achievement.Id; + } + + public override int GetHashCode() + { + unchecked + { + var hash = 17; + hash = hash * 23 + Habbo.Id.GetHashCode(); + hash = hash * 23 + Achievement.Id.GetHashCode(); + return hash; + } + } +} \ No newline at end of file diff --git a/Game/Habbos/HabboAchievementMap.cs b/Game/Habbos/HabboAchievementMap.cs new file mode 100644 index 0000000..50124d9 --- /dev/null +++ b/Game/Habbos/HabboAchievementMap.cs @@ -0,0 +1,17 @@ +using FluentNHibernate.Mapping; + +namespace Tiger.Game.Habbos; + +public class HabboAchievementMap : ClassMap +{ + public HabboAchievementMap() + { + Table("habbo_achievements"); + LazyLoad(); + CompositeId() + .KeyReference(ha => ha.Habbo, "habbo_id") + .KeyReference(ha => ha.Achievement, "achievement_id"); + Map(ha => ha.Level).Column("level").Not.Nullable(); + Map(ha => ha.Progress).Column("progress").Not.Nullable(); + } +} \ No newline at end of file diff --git a/Game/Habbos/HabboMap.cs b/Game/Habbos/HabboMap.cs index 7e373b3..113575f 100644 --- a/Game/Habbos/HabboMap.cs +++ b/Game/Habbos/HabboMap.cs @@ -23,7 +23,18 @@ public class HabboMap : ClassMap Map(h => h.AchievementScore).Column("achievement_score").Not.Nullable(); Map(h => h.GroupId).Column("group_id").Nullable(); Map(h => h.SsoTicket).Column("sso_ticket").Nullable(); - HasMany(h => h.Activitypoints).LazyLoad().Inverse().Cascade.All(); - HasMany(h => h.Badges).LazyLoad().Inverse().Cascade.All(); + HasMany(h => h.Activitypoints).AsMap(a => a.Type).Inverse().Cascade.All(); + HasMany(h => h.Badges).Inverse().Cascade.All(); + HasMany(x => x.Achievements) + .Table("habbo_achievements") + .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(); } } \ No newline at end of file diff --git a/Program.cs b/Program.cs index 124cd73..99fb035 100644 --- a/Program.cs +++ b/Program.cs @@ -3,6 +3,7 @@ using Microsoft.Extensions.Configuration.Yaml; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Tiger.Communication.Messages; +using Tiger.Game.Achievements; using Tiger.Game.Catalogue; using Tiger.Game.Figuredata; using Tiger.Game.Habbos; @@ -39,6 +40,7 @@ collection.AddSingleton(); collection.AddSingleton(); collection.AddSingleton(); collection.AddSingleton(); +collection.AddSingleton(); collection.RegisterMessageEvents(); var provider = collection.BuildServiceProvider(); @@ -47,6 +49,7 @@ await provider.GetRequiredService().ReloadSettingsAsync(); await provider.GetRequiredService().LoadPagesAsync(); provider.GetRequiredService(); await provider.GetRequiredService().LoadPromoArticlesAsync(); +await provider.GetRequiredService().LoadAchievementsAsync(); provider.GetRequiredService().Start($"http://{configuration["Network:Game:Ip"]}:{configuration["Network:Game:Port"]}/");