refactor(net): own live session composition
Extract reset, selection, entered-world, and route construction behind LiveSessionHost while preserving the sole LiveSessionController authority. Retain partial route and subscription cleanup for retry, and replace the embedded ACE-only shortcut with the exact named-retail unsigned skill formula. Co-authored-by: Codex <codex@openai.com>
This commit is contained in:
parent
18d4b999de
commit
557eb7ef6b
22 changed files with 1430 additions and 236 deletions
112
tests/AcDream.App.Tests/Net/RetailSkillFormulaTests.cs
Normal file
112
tests/AcDream.App.Tests/Net/RetailSkillFormulaTests.cs
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
using AcDream.App.Net;
|
||||
using DatReaderWriter.DBObjs;
|
||||
using DatReaderWriter.Enums;
|
||||
using DatReaderWriter.Types;
|
||||
|
||||
namespace AcDream.App.Tests.Net;
|
||||
|
||||
public sealed class RetailSkillFormulaTests
|
||||
{
|
||||
[Fact]
|
||||
public void ZeroDivisorIsTheOnlyFormulaFailureGate()
|
||||
{
|
||||
SkillFormula invalid = Formula(w: 7, x: 1, y: 1, z: 0);
|
||||
Assert.False(RetailSkillFormula.TryCalculate(invalid, 10u, 20u, out uint invalidResult));
|
||||
Assert.Equal(0u, invalidResult);
|
||||
|
||||
SkillFormula zeroX = Formula(w: 7, x: 0, y: 2, z: 3);
|
||||
Assert.True(RetailSkillFormula.TryCalculate(zeroX, 10u, 4u, out uint validResult));
|
||||
Assert.Equal(5u, validResult);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(9u, 4u, 2u)]
|
||||
[InlineData(10u, 4u, 3u)]
|
||||
[InlineData(11u, 4u, 3u)]
|
||||
[InlineData(12u, 4u, 3u)]
|
||||
public void DivisionRoundsToNearestWithExactHalvesUp(
|
||||
uint numerator,
|
||||
uint divisor,
|
||||
uint expected)
|
||||
{
|
||||
SkillFormula formula = Formula(w: 0, x: 1, y: 0, z: divisor);
|
||||
|
||||
Assert.True(RetailSkillFormula.TryCalculate(
|
||||
formula,
|
||||
numerator,
|
||||
0u,
|
||||
out uint result));
|
||||
Assert.Equal(expected, result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AdditiveWordIsInsideTheNumerator()
|
||||
{
|
||||
SkillFormula formula = Formula(w: 3, x: 1, y: 1, z: 4);
|
||||
|
||||
Assert.True(RetailSkillFormula.TryCalculate(formula, 4u, 2u, out uint result));
|
||||
|
||||
Assert.Equal(2u, result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NumeratorUsesUnsignedThirtyTwoBitWrap()
|
||||
{
|
||||
SkillFormula formula = Formula(w: 1, x: 2, y: 0, z: 2);
|
||||
|
||||
Assert.True(RetailSkillFormula.TryCalculate(
|
||||
formula,
|
||||
uint.MaxValue,
|
||||
0u,
|
||||
out uint result));
|
||||
|
||||
Assert.Equal(0x80000000u, result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SignedDatStorageIsReinterpretedAsRetailUnsignedWords()
|
||||
{
|
||||
SkillFormula formula = Formula(w: -1, x: 0, y: 0, z: 1);
|
||||
|
||||
Assert.True(RetailSkillFormula.TryCalculate(formula, 0u, 0u, out uint result));
|
||||
|
||||
Assert.Equal(uint.MaxValue, result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LiveResolverLooksUpTheDatFormulaAndTreatsMissingAttributesAsZero()
|
||||
{
|
||||
const uint skillId = 0x345u;
|
||||
const uint firstAttributeId = 1u;
|
||||
const uint secondAttributeId = 2u;
|
||||
var skillTable = new SkillTable();
|
||||
skillTable.Skills.Add((SkillId)skillId, new SkillBase
|
||||
{
|
||||
Formula = new SkillFormula
|
||||
{
|
||||
AdditiveBonus = 1,
|
||||
Attribute1Multiplier = 1,
|
||||
Attribute2Multiplier = 2,
|
||||
Divisor = 3,
|
||||
Attribute1 = (AttributeId)firstAttributeId,
|
||||
Attribute2 = (AttributeId)secondAttributeId,
|
||||
},
|
||||
});
|
||||
var resolver = new LiveSkillCreditResolver(skillTable);
|
||||
|
||||
uint result = resolver.Resolve(
|
||||
skillId,
|
||||
new Dictionary<uint, uint> { [firstAttributeId] = 8u });
|
||||
|
||||
Assert.Equal(3u, result);
|
||||
Assert.Equal(0u, resolver.Resolve(0x999u, new Dictionary<uint, uint>()));
|
||||
}
|
||||
|
||||
private static SkillFormula Formula(int w, int x, int y, uint z) => new()
|
||||
{
|
||||
AdditiveBonus = w,
|
||||
Attribute1Multiplier = x,
|
||||
Attribute2Multiplier = y,
|
||||
Divisor = unchecked((int)z),
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue