//
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
//
namespace MUnique.OpenMU.Persistence.EntityFramework;
using System.Threading;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using MUnique.OpenMU.Persistence.EntityFramework.Model;
///
/// Persistence context which is used by in-game players.
///
internal class PlayerContext : CachingEntityFrameworkContext, IPlayerContext
{
///
/// Initializes a new instance of the class.
///
/// The context.
/// The repository provider.
/// The logger.
public PlayerContext(DbContext context, IContextAwareRepositoryProvider repositoryProvider, ILogger logger)
: base(context, repositoryProvider, null, logger)
{
}
///
public async ValueTask GetLetterBodyByHeaderIdAsync(Guid headerId, CancellationToken cancellationToken = default)
{
using var context = this.RepositoryProvider.ContextStack.UseContext(this);
if (this.RepositoryProvider.GetRepository() is { } repository)
{
return await repository.GetBodyByHeaderIdAsync(headerId, cancellationToken).ConfigureAwait(false);
}
return null;
}
///
public async ValueTask CanSaveLetterAsync(Interfaces.LetterHeader letterHeader, CancellationToken cancellationToken = default)
{
if (letterHeader is not Model.LetterHeader persistentHeader)
{
return false;
}
persistentHeader.Receiver = await this.Context.Set().FirstOrDefaultAsync(c => c.Name == letterHeader.ReceiverName, cancellationToken).ConfigureAwait(false);
return persistentHeader.Receiver != null;
}
///
public async ValueTask AuthenticateAsync(string loginName, string password, CancellationToken cancellationToken = default)
{
using (this.RepositoryProvider.ContextStack.UseContext(this))
{
if (this.RepositoryProvider.GetRepository() is { } accountRepository)
{
return await accountRepository.AuthenticateAsync(loginName, password, cancellationToken).ConfigureAwait(false);
}
}
return null;
}
///
public async ValueTask GetAccountByLoginNameAsync(string loginName, string password, CancellationToken cancellationToken = default)
{
using (this.RepositoryProvider.ContextStack.UseContext(this))
{
if (this.RepositoryProvider.GetRepository() is { } accountRepository)
{
return await accountRepository.GetAccountByLoginNameAsync(loginName, password, cancellationToken).ConfigureAwait(false);
}
}
return null;
}
///
public async ValueTask GetAccountByLoginNameAsync(string loginName, CancellationToken cancellationToken = default)
{
using (this.RepositoryProvider.ContextStack.UseContext(this))
{
if (this.RepositoryProvider.GetRepository() is { } accountRepository)
{
return await accountRepository.GetAccountByLoginNameAsync(loginName, cancellationToken).ConfigureAwait(false);
}
}
return null;
}
///
public async ValueTask> GetAccountsOrderedByLoginNameAsync(int skip, int count, CancellationToken cancellationToken = default)
{
using (this.RepositoryProvider.ContextStack.UseContext(this))
{
return await this.Context.Set().AsNoTracking().OrderBy(a => a.LoginName).Skip(skip).Take(count).ToListAsync(cancellationToken).ConfigureAwait(false);
}
}
///
public async ValueTask> SearchAccountsAsync(string searchTerm, int skip, int count, CancellationToken cancellationToken = default)
{
using (this.RepositoryProvider.ContextStack.UseContext(this))
{
// Invariant: this one runs in .NET, so it must not depend on the server's locale - in a
// Turkish one, "I".ToLower() is a dotless "ı" and the term would match nothing. The
// ToLower() calls inside the query below are a different matter: they are translated to
// the database's own lower(), which is why they cannot take a culture.
var term = searchTerm.ToLowerInvariant();
return await this.Context.Set().AsNoTracking()
.Where(a => a.LoginName.ToLower().Contains(term)
|| a.RawCharacters.Any(c => c.Name.ToLower().Contains(term)))
.OrderBy(a => a.LoginName)
.Skip(skip)
.Take(count)
.ToListAsync(cancellationToken).ConfigureAwait(false);
}
}
///
public async ValueTask GetAccountByCharacterNameAsync(string characterName, CancellationToken cancellationToken = default)
{
using (this.RepositoryProvider.ContextStack.UseContext(this))
{
if (this.RepositoryProvider.GetRepository() is { } accountRepository)
{
return await accountRepository.GetAccountByCharacterNameAsync(characterName, cancellationToken).ConfigureAwait(false);
}
}
return null;
}
}