//
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
//
namespace MUnique.OpenMU.Tests;
using Microsoft.Extensions.Logging.Abstractions;
using Moq;
using MUnique.OpenMU.AttributeSystem;
using MUnique.OpenMU.DataModel.Configuration;
using MUnique.OpenMU.DataModel.Configuration.Items;
using MUnique.OpenMU.DataModel.Entities;
using MUnique.OpenMU.GameLogic;
using MUnique.OpenMU.GameLogic.Attributes;
using MUnique.OpenMU.GameLogic.Offline;
using MUnique.OpenMU.GameLogic.Views;
using MUnique.OpenMU.Persistence.InMemory;
using MUnique.OpenMU.PlugIns;
///
/// Helper functions to create test players.
///
public static class PlayerTestHelper
{
///
/// Gets a test player with a new in-memory game context.
///
/// The test player.
public static async ValueTask CreatePlayerAsync()
{
var gameConfig = new Mock();
gameConfig.SetupAllProperties();
gameConfig.Setup(c => c.Maps).Returns(new List());
gameConfig.Setup(c => c.Items).Returns(new List());
gameConfig.Setup(c => c.Skills).Returns(new List());
gameConfig.Setup(c => c.PlugInConfigurations).Returns(new List());
gameConfig.Setup(c => c.CharacterClasses).Returns(new List());
gameConfig.Setup(c => c.GlobalAttributeCombinations).Returns(new List());
gameConfig.Setup(c => c.GlobalBaseAttributeValues).Returns(new List
{
new(1, Stats.MoneyAmountRate),
});
var map = new Mock();
map.SetupAllProperties();
map.Setup(m => m.DropItemGroups).Returns(new List());
map.Setup(m => m.MonsterSpawns).Returns(new List());
map.Object.TerrainData = new byte[ushort.MaxValue + 3];
gameConfig.Object.RecoveryInterval = int.MaxValue;
gameConfig.Object.Maps.Add(map.Object);
var mapInitializer = new MapInitializer(gameConfig.Object, new NullLogger(), NullDropGenerator.Instance, null);
var gameContext = new GameContext(gameConfig.Object, new InMemoryPersistenceContextProvider(), mapInitializer, new NullLoggerFactory(), new PlugInManager(null, new NullLoggerFactory(), null, null), NullDropGenerator.Instance, new ConfigurationChangeMediator());
mapInitializer.PlugInManager = gameContext.PlugInManager;
mapInitializer.PathFinderPool = gameContext.PathFinderPool;
return await CreatePlayerAsync(gameContext).ConfigureAwait(false);
}
///
/// Gets a test player with the specified game context.
///
/// The game context.
/// The test player.
public static async ValueTask CreatePlayerAsync(IGameContext gameContext)
{
var characterMock = new Mock();
characterMock.SetupAllProperties();
characterMock.Setup(c => c.LearnedSkills).Returns(new List());
characterMock.Setup(c => c.Attributes).Returns(new List());
characterMock.Setup(c => c.DropItemGroups).Returns(new List());
var inventoryMock = new Mock();
inventoryMock.SetupAllProperties();
inventoryMock.Setup(i => i.Items).Returns(new List- ());
var character = characterMock.Object;
character.Inventory = inventoryMock.Object;
character.CurrentMap = gameContext.Configuration.Maps.FirstOrDefault(m => m.Number == 0);
var characterClassMock = new Mock();
characterClassMock.Setup(c => c.StatAttributes).Returns(
new List
{
new (Stats.Level, 0, false),
new (Stats.BaseStrength, 28, true),
new (Stats.BaseAgility, 20, true),
new (Stats.BaseVitality, 25, true),
new (Stats.BaseEnergy, 10, true),
new (Stats.CurrentHealth, 0, false),
new (Stats.CurrentMana, 0, false),
new (Stats.CurrentShield, 0, false),
new (Stats.Resets, 0, false),
new (Stats.PointsPerReset, 0, false),
});
characterClassMock.Setup(c => c.AttributeCombinations).Returns(new List
{
new (Stats.TotalStrength, 1, Stats.BaseStrength),
new (Stats.TotalAgility, 1, Stats.BaseAgility),
new (Stats.TotalVitality, 1, Stats.BaseVitality),
new (Stats.TotalEnergy, 1, Stats.BaseEnergy),
new (Stats.MaximumAbility, 1, Stats.TotalEnergy),
new (Stats.MaximumAbility, 0.3f, Stats.TotalVitality),
new (Stats.MaximumAbility, 0.2f, Stats.TotalAgility),
new (Stats.MaximumAbility, 0.15f, Stats.TotalStrength),
new (Stats.MaximumShield, 1.2f, Stats.TotalEnergy),
new (Stats.MaximumShield, 1.2f, Stats.TotalVitality),
new (Stats.MaximumShield, 1.2f, Stats.TotalAgility),
new (Stats.MaximumShield, 1.2f, Stats.TotalStrength),
new (Stats.MaximumShield, 0.5f, Stats.DefenseBase),
new (Stats.MaximumMana, 1, Stats.TotalEnergy),
new (Stats.MaximumMana, 0.5f, Stats.Level),
new (Stats.MaximumHealth, 2, Stats.Level),
new (Stats.MaximumHealth, 3, Stats.TotalVitality),
});
characterClassMock.Setup(c => c.BaseAttributeValues).Returns(new List
{
new (10, Stats.MaximumMana),
new (35, Stats.MaximumHealth),
new (2, Stats.SkillMultiplier),
new (2, Stats.AbilityRecoveryMultiplier),
new (1, Stats.DamageReceiveDecrement),
new (1, Stats.AttackDamageIncrease),
});
character.CharacterClass = characterClassMock.Object;
foreach (var attributeDef in character.CharacterClass.StatAttributes)
{
character.Attributes.Add(new StatAttribute(attributeDef.Attribute!, attributeDef.BaseValue));
}
var accountMock = new Mock();
accountMock.Setup(mock => mock.Attributes).Returns(new List());
accountMock.Setup(mock => mock.UnlockedCharacterClasses).Returns(new List());
var player = new TestPlayer(gameContext) { Account = accountMock.Object };
await player.PlayerState.TryAdvanceToAsync(PlayerState.LoginScreen).ConfigureAwait(false);
await player.PlayerState.TryAdvanceToAsync(PlayerState.Authenticated).ConfigureAwait(false);
await player.PlayerState.TryAdvanceToAsync(PlayerState.CharacterSelection).ConfigureAwait(false);
await player.SetSelectedCharacterAsync(character).ConfigureAwait(false);
return player;
}
///
/// Creates an offline player at .
///
/// The game context.
/// The offline player.
public static async ValueTask CreateOfflineLevelingPlayerAsync(IGameContext gameContext)
{
var regularPlayer = await CreatePlayerAsync(gameContext).ConfigureAwait(false);
var offlinePlayer = new OfflinePlayer(gameContext) { Account = regularPlayer.Account };
await offlinePlayer.PlayerState.TryAdvanceToAsync(PlayerState.LoginScreen).ConfigureAwait(false);
await offlinePlayer.PlayerState.TryAdvanceToAsync(PlayerState.Authenticated).ConfigureAwait(false);
await offlinePlayer.PlayerState.TryAdvanceToAsync(PlayerState.CharacterSelection).ConfigureAwait(false);
await offlinePlayer.SetSelectedCharacterAsync(regularPlayer.SelectedCharacter!).ConfigureAwait(false);
return offlinePlayer;
}
private class TestPlayer : Player
{
public TestPlayer(IGameContext gameContext)
: base(gameContext)
{
}
protected override ICustomPlugInContainer CreateViewPlugInContainer()
{
return new MockViewPlugInContainer();
}
}
}