baseline: OpenMU upstream b5a0961 (fresh source)
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
// <copyright file="DropItemGroupExtensions.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.Benchmarks.Helpers;
|
||||
|
||||
using Moq;
|
||||
using MUnique.OpenMU.DataModel.Configuration;
|
||||
using MUnique.OpenMU.DataModel.Configuration.Items;
|
||||
|
||||
/// <summary>
|
||||
/// Extensions for <see cref="DropItemGroup"/>.
|
||||
/// </summary>
|
||||
public static class DropItemGroupExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds the basic drop item groups.
|
||||
/// </summary>
|
||||
/// <param name="itemGroups">The item groups.</param>
|
||||
public static void AddBasicDropItemGroups(this ICollection<DropItemGroup> itemGroups)
|
||||
{
|
||||
itemGroups.Add(1, SpecialItemType.RandomItem, true);
|
||||
itemGroups.Add(1000, SpecialItemType.Excellent, true);
|
||||
itemGroups.Add(3000, SpecialItemType.Money, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new drop item group with the specified data.
|
||||
/// </summary>
|
||||
/// <param name="list">The list.</param>
|
||||
/// <param name="chance">The chance.</param>
|
||||
/// <param name="itemType">Type of the item.</param>
|
||||
/// <param name="addItem">if set to <c>true</c>, it adds a test item to the possible item list.</param>
|
||||
/// <returns>The drop item group which has been added to the list.</returns>
|
||||
public static DropItemGroup Add(this ICollection<DropItemGroup> list, int chance, SpecialItemType itemType, bool addItem)
|
||||
{
|
||||
var dropItemGroup = new Mock<DropItemGroup>();
|
||||
dropItemGroup.SetupAllProperties();
|
||||
dropItemGroup.Object.Chance = chance / 10000.0;
|
||||
dropItemGroup.Object.ItemType = itemType;
|
||||
var itemList = new List<ItemDefinition>();
|
||||
dropItemGroup.Setup(g => g.PossibleItems).Returns(itemList);
|
||||
if (addItem)
|
||||
{
|
||||
var itemDefinition = new Mock<ItemDefinition>();
|
||||
itemDefinition.SetupAllProperties();
|
||||
itemDefinition.Object.DropsFromMonsters = true;
|
||||
itemDefinition.Setup(d => d.PossibleItemSetGroups).Returns(new List<ItemSetGroup>());
|
||||
itemDefinition.Setup(d => d.PossibleItemOptions).Returns(new List<ItemOptionDefinition>());
|
||||
itemList.Add(itemDefinition.Object);
|
||||
}
|
||||
|
||||
list.Add(dropItemGroup.Object);
|
||||
|
||||
return dropItemGroup.Object;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
// <copyright file="GameConfigurationTestHelper.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.Benchmarks.Helpers;
|
||||
|
||||
using Moq;
|
||||
using MUnique.OpenMU.DataModel.Configuration;
|
||||
using MUnique.OpenMU.DataModel.Configuration.Items;
|
||||
using MUnique.OpenMU.GameLogic.Attributes;
|
||||
|
||||
/// <summary>
|
||||
/// Helper for creating test game configurations.
|
||||
/// </summary>
|
||||
public static class GameConfigurationTestHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a mock game configuration for drop generation testing.
|
||||
/// </summary>
|
||||
/// <returns>A mock game configuration.</returns>
|
||||
public static GameConfiguration Create()
|
||||
{
|
||||
var gameConfiguration = new Mock<GameConfiguration>();
|
||||
gameConfiguration.SetupAllProperties();
|
||||
gameConfiguration.Object.ExcellentItemDropLevelDelta = 50;
|
||||
gameConfiguration.Object.MaximumItemOptionLevelDrop = 3;
|
||||
|
||||
var items = CreateItems();
|
||||
gameConfiguration.Setup(c => c.Items).Returns(items);
|
||||
return gameConfiguration.Object;
|
||||
}
|
||||
|
||||
private static IList<ItemDefinition> CreateItems()
|
||||
{
|
||||
var items = new List<ItemDefinition>();
|
||||
var random = new Random(42);
|
||||
|
||||
for (byte dropLevel = 0; dropLevel <= 200; dropLevel++)
|
||||
{
|
||||
int itemsAtThisLevel = random.Next(5, 20);
|
||||
for (int i = 0; i < itemsAtThisLevel; i++)
|
||||
{
|
||||
var item = new Mock<ItemDefinition>();
|
||||
item.SetupAllProperties();
|
||||
item.Setup(d => d.PossibleItemSetGroups).Returns(new List<ItemSetGroup>());
|
||||
item.Setup(d => d.PossibleItemOptions).Returns(CreateItemOptions(dropLevel));
|
||||
item.Setup(d => d.Requirements).Returns(new List<AttributeRequirement>());
|
||||
item.Setup(d => d.BasePowerUpAttributes).Returns(new List<ItemBasePowerUpDefinition>());
|
||||
item.Setup(d => d.DropItems).Returns(new List<ItemDropItemGroup>());
|
||||
item.Setup(d => d.QualifiedCharacters).Returns(new List<CharacterClass>());
|
||||
|
||||
item.Object.DropsFromMonsters = true;
|
||||
item.Object.DropLevel = dropLevel;
|
||||
item.Object.Width = (byte)(i % 4 + 1);
|
||||
item.Object.Height = (byte)(i % 4 + 1);
|
||||
item.Object.MaximumItemLevel = 13;
|
||||
item.Object.MaximumSockets = dropLevel > 100 ? 5 : 0;
|
||||
item.Object.Group = (byte)(dropLevel % 16);
|
||||
item.Object.Number = (short)(i % 256);
|
||||
|
||||
items.Add(item.Object);
|
||||
}
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
private static IList<ItemOptionDefinition> CreateItemOptions(byte dropLevel)
|
||||
{
|
||||
var options = new List<ItemOptionDefinition>();
|
||||
|
||||
if (dropLevel > 30)
|
||||
{
|
||||
var excellentOption = new Mock<ItemOptionDefinition>();
|
||||
excellentOption.SetupAllProperties();
|
||||
excellentOption.Setup(o => o.PossibleOptions).Returns(CreateExcellentOptions());
|
||||
excellentOption.Object.AddsRandomly = true;
|
||||
excellentOption.Object.AddChance = 100;
|
||||
excellentOption.Object.MaximumOptionsPerItem = 6;
|
||||
options.Add(excellentOption.Object);
|
||||
}
|
||||
|
||||
if (dropLevel > 50)
|
||||
{
|
||||
var luckOption = new Mock<ItemOptionDefinition>();
|
||||
luckOption.SetupAllProperties();
|
||||
luckOption.Setup(o => o.PossibleOptions).Returns(new List<IncreasableItemOption>());
|
||||
luckOption.Object.AddsRandomly = true;
|
||||
luckOption.Object.AddChance = 100;
|
||||
luckOption.Object.MaximumOptionsPerItem = 1;
|
||||
options.Add(luckOption.Object);
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
private static IList<IncreasableItemOption> CreateExcellentOptions()
|
||||
{
|
||||
var options = new List<IncreasableItemOption>();
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
var option = new Mock<IncreasableItemOption>();
|
||||
option.SetupAllProperties();
|
||||
option.Setup(o => o.LevelDependentOptions).Returns(new List<ItemOptionOfLevel>());
|
||||
options.Add(option.Object);
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
// <copyright file="MockViewPlugInContainer.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.Benchmarks.Helpers;
|
||||
|
||||
using Moq;
|
||||
using MUnique.OpenMU.GameLogic.Views;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// A view plugin container which automatically create mocks for requested view plugins.
|
||||
/// </summary>
|
||||
public class MockViewPlugInContainer : ICustomPlugInContainer<IViewPlugIn>
|
||||
{
|
||||
private readonly Dictionary<Type, IViewPlugIn> _mocks = new();
|
||||
|
||||
/// <inheritdoc />
|
||||
public T GetPlugIn<T>()
|
||||
where T : class, IViewPlugIn
|
||||
{
|
||||
if (!this._mocks.TryGetValue(typeof(T), out var mock))
|
||||
{
|
||||
mock = new Mock<T>().Object;
|
||||
this._mocks.Add(typeof(T), mock);
|
||||
}
|
||||
|
||||
return (T)mock;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
// <copyright file="MonsterTestHelper.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.Benchmarks.Helpers;
|
||||
|
||||
using Moq;
|
||||
using MUnique.OpenMU.DataModel.Configuration;
|
||||
using MUnique.OpenMU.DataModel.Configuration.Items;
|
||||
using MUnique.OpenMU.GameLogic.Attributes;
|
||||
|
||||
/// <summary>
|
||||
/// Helper for creating test monsters.
|
||||
/// </summary>
|
||||
public static class MonsterTestHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a mock monster definition.
|
||||
/// </summary>
|
||||
/// <param name="numberOfDrops">The maximum number of item drops.</param>
|
||||
/// <param name="level">The monster level.</param>
|
||||
/// <returns>A mock monster definition.</returns>
|
||||
public static MonsterDefinition Create(int numberOfDrops, byte level)
|
||||
{
|
||||
var monster = new Mock<MonsterDefinition>();
|
||||
monster.SetupAllProperties();
|
||||
monster.Setup(m => m.DropItemGroups).Returns(new List<DropItemGroup>());
|
||||
monster.Setup(m => m.Attributes).Returns(new List<MonsterAttribute>());
|
||||
monster.Object.NumberOfMaximumItemDrops = numberOfDrops;
|
||||
monster.Object.Attributes.Add(new MonsterAttribute { AttributeDefinition = Stats.Level, Value = level });
|
||||
|
||||
monster.Object.DropItemGroups.AddBasicDropItemGroups();
|
||||
|
||||
return monster.Object;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
// <copyright file="PlayerTestHelper.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.Benchmarks.Helpers;
|
||||
|
||||
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.Attributes;
|
||||
|
||||
using MUnique.OpenMU.GameLogic.Views;
|
||||
using MUnique.OpenMU.Persistence.InMemory;
|
||||
using MUnique.OpenMU.PlugIns;
|
||||
|
||||
/// <summary>
|
||||
/// Helper functions to create test players.
|
||||
/// </summary>
|
||||
public static class PlayerTestHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a test player with a new in-memory game context.
|
||||
/// </summary>
|
||||
/// <returns>The test player.</returns>
|
||||
public static async ValueTask<Player> CreatePlayerAsync()
|
||||
{
|
||||
var gameConfig = new Mock<GameConfiguration>();
|
||||
gameConfig.SetupAllProperties();
|
||||
gameConfig.Setup(c => c.Maps).Returns(new List<GameMapDefinition>());
|
||||
gameConfig.Setup(c => c.Items).Returns(new List<ItemDefinition>());
|
||||
gameConfig.Setup(c => c.Skills).Returns(new List<Skill>());
|
||||
gameConfig.Setup(c => c.PlugInConfigurations).Returns(new List<PlugInConfiguration>());
|
||||
gameConfig.Setup(c => c.CharacterClasses).Returns(new List<CharacterClass>());
|
||||
gameConfig.Setup(c => c.GlobalAttributeCombinations).Returns(new List<AttributeRelationship>());
|
||||
gameConfig.Setup(c => c.GlobalBaseAttributeValues).Returns(new List<ConstValueAttribute>
|
||||
{
|
||||
new(1, Stats.MoneyAmountRate),
|
||||
});
|
||||
var map = new Mock<GameMapDefinition>();
|
||||
map.SetupAllProperties();
|
||||
map.Setup(m => m.DropItemGroups).Returns(new List<DropItemGroup>());
|
||||
map.Setup(m => m.MonsterSpawns).Returns(new List<MonsterSpawnArea>());
|
||||
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<MapInitializer>(), 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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a test player with the specified game context.
|
||||
/// </summary>
|
||||
/// <param name="gameContext">The game context.</param>
|
||||
/// <returns>The test player.</returns>
|
||||
public static async ValueTask<Player> CreatePlayerAsync(IGameContext gameContext)
|
||||
{
|
||||
var characterMock = new Mock<Character>();
|
||||
characterMock.SetupAllProperties();
|
||||
characterMock.Setup(c => c.LearnedSkills).Returns(new List<SkillEntry>());
|
||||
characterMock.Setup(c => c.Attributes).Returns(new List<StatAttribute>());
|
||||
characterMock.Setup(c => c.DropItemGroups).Returns(new List<DropItemGroup>());
|
||||
|
||||
var inventoryMock = new Mock<ItemStorage>();
|
||||
inventoryMock.SetupAllProperties();
|
||||
inventoryMock.Setup(i => i.Items).Returns(new List<Item>());
|
||||
|
||||
var character = characterMock.Object;
|
||||
character.Inventory = inventoryMock.Object;
|
||||
character.CurrentMap = gameContext.Configuration.Maps.FirstOrDefault(m => m.Number == 0);
|
||||
var characterClassMock = new Mock<CharacterClass>();
|
||||
characterClassMock.Setup(c => c.StatAttributes).Returns(
|
||||
new List<StatAttributeDefinition>
|
||||
{
|
||||
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<AttributeRelationship>
|
||||
{
|
||||
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<ConstValueAttribute>
|
||||
{
|
||||
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<Account>();
|
||||
accountMock.Setup(mock => mock.Attributes).Returns(new List<StatAttribute>());
|
||||
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);
|
||||
|
||||
player.Attributes!.AddElement(new SimpleElement(200.0f, AggregateType.AddRaw), Stats.TotalLevel);
|
||||
|
||||
return player;
|
||||
}
|
||||
|
||||
private class TestPlayer : Player
|
||||
{
|
||||
public TestPlayer(IGameContext gameContext)
|
||||
: base(gameContext)
|
||||
{
|
||||
}
|
||||
|
||||
protected override ICustomPlugInContainer<IViewPlugIn> CreateViewPlugInContainer()
|
||||
{
|
||||
return new MockViewPlugInContainer();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
// <copyright file="RandomizerTestHelper.cs" company="MUnique">
|
||||
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
|
||||
// </copyright>
|
||||
|
||||
namespace MUnique.OpenMU.GameLogic.Benchmarks.Helpers;
|
||||
|
||||
using Moq;
|
||||
using MUnique.OpenMU.AttributeSystem;
|
||||
|
||||
/// <summary>
|
||||
/// Helper for creating test randomizers.
|
||||
/// </summary>
|
||||
public static class RandomizerTestHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a mock randomizer with random behavior.
|
||||
/// </summary>
|
||||
/// <returns>A mock randomizer.</returns>
|
||||
public static IRandomizer Create()
|
||||
{
|
||||
var randomizer = new Mock<IRandomizer>();
|
||||
var random = new Random();
|
||||
randomizer.Setup(r => r.NextInt(It.IsAny<int>(), It.IsAny<int>())).Returns((int min, int max) => random.Next(min, max));
|
||||
randomizer.Setup(r => r.NextDouble()).Returns(() => random.NextDouble());
|
||||
randomizer.Setup(r => r.NextRandomBool(It.IsAny<int>())).Returns((int chance) => random.Next(100) < chance);
|
||||
return randomizer.Object;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user