diff --git a/Communication/Messages/Incoming/Navigator/GetUserFlatCatsMessageEvent.cs b/Communication/Messages/Incoming/Navigator/GetUserFlatCatsMessageEvent.cs new file mode 100644 index 0000000..4820935 --- /dev/null +++ b/Communication/Messages/Incoming/Navigator/GetUserFlatCatsMessageEvent.cs @@ -0,0 +1,32 @@ +using Tiger.Communication.Messages.Interfaces; +using Tiger.Communication.Messages.Outgoing.Navigator; +using Tiger.Communication.Messages.Types; +using Tiger.Game.Rooms; +using Tiger.Networking.Game.Sessions; + +namespace Tiger.Communication.Messages.Incoming.Navigator; + +public class GetUserFlatCatsMessageEvent : IMessageEvent +{ + private readonly IGameSessionManager _gameSessionManager; + private readonly IRoomManager _roomManager; + + public GetUserFlatCatsMessageEvent(IRoomManager roomManager, IGameSessionManager gameSessionManager) + { + _roomManager = roomManager; + _gameSessionManager = gameSessionManager; + } + + public IncomingHeaders Header => IncomingHeaders.GetUserFlatCats; + public async Task HandleAsync(GameSession gameSession, ClientMessage request) + { + if (gameSession.Habbo == null) + { + await _gameSessionManager.CloseAsync("Not logged in", gameSession); + return; + } + + await gameSession.SendComposerAsync(new UserFlatCatsComposer(_roomManager.PrivateCategories.Values, + gameSession.Habbo.Rank)); + } +} \ No newline at end of file diff --git a/Communication/Messages/Incoming/Navigator/NavigatorInitEvent.cs b/Communication/Messages/Incoming/Navigator/NavigatorInitEvent.cs new file mode 100644 index 0000000..c4bb90a --- /dev/null +++ b/Communication/Messages/Incoming/Navigator/NavigatorInitEvent.cs @@ -0,0 +1,32 @@ +using Tiger.Communication.Messages.Interfaces; +using Tiger.Communication.Messages.Outgoing.Navigator; +using Tiger.Communication.Messages.Types; +using Tiger.Game.Navigator; +using Tiger.Networking.Game.Sessions; + +namespace Tiger.Communication.Messages.Incoming.Navigator; + +public class NavigatorInitEvent : IMessageEvent +{ + private readonly IGameSessionManager _gameSessionManager; + private readonly INavigatorManager _navigatorManager; + + public NavigatorInitEvent(IGameSessionManager gameSessionManager, INavigatorManager navigatorManager) + { + _gameSessionManager = gameSessionManager; + _navigatorManager = navigatorManager; + } + + public IncomingHeaders Header => IncomingHeaders.NavigatorInit; + public async Task HandleAsync(GameSession gameSession, ClientMessage request) + { + if (gameSession.Habbo == null) + { + await _gameSessionManager.CloseAsync("Not logged in", gameSession); + return; + } + + await gameSession.SendComposerAsync(new NavigatorMetadataComposer(_navigatorManager.NavigatorViews.Values)); + await gameSession.SendComposerAsync(new NavigatorCollapsedComposer()); + } +} \ No newline at end of file diff --git a/Communication/Messages/Incoming/Navigator/NavigatorSearchEvent.cs b/Communication/Messages/Incoming/Navigator/NavigatorSearchEvent.cs new file mode 100644 index 0000000..c4b973d --- /dev/null +++ b/Communication/Messages/Incoming/Navigator/NavigatorSearchEvent.cs @@ -0,0 +1,37 @@ +using Tiger.Communication.Messages.Interfaces; +using Tiger.Communication.Messages.Outgoing.Navigator; +using Tiger.Communication.Messages.Types; +using Tiger.Game.Navigator; +using Tiger.Networking.Game.Sessions; + +namespace Tiger.Communication.Messages.Incoming.Navigator; + +public class NavigatorSearchEvent : IMessageEvent +{ + private readonly IGameSessionManager _gameSessionManager; + private readonly INavigatorManager _navigatorManager; + + public NavigatorSearchEvent(IGameSessionManager gameSessionManager, INavigatorManager navigatorManager) + { + _gameSessionManager = gameSessionManager; + _navigatorManager = navigatorManager; + } + + public IncomingHeaders Header => IncomingHeaders.NavigatorSearch; + public async Task HandleAsync(GameSession gameSession, ClientMessage request) + { + if (gameSession.Habbo == null) + { + await _gameSessionManager.CloseAsync("Not logged in", gameSession); + return; + } + + var viewName = request.ReadString(); + var query = request.ReadString(); + + if (viewName is null || query is null || + !_navigatorManager.NavigatorViews.TryGetValue(viewName, out var navigatorView)) return; + + await gameSession.SendComposerAsync(new NavigatorSearchComposer(navigatorView, query, gameSession.Habbo)); + } +} \ No newline at end of file diff --git a/Communication/Messages/Outgoing/Navigator/NavigatorCollapsedComposer.cs b/Communication/Messages/Outgoing/Navigator/NavigatorCollapsedComposer.cs new file mode 100644 index 0000000..aa9267d --- /dev/null +++ b/Communication/Messages/Outgoing/Navigator/NavigatorCollapsedComposer.cs @@ -0,0 +1,14 @@ +using Tiger.Communication.Messages.Interfaces; +using Tiger.Communication.Messages.Types; + +namespace Tiger.Communication.Messages.Outgoing.Navigator; + +public class NavigatorCollapsedComposer : IMessageComposer +{ + public OutgoingHeaders Header => OutgoingHeaders.NavigatorCollapsed; + public void Compose(ServerMessage message) + { + message.AppendInt32(1); + message.AppendString("official"); + } +} \ No newline at end of file diff --git a/Communication/Messages/Outgoing/Navigator/NavigatorMetadataComposer.cs b/Communication/Messages/Outgoing/Navigator/NavigatorMetadataComposer.cs new file mode 100644 index 0000000..45e17a1 --- /dev/null +++ b/Communication/Messages/Outgoing/Navigator/NavigatorMetadataComposer.cs @@ -0,0 +1,27 @@ +using Tiger.Communication.Messages.Interfaces; +using Tiger.Communication.Messages.Types; +using Tiger.Game.Navigator.Views; + +namespace Tiger.Communication.Messages.Outgoing.Navigator; + +public class NavigatorMetadataComposer : IMessageComposer +{ + private readonly ICollection _navigatorViews; + + public NavigatorMetadataComposer(ICollection navigatorViews) + { + _navigatorViews = navigatorViews; + } + + public OutgoingHeaders Header => OutgoingHeaders.NavigatorMetadata; + public void Compose(ServerMessage message) + { + message.AppendInt32(_navigatorViews.Count); + + foreach (var navigatorView in _navigatorViews) + { + message.AppendString(navigatorView.Code); + message.AppendInt32(0); // saved searches + } + } +} \ No newline at end of file diff --git a/Communication/Messages/Outgoing/Navigator/NavigatorSearchComposer.cs b/Communication/Messages/Outgoing/Navigator/NavigatorSearchComposer.cs new file mode 100644 index 0000000..a09f8bc --- /dev/null +++ b/Communication/Messages/Outgoing/Navigator/NavigatorSearchComposer.cs @@ -0,0 +1,28 @@ +using Tiger.Communication.Messages.Interfaces; +using Tiger.Communication.Messages.Types; +using Tiger.Game.Habbos; +using Tiger.Game.Navigator.Views; + +namespace Tiger.Communication.Messages.Outgoing.Navigator; + +public class NavigatorSearchComposer : IMessageComposer +{ + private readonly INavigatorView _navigatorView; + private readonly string _query; + private readonly Habbo _habbo; + + public NavigatorSearchComposer(INavigatorView navigatorView, string query, Habbo habbo) + { + _navigatorView = navigatorView; + _query = query; + _habbo = habbo; + } + + public OutgoingHeaders Header => OutgoingHeaders.NavigatorSearch; + public void Compose(ServerMessage message) + { + message.AppendString(_navigatorView.Code); + message.AppendString(_query); + _navigatorView.Compose(message, _habbo, _query); + } +} \ No newline at end of file diff --git a/Communication/Messages/Outgoing/Navigator/UserFlatCatsComposer.cs b/Communication/Messages/Outgoing/Navigator/UserFlatCatsComposer.cs new file mode 100644 index 0000000..d4ef7c0 --- /dev/null +++ b/Communication/Messages/Outgoing/Navigator/UserFlatCatsComposer.cs @@ -0,0 +1,34 @@ +using Tiger.Communication.Messages.Interfaces; +using Tiger.Communication.Messages.Types; +using Tiger.Game.Rooms; + +namespace Tiger.Communication.Messages.Outgoing.Navigator; + +public class UserFlatCatsComposer : IMessageComposer +{ + private readonly ICollection _privateCategories; + private readonly int _rank; + + public UserFlatCatsComposer(ICollection privateCategories, int rank) + { + _privateCategories = privateCategories; + _rank = rank; + } + + public OutgoingHeaders Header => OutgoingHeaders.NavigatorCategories; + public void Compose(ServerMessage message) + { + message.AppendInt32(_privateCategories.Count); + + foreach (var privateCategory in _privateCategories) + { + message.AppendInt32(privateCategory.Id); + message.AppendString(privateCategory.Name); + message.AppendBoolean(privateCategory.MinRank <= _rank); + message.AppendBoolean(true); // automatic? + message.AppendString(""); // automatic category key? + message.AppendString(""); // global category key? + message.AppendBoolean(privateCategory.MinRank >= 4); + } + } +} \ No newline at end of file diff --git a/Game/Navigator/INavigatorManager.cs b/Game/Navigator/INavigatorManager.cs new file mode 100644 index 0000000..54c8364 --- /dev/null +++ b/Game/Navigator/INavigatorManager.cs @@ -0,0 +1,8 @@ +using Tiger.Game.Navigator.Views; + +namespace Tiger.Game.Navigator; + +public interface INavigatorManager +{ + IDictionary NavigatorViews { get; } +} \ No newline at end of file diff --git a/Game/Navigator/NavigatorManager.cs b/Game/Navigator/NavigatorManager.cs new file mode 100644 index 0000000..8a329ce --- /dev/null +++ b/Game/Navigator/NavigatorManager.cs @@ -0,0 +1,13 @@ +using Tiger.Game.Navigator.Views; + +namespace Tiger.Game.Navigator; + +public class NavigatorManager : INavigatorManager +{ + public IDictionary NavigatorViews { get; } + + public NavigatorManager(IEnumerable navigatorViews) + { + NavigatorViews = navigatorViews.ToDictionary(n => n.Code); + } +} \ No newline at end of file diff --git a/Game/Navigator/Views/INavigatorView.cs b/Game/Navigator/Views/INavigatorView.cs new file mode 100644 index 0000000..52b4262 --- /dev/null +++ b/Game/Navigator/Views/INavigatorView.cs @@ -0,0 +1,10 @@ +using Tiger.Communication.Messages.Types; +using Tiger.Game.Habbos; + +namespace Tiger.Game.Navigator.Views; + +public interface INavigatorView +{ + string Code { get; } + void Compose(ServerMessage message, Habbo habbo, string query); +} \ No newline at end of file diff --git a/Game/Navigator/Views/MyWorldView.cs b/Game/Navigator/Views/MyWorldView.cs new file mode 100644 index 0000000..fe0febb --- /dev/null +++ b/Game/Navigator/Views/MyWorldView.cs @@ -0,0 +1,54 @@ +using System.Collections; +using Tiger.Communication.Messages.Types; +using Tiger.Game.Habbos; + +namespace Tiger.Game.Navigator.Views; + +public class MyWorldView : INavigatorView +{ + private const int OwnRoomsType = 0; + private const int FavoriteRoomsType = 1; + private const int GroupRoomsType = 2; + private const int VisitedRoomsType = 3; + private const int FriendRoomsType = 4; + private const int RightsRoomType = 5; + + public string Code => "myworld_view"; + + private readonly IDictionary _categories = new Dictionary + { + {"My Rooms", OwnRoomsType}, + {"My Favorite Rooms", FavoriteRoomsType}, + {"My Groups", GroupRoomsType}, + {"My Room Visit History", VisitedRoomsType}, + {"My Friends' Rooms", FriendRoomsType}, + {"Rooms Where I Have Rights", RightsRoomType} + }; + + public MyWorldView() + { + } + + public void Compose(ServerMessage message, Habbo habbo, string query) + { + message.AppendInt32(_categories.Count); + + foreach (var (category, type) in _categories) + { + message.AppendString(category); + message.AppendString(category); + message.AppendInt32(0); // action? + message.AppendBoolean(false); // closed? + message.AppendInt32(0); // mode? + + var rooms = GetRoomsByType(habbo, type); + + message.AppendInt32(rooms.Count); // TODO: Rooms, this will ALWAYS return 0. + } + } + + private ICollection GetRoomsByType(Habbo habbo, int type) + { + return new List(); + } +} \ No newline at end of file diff --git a/Game/Navigator/Views/OfficialView.cs b/Game/Navigator/Views/OfficialView.cs new file mode 100644 index 0000000..b8826cb --- /dev/null +++ b/Game/Navigator/Views/OfficialView.cs @@ -0,0 +1,13 @@ +using Tiger.Communication.Messages.Types; +using Tiger.Game.Habbos; + +namespace Tiger.Game.Navigator.Views; + +public class OfficialView : INavigatorView +{ + public string Code => "official_view"; + public void Compose(ServerMessage message, Habbo habbo, string query) + { + message.AppendInt32(0); + } +} \ No newline at end of file diff --git a/Game/Rooms/IRoomManager.cs b/Game/Rooms/IRoomManager.cs new file mode 100644 index 0000000..b7f9518 --- /dev/null +++ b/Game/Rooms/IRoomManager.cs @@ -0,0 +1,7 @@ +namespace Tiger.Game.Rooms; + +public interface IRoomManager +{ + IDictionary PrivateCategories { get; } + Task LoadPrivateCategoriesAsync(); +} \ No newline at end of file diff --git a/Game/Rooms/RoomManager.cs b/Game/Rooms/RoomManager.cs new file mode 100644 index 0000000..6c0b754 --- /dev/null +++ b/Game/Rooms/RoomManager.cs @@ -0,0 +1,28 @@ +using Microsoft.Extensions.Logging; +using Tiger.Storage; + +namespace Tiger.Game.Rooms; + +public class RoomManager : IRoomManager +{ + private readonly IRepository _roomPrivateCategoryRepository; + private readonly ILogger _logger; + + public IDictionary PrivateCategories { get; private set; } + + public RoomManager(IRepository roomPrivateCategoryRepository, ILogger logger) + { + _roomPrivateCategoryRepository = roomPrivateCategoryRepository; + _logger = logger; + + PrivateCategories = new Dictionary(); + } + + public async Task LoadPrivateCategoriesAsync() + { + PrivateCategories = + (await _roomPrivateCategoryRepository.FindByAsync()).ToDictionary(rpc => rpc.Id); + + _logger.LogInformation("Loaded {Count} private room categories", PrivateCategories.Count); + } +} \ No newline at end of file diff --git a/Game/Rooms/RoomPrivateCategory.cs b/Game/Rooms/RoomPrivateCategory.cs new file mode 100644 index 0000000..00d66d9 --- /dev/null +++ b/Game/Rooms/RoomPrivateCategory.cs @@ -0,0 +1,10 @@ +namespace Tiger.Game.Rooms; + +public class RoomPrivateCategory +{ + public virtual int Id { get; set; } + public virtual int MinRank { get; set; } + public virtual string Code { get; set; } = null!; + public virtual string Name { get; set; } = null!; + public virtual bool CanTrade { get; set; } +} \ No newline at end of file diff --git a/Game/Rooms/RoomPrivateCategoryMap.cs b/Game/Rooms/RoomPrivateCategoryMap.cs new file mode 100644 index 0000000..9bcac19 --- /dev/null +++ b/Game/Rooms/RoomPrivateCategoryMap.cs @@ -0,0 +1,6 @@ +namespace Tiger.Game.Rooms; + +public class RoomPrivateCategoryMap +{ + +} \ No newline at end of file diff --git a/Program.cs b/Program.cs index cfdbc66..da21388 100644 --- a/Program.cs +++ b/Program.cs @@ -3,11 +3,15 @@ using Microsoft.Extensions.Configuration.Yaml; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Tiger.Communication.Messages; +using Tiger.Communication.Messages.Interfaces; using Tiger.Game.Achievements; using Tiger.Game.Catalogue; using Tiger.Game.Figuredata; using Tiger.Game.Habbos; using Tiger.Game.LandingView; +using Tiger.Game.Navigator; +using Tiger.Game.Navigator.Views; +using Tiger.Game.Rooms; using Tiger.Game.Settings; using Tiger.Networking.Game; using Tiger.Networking.Game.Sessions; @@ -41,7 +45,10 @@ collection.AddSingleton(); collection.AddSingleton(); collection.AddSingleton(); collection.AddSingleton(); -collection.RegisterMessageEvents(); +collection.AddSingleton(); +collection.AddSingleton(); +collection.RegisterOnInherited(); +collection.RegisterOnInherited(); var provider = collection.BuildServiceProvider(); @@ -51,6 +58,7 @@ await provider.GetRequiredService().LoadFeaturedPagesAsync(); provider.GetRequiredService(); await provider.GetRequiredService().LoadPromoArticlesAsync(); await provider.GetRequiredService().LoadAchievementsAsync(); +await provider.GetRequiredService().LoadPrivateCategoriesAsync(); provider.GetRequiredService().Start($"http://{configuration["Network:Game:Ip"]}:{configuration["Network:Game:Port"]}/"); diff --git a/TigerEmu.csproj b/TigerEmu.csproj index 1a02297..1d79ada 100644 --- a/TigerEmu.csproj +++ b/TigerEmu.csproj @@ -30,7 +30,4 @@ PreserveNewest - - - diff --git a/Utils/DependencyInjectionExtensions.cs b/Utils/DependencyInjectionExtensions.cs index 262ca61..fd9c1b8 100644 --- a/Utils/DependencyInjectionExtensions.cs +++ b/Utils/DependencyInjectionExtensions.cs @@ -6,19 +6,19 @@ namespace Tiger.Utils; public static class DependencyInjectionExtensions { - public static void RegisterMessageEvents(this IServiceCollection services) + public static void RegisterOnInherited(this IServiceCollection services) { // Get the assembly you are interested in (this could be any Assembly) var assembly = Assembly.GetExecutingAssembly(); // Get all types that implement IMessageEvent and are not abstract - var messageEventTypes = assembly.GetTypes() - .Where(t => t.GetInterfaces().Contains(typeof(IMessageEvent)) && !t.IsAbstract); + var types = assembly.GetTypes() + .Where(t => t.GetInterfaces().Contains(typeof(T)) && !t.IsAbstract); // Register each type with AddSingleton - foreach (var type in messageEventTypes) + foreach (var type in types) { - services.AddSingleton(typeof(IMessageEvent), type); + services.AddSingleton(typeof(T), type); } }