baseline: OpenMU upstream b5a0961 (fresh source)

This commit is contained in:
Acentech Dev
2026-07-14 19:00:35 +03:00
parent 450402e47d
commit 36fc125d5c
11968 changed files with 748705 additions and 0 deletions

View File

@@ -0,0 +1,42 @@
// <copyright file="DropGeneratorBenchmarks.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>
using MUnique.OpenMU.DataModel.Configuration;
using MUnique.OpenMU.GameLogic.Benchmarks.Helpers;
namespace MUnique.OpenMU.GameLogic.Benchmarks;
/// <summary>
/// Benchmarks for the <see cref="DefaultDropGenerator"/>.
/// </summary>
[MemoryDiagnoser]
[ThreadingDiagnoser]
[InvocationCount(100)]
public class DropGeneratorBenchmarks
{
private DefaultDropGenerator _generator = null!;
private MonsterDefinition _monster = null!;
private Player _player = null!;
/// <summary>
/// Global setup for the benchmarks.
/// </summary>
[GlobalSetup]
public async Task Setup()
{
var config = GameConfigurationTestHelper.Create();
var randomizer = RandomizerTestHelper.Create();
_generator = new DefaultDropGenerator(config, randomizer);
_monster = MonsterTestHelper.Create(10, 1);
_player = await PlayerTestHelper.CreatePlayerAsync();
}
/// <summary>
/// Benchmarks the drop generation with a single player and monster.
/// </summary>
/// <returns>A value task.</returns>
[Benchmark]
public async ValueTask GenerateItemDropsAsync()
=> await _generator.GenerateItemDropsAsync(_monster, 1000, _player);
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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();
}
}
}

View File

@@ -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;
}
}

View File

@@ -0,0 +1,49 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<WarningsAsErrors>nullable;CS4014;VSTHRD110;VSTHRD100</WarningsAsErrors>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<ApplicationIcon />
<OutputType>Exe</OutputType>
<StartupObject />
<AssemblyName>MUnique.OpenMU.GameLogic.Benchmarks</AssemblyName>
<PlatformTarget>AnyCPU</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<OutputPath>bin\Debug\</OutputPath>
<DocumentationFile>bin\Debug\MUnique.OpenMU.GameLogic.Benchmarks.xml</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<OutputPath>bin\Release\</OutputPath>
<DocumentationFile>bin\Release\MUnique.OpenMU.GameLogic.Benchmarks.xml</DocumentationFile>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\..\src\SharedAssemblyInfo.cs" Link="Properties\SharedAssemblyInfo.cs" />
<Compile Include="..\..\src\SharedGlobalUsings.cs" Link="SharedGlobalUsings.cs" />
</ItemGroup>
<ItemGroup>
<None Include="..\..\src\.editorconfig" Link=".editorconfig" />
</ItemGroup>
<ItemGroup>
<AdditionalFiles Include="..\..\src\stylecop.json" Link="stylecop.json" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="BenchmarkDotNet" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" />
<PackageReference Include="Moq" />
<PackageReference Include="Nito.AsyncEx.Coordination" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\GameLogic\MUnique.OpenMU.GameLogic.csproj" />
<ProjectReference Include="..\..\src\Persistence\InMemory\MUnique.OpenMU.Persistence.InMemory.csproj" />
<ProjectReference Include="..\..\src\PlugIns\MUnique.OpenMU.PlugIns.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,24 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27703.2047
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MUnique.OpenMU.GameLogic.Benchmarks", "MUnique.OpenMU.GameLogic.Benchmarks.csproj", "{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {B2012905-0E9A-4059-9E4D-AD78A91273F2}
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,100 @@
// <copyright file="PartyBenchmarks.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;
using Microsoft.Extensions.Logging.Abstractions;
using Moq;
using MUnique.OpenMU.AttributeSystem;
using MUnique.OpenMU.GameLogic;
using MUnique.OpenMU.GameLogic.Attributes;
using MUnique.OpenMU.GameLogic.Benchmarks.Helpers;
/// <summary>
/// Benchmarks for <see cref="Party"/> class methods related to XP distribution and item drops.
/// </summary>
[MemoryDiagnoser]
[ThreadingDiagnoser]
[InvocationCount(100)]
public class PartyBenchmarks
{
private Party _party = null!;
private Player _killer = null!;
private IAttackable _killedObject = null!;
private List<Player> _players = null!;
/// <summary>
/// Sets up the benchmark by creating a party with 5 players.
/// </summary>
[GlobalSetup]
public async Task Setup()
{
var partyManager = new PartyManager(5, new NullLogger<Party>());
_party = new Party(partyManager, 5, new NullLogger<Party>());
_players = new List<Player>();
for (int i = 0; i < 5; i++)
{
var player = await PlayerTestHelper.CreatePlayerAsync();
await player.PlayerState.TryAdvanceToAsync(PlayerState.EnteredWorld).ConfigureAwait(false);
if (player.Attributes is { } attrs)
{
attrs[Stats.Level] = (short)(100 + i);
}
_players.Add(player);
await _party.AddAsync(player).ConfigureAwait(false);
}
_killer = _players[0];
foreach (var player in _players)
{
_killer.Observers.Add(player);
}
_killedObject = CreateMockAttackable(50);
}
/// <summary>
/// Benchmarks the <see cref="Party.DistributeExperienceAfterKillAsync"/> method.
/// </summary>
[Benchmark]
public async ValueTask DistributeExperienceAfterKillAsync()
{
await _party.DistributeExperienceAfterKillAsync(_killedObject, _killer);
}
/// <summary>
/// Benchmarks the <see cref="Party.DistributeMoneyAfterKillAsync"/> method.
/// </summary>
[Benchmark]
public async ValueTask DistributeMoneyAfterKillAsync()
{
await _party.DistributeMoneyAfterKillAsync(_killedObject, _killer, 10000);
}
/// <summary>
/// Benchmarks the <see cref="Party.GetQuestDropItemGroupsAsync"/> method.
/// </summary>
[Benchmark]
public async ValueTask GetQuestDropItemGroupsAsync()
{
await _party.GetQuestDropItemGroupsAsync(_killer);
}
private static IAttackable CreateMockAttackable(float level)
{
var attributes = new Mock<IAttributeSystem>();
attributes.Setup(a => a[Stats.Level]).Returns(level);
var result = new Mock<IAttackable>();
result.SetupAllProperties();
result.SetupGet(a => a.Attributes).Returns(attributes.Object);
GameMap? nullMap = null;
result.SetupGet(a => a.CurrentMap).Returns(nullMap);
return result.Object;
}
}

View File

@@ -0,0 +1,29 @@
// <copyright file="Program.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>
#pragma warning disable SA1200
global using BenchmarkDotNet.Attributes;
global using BenchmarkDotNet.Jobs;
global using BenchmarkDotNet.Running;
#pragma warning restore SA1200
namespace MUnique.OpenMU.GameLogic.Benchmarks;
/// <summary>
/// The class of the entry point of the benchmark.
/// </summary>
public static class Program
{
/// <summary>
/// The entry point of the benchmark.
/// </summary>
/// <param name="args">The arguments.</param>
public static void Main(string[] args)
{
BenchmarkRunner.Run<DropGeneratorBenchmarks>();
BenchmarkRunner.Run<PartyBenchmarks>();
}
}