Started on catalogue, added the index and pages packets
parent
66744ead65
commit
59d90aeeb2
|
@ -0,0 +1,34 @@
|
||||||
|
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 GetCatalogIndexEvent : IMessageEvent
|
||||||
|
{
|
||||||
|
private readonly ICatalogueManager _catalogueManager;
|
||||||
|
private readonly IGameSessionManager _gameSessionManager;
|
||||||
|
|
||||||
|
public GetCatalogIndexEvent(ICatalogueManager catalogueManager, IGameSessionManager gameSessionManager)
|
||||||
|
{
|
||||||
|
_catalogueManager = catalogueManager;
|
||||||
|
_gameSessionManager = gameSessionManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IncomingHeaders Header => IncomingHeaders.GetCatalogIndexEvent;
|
||||||
|
public async Task HandleAsync(GameSession gameSession, ClientMessage request)
|
||||||
|
{
|
||||||
|
if (gameSession.Habbo == null)
|
||||||
|
{
|
||||||
|
await _gameSessionManager.CloseAsync("Not logged in", gameSession);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var categories = _catalogueManager.Pages.Values.Where(p => p.Parent is null);
|
||||||
|
|
||||||
|
await gameSession.SendComposerAsync(new CatalogIndexMessageComposer(categories,
|
||||||
|
request.ReadString() ?? "normal"));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
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 GetCatalogPageEvent : IMessageEvent
|
||||||
|
{
|
||||||
|
private readonly ICatalogueManager _catalogueManager;
|
||||||
|
private readonly IGameSessionManager _gameSessionManager;
|
||||||
|
|
||||||
|
public GetCatalogPageEvent(ICatalogueManager catalogueManager, IGameSessionManager gameSessionManager)
|
||||||
|
{
|
||||||
|
_catalogueManager = catalogueManager;
|
||||||
|
_gameSessionManager = gameSessionManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IncomingHeaders Header => IncomingHeaders.GetCatalogPageEvent;
|
||||||
|
public async Task HandleAsync(GameSession gameSession, ClientMessage request)
|
||||||
|
{
|
||||||
|
if (gameSession.Habbo == null)
|
||||||
|
{
|
||||||
|
await _gameSessionManager.CloseAsync("Not logged in", gameSession);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var pageId = request.ReadInt32() ?? -1;
|
||||||
|
var offerId = request.ReadInt32() ?? 0;
|
||||||
|
var mode = request.ReadString() ?? "normal";
|
||||||
|
|
||||||
|
if (!_catalogueManager.Pages.TryGetValue(pageId, out var page))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await gameSession.SendComposerAsync(new CatalogPageMessageComposer(page, offerId, mode));
|
||||||
|
}
|
||||||
|
}
|
|
@ -32,7 +32,8 @@ public class SetActivatedBadgesEvent : IMessageEvent
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var wearingBadges = new Collection<Badge>();
|
var wearingBadges = new Collection<Badge>();
|
||||||
foreach (var currentBadge in gameSession.Habbo.Badges)
|
var current = gameSession.Habbo.Badges.Where(b => b.Slot != 0);
|
||||||
|
foreach (var currentBadge in current)
|
||||||
{
|
{
|
||||||
currentBadge.Slot = 0;
|
currentBadge.Slot = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
using Tiger.Communication.Messages.Interfaces;
|
||||||
|
using Tiger.Communication.Messages.Types;
|
||||||
|
using Tiger.Game.Catalogue;
|
||||||
|
|
||||||
|
namespace Tiger.Communication.Messages.Outgoing.Catalog;
|
||||||
|
|
||||||
|
public class CatalogIndexMessageComposer : IMessageComposer
|
||||||
|
{
|
||||||
|
private readonly IEnumerable<CataloguePage> _pages;
|
||||||
|
private readonly string _mode;
|
||||||
|
|
||||||
|
public CatalogIndexMessageComposer(IEnumerable<CataloguePage> pages, string mode)
|
||||||
|
{
|
||||||
|
_pages = pages;
|
||||||
|
_mode = mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OutgoingHeaders Header => OutgoingHeaders.CatalogIndexMessageComposer;
|
||||||
|
public void Compose(ServerMessage message)
|
||||||
|
{
|
||||||
|
message.AppendBoolean(true);
|
||||||
|
message.AppendInt32(0);
|
||||||
|
message.AppendInt32(-1);
|
||||||
|
message.AppendString(string.Empty);
|
||||||
|
message.AppendString(string.Empty);
|
||||||
|
message.AppendInt32(0);
|
||||||
|
message.AppendInt32(_pages.Count());
|
||||||
|
|
||||||
|
foreach (var page in _pages)
|
||||||
|
{
|
||||||
|
SerializeNode(page, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
message.AppendBoolean(false);
|
||||||
|
message.AppendString(_mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SerializeNode(CataloguePage page, ServerMessage message)
|
||||||
|
{
|
||||||
|
message.AppendBoolean(page.Visible);
|
||||||
|
message.AppendInt32(page.Icon);
|
||||||
|
message.AppendInt32(page.Id);
|
||||||
|
message.AppendString(page.InternalName);
|
||||||
|
message.AppendString(page.Name);
|
||||||
|
message.AppendInt32(0);
|
||||||
|
message.AppendInt32(page.Children.Count);
|
||||||
|
|
||||||
|
foreach (var child in page.Children)
|
||||||
|
{
|
||||||
|
SerializeNode(child, message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
using Tiger.Communication.Messages.Interfaces;
|
||||||
|
using Tiger.Communication.Messages.Types;
|
||||||
|
using Tiger.Game.Catalogue;
|
||||||
|
|
||||||
|
namespace Tiger.Communication.Messages.Outgoing.Catalog;
|
||||||
|
|
||||||
|
public class CatalogPageMessageComposer : IMessageComposer
|
||||||
|
{
|
||||||
|
private readonly CataloguePage _page;
|
||||||
|
private readonly int _offerId;
|
||||||
|
private readonly string _mode;
|
||||||
|
|
||||||
|
public CatalogPageMessageComposer(CataloguePage page, int offerId, string mode)
|
||||||
|
{
|
||||||
|
_page = page;
|
||||||
|
_offerId = offerId;
|
||||||
|
_mode = mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OutgoingHeaders Header => OutgoingHeaders.CatalogPageMessageComposer;
|
||||||
|
public void Compose(ServerMessage message)
|
||||||
|
{
|
||||||
|
message.AppendInt32(_page.Id);
|
||||||
|
message.AppendString(_mode);
|
||||||
|
message.AppendString(_page.Layout);
|
||||||
|
message.AppendInt32(_page.Images.Count);
|
||||||
|
|
||||||
|
foreach (var image in _page.Images)
|
||||||
|
{
|
||||||
|
message.AppendString(image);
|
||||||
|
}
|
||||||
|
|
||||||
|
message.AppendInt32(_page.Texts.Count);
|
||||||
|
|
||||||
|
foreach (var text in _page.Texts)
|
||||||
|
{
|
||||||
|
message.AppendString(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
message.AppendInt32(0);
|
||||||
|
message.AppendInt32(_offerId);
|
||||||
|
message.AppendBoolean(_page.SeasonalCurrency);
|
||||||
|
}
|
||||||
|
}
|
|
@ -55,7 +55,7 @@ public enum OutgoingHeaders
|
||||||
CarryObjectMessageComposer = 1474,
|
CarryObjectMessageComposer = 1474,
|
||||||
CatalogPageExpirationComposer = 2668,
|
CatalogPageExpirationComposer = 2668,
|
||||||
CatalogPageMessageComposer = 804,
|
CatalogPageMessageComposer = 804,
|
||||||
CatalogPagesListComposer = 1032,
|
CatalogIndexMessageComposer = 1032,
|
||||||
CatalogPageWithEarliestExpiryMessageComposer = 2515,
|
CatalogPageWithEarliestExpiryMessageComposer = 2515,
|
||||||
CatalogPublishedMessageComposer = 1866,
|
CatalogPublishedMessageComposer = 1866,
|
||||||
CategoriesWithVisitorCountComposer = 1455,
|
CategoriesWithVisitorCountComposer = 1455,
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Tiger.Storage;
|
||||||
|
|
||||||
|
namespace Tiger.Game.Catalogue;
|
||||||
|
|
||||||
|
public class CatalogueManager : ICatalogueManager
|
||||||
|
{
|
||||||
|
private readonly IRepository<CataloguePage> _pagesRepository;
|
||||||
|
private readonly ILogger<ICatalogueManager> _logger;
|
||||||
|
|
||||||
|
public IDictionary<int, CataloguePage> Pages { get; private set; }
|
||||||
|
|
||||||
|
public CatalogueManager(IRepository<CataloguePage> pagesRepository, ILogger<ICatalogueManager> logger)
|
||||||
|
{
|
||||||
|
_pagesRepository = pagesRepository;
|
||||||
|
_logger = logger;
|
||||||
|
Pages = new Dictionary<int, CataloguePage>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task LoadPagesAsync()
|
||||||
|
{
|
||||||
|
Pages = (await _pagesRepository.FindByAsync()).ToDictionary(p => p.Id, p => p);
|
||||||
|
|
||||||
|
_logger.LogInformation("Loaded {Count} catalogue pages", Pages.Count);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
namespace Tiger.Game.Catalogue;
|
||||||
|
|
||||||
|
public class CataloguePage
|
||||||
|
{
|
||||||
|
public virtual int Id { get; set; }
|
||||||
|
public virtual string Name { get; set; } = null!;
|
||||||
|
public virtual string InternalName { get; set; } = null!;
|
||||||
|
public virtual string Layout { get; set; } = null!;
|
||||||
|
public virtual bool Visible { get; set; }
|
||||||
|
public virtual bool Enabled { get; set; }
|
||||||
|
public virtual int Icon { get; set; }
|
||||||
|
public virtual int MinRank { get; set; }
|
||||||
|
public virtual CataloguePage? Parent { get; set; }
|
||||||
|
public virtual IList<CataloguePage> Children { get; set; } = new List<CataloguePage>();
|
||||||
|
public virtual IList<string> Images { get; set; } = new List<string>();
|
||||||
|
public virtual IList<string> Texts { get; set; } = new List<string>();
|
||||||
|
public virtual bool SeasonalCurrency { get; set; }
|
||||||
|
public virtual IList<string> Modes { get; set; } = new List<string>();
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
using FluentNHibernate.Mapping;
|
||||||
|
using Tiger.Storage;
|
||||||
|
|
||||||
|
namespace Tiger.Game.Catalogue;
|
||||||
|
|
||||||
|
public class CataloguePageMap : ClassMap<CataloguePage>
|
||||||
|
{
|
||||||
|
public CataloguePageMap()
|
||||||
|
{
|
||||||
|
Table("catalogue_pages");
|
||||||
|
LazyLoad();
|
||||||
|
Id(c => c.Id).Column("id").GeneratedBy.Identity();
|
||||||
|
Map(c => c.Name).Column("name").Not.Nullable();
|
||||||
|
Map(c => c.InternalName).Column("internal_name").Not.Nullable();
|
||||||
|
Map(c => c.Layout).Column("layout").Not.Nullable();
|
||||||
|
Map(c => c.Visible).Column("visible").Not.Nullable();
|
||||||
|
Map(c => c.Enabled).Column("enabled").Not.Nullable();
|
||||||
|
Map(c => c.Icon).Column("icon").Not.Nullable();
|
||||||
|
Map(c => c.MinRank).Column("min_rank").Not.Nullable();
|
||||||
|
References(x => x.Parent).Column("parent_id").Nullable();
|
||||||
|
HasMany(x => x.Children).KeyColumn("parent_id").Inverse().Cascade.AllDeleteOrphan();
|
||||||
|
Map(c => c.Images).CustomType<StringListTypeConverter>();
|
||||||
|
Map(c => c.Texts).CustomType<StringListTypeConverter>();
|
||||||
|
Map(c => c.SeasonalCurrency).Column("seasonal_currency").Not.Nullable();
|
||||||
|
Map(c => c.Modes).CustomType<StringListTypeConverter>();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
namespace Tiger.Game.Catalogue;
|
||||||
|
|
||||||
|
public interface ICatalogueManager
|
||||||
|
{
|
||||||
|
public IDictionary<int, CataloguePage> Pages { get; }
|
||||||
|
Task LoadPagesAsync();
|
||||||
|
}
|
|
@ -3,6 +3,7 @@ using Microsoft.Extensions.Configuration.Yaml;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Tiger.Communication.Messages;
|
using Tiger.Communication.Messages;
|
||||||
|
using Tiger.Game.Catalogue;
|
||||||
using Tiger.Game.Habbos;
|
using Tiger.Game.Habbos;
|
||||||
using Tiger.Game.Settings;
|
using Tiger.Game.Settings;
|
||||||
using Tiger.Networking.Game;
|
using Tiger.Networking.Game;
|
||||||
|
@ -33,11 +34,13 @@ collection.AddSingleton<INhSessionFactory, NhSessionFactory>();
|
||||||
collection.AddScoped(serviceProvider => serviceProvider.GetRequiredService<INhSessionFactory>().OpenSession());
|
collection.AddScoped(serviceProvider => serviceProvider.GetRequiredService<INhSessionFactory>().OpenSession());
|
||||||
collection.AddScoped(typeof(IRepository<>), typeof(Repository<>));
|
collection.AddScoped(typeof(IRepository<>), typeof(Repository<>));
|
||||||
collection.AddSingleton<ISettingManager, SettingManager>();
|
collection.AddSingleton<ISettingManager, SettingManager>();
|
||||||
|
collection.AddSingleton<ICatalogueManager, CatalogueManager>();
|
||||||
collection.RegisterMessageEvents();
|
collection.RegisterMessageEvents();
|
||||||
|
|
||||||
var provider = collection.BuildServiceProvider();
|
var provider = collection.BuildServiceProvider();
|
||||||
|
|
||||||
await provider.GetRequiredService<ISettingManager>().ReloadSettingsAsync();
|
await provider.GetRequiredService<ISettingManager>().ReloadSettingsAsync();
|
||||||
|
await provider.GetRequiredService<ICatalogueManager>().LoadPagesAsync();
|
||||||
|
|
||||||
provider.GetRequiredService<IWebSocketServer>().Start($"http://{configuration["Network:Game:Ip"]}:{configuration["Network:Game:Port"]}/");
|
provider.GetRequiredService<IWebSocketServer>().Start($"http://{configuration["Network:Game:Ip"]}:{configuration["Network:Game:Port"]}/");
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,9 @@ public interface IRepository<T>
|
||||||
{
|
{
|
||||||
Task<T?> FindAsync(object id);
|
Task<T?> FindAsync(object id);
|
||||||
Task SaveAsync(T entity);
|
Task SaveAsync(T entity);
|
||||||
|
Task SaveManyAsync(params T[] entities);
|
||||||
|
Task SaveManyAsync(IEnumerable<T> entities);
|
||||||
|
// Task FlushAsync();
|
||||||
Task<IEnumerable<T>> FindByAsync(Expression<Func<T, bool>>? expression = null);
|
Task<IEnumerable<T>> FindByAsync(Expression<Func<T, bool>>? expression = null);
|
||||||
Task<T?> FindOneByAsync(Expression<Func<T, bool>> expression);
|
Task<T?> FindOneByAsync(Expression<Func<T, bool>> expression);
|
||||||
}
|
}
|
|
@ -24,6 +24,26 @@ public class Repository<T> : IRepository<T> where T : class
|
||||||
await _session.FlushAsync();
|
await _session.FlushAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task SaveManyAsync(params T[] entities)
|
||||||
|
{
|
||||||
|
foreach (var entity in entities)
|
||||||
|
{
|
||||||
|
await _session.SaveOrUpdateAsync(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
await _session.FlushAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task SaveManyAsync(IEnumerable<T> entities)
|
||||||
|
{
|
||||||
|
foreach (var entity in entities)
|
||||||
|
{
|
||||||
|
await _session.SaveOrUpdateAsync(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
await _session.FlushAsync();
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<IEnumerable<T>> FindByAsync(Expression<Func<T, bool>>? expression)
|
public async Task<IEnumerable<T>> FindByAsync(Expression<Func<T, bool>>? expression)
|
||||||
{
|
{
|
||||||
var query = _session.Query<T>();
|
var query = _session.Query<T>();
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
using System.Data;
|
||||||
|
using System.Data.Common;
|
||||||
|
using System.Text.Json;
|
||||||
|
using NHibernate.Engine;
|
||||||
|
using NHibernate.SqlTypes;
|
||||||
|
using NHibernate.UserTypes;
|
||||||
|
|
||||||
|
namespace Tiger.Storage;
|
||||||
|
|
||||||
|
public class StringListTypeConverter : IUserType
|
||||||
|
{
|
||||||
|
public new bool Equals(object x, object y)
|
||||||
|
{
|
||||||
|
return object.Equals(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetHashCode(object x)
|
||||||
|
{
|
||||||
|
return x.GetHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public object NullSafeGet(DbDataReader rs, string[] names, ISessionImplementor session, object owner)
|
||||||
|
{
|
||||||
|
var r = rs[names[0]];
|
||||||
|
if (r == DBNull.Value) return null!;
|
||||||
|
var strList = JsonSerializer.Deserialize<List<string>>(r.ToString() ?? "") ?? new List<string>();
|
||||||
|
return strList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void NullSafeSet(DbCommand cmd, object value, int index, ISessionImplementor session)
|
||||||
|
{
|
||||||
|
if (value == null!)
|
||||||
|
{
|
||||||
|
((IDataParameter)cmd.Parameters[index]).Value = DBNull.Value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var strList = (List<string>)value;
|
||||||
|
var strValue = JsonSerializer.Serialize(strList);
|
||||||
|
((IDataParameter)cmd.Parameters[index]).Value = strValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public object DeepCopy(object value)
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public object Replace(object original, object target, object owner)
|
||||||
|
{
|
||||||
|
return original;
|
||||||
|
}
|
||||||
|
|
||||||
|
public object Assemble(object cached, object owner)
|
||||||
|
{
|
||||||
|
return cached;
|
||||||
|
}
|
||||||
|
|
||||||
|
public object Disassemble(object value)
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SqlType[] SqlTypes => new SqlType[] { SqlTypeFactory.GetString(8000) };
|
||||||
|
public Type ReturnedType => typeof(List<string>);
|
||||||
|
public bool IsMutable => true;
|
||||||
|
}
|
|
@ -23,7 +23,7 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Update="appsettings.yaml">
|
<None Update="appsettings.yaml">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
Database:
|
Database:
|
||||||
Host: 127.0.0.1
|
Host: localhost
|
||||||
Port: 3306
|
Port: 3306
|
||||||
Username: root
|
Username: tiger
|
||||||
Password: 123
|
Password: 123
|
||||||
Database: tiger_db
|
Database: tiger_db
|
||||||
MinPool: 5
|
MinPool: 5
|
||||||
|
|
Loading…
Reference in New Issue