geometry-tower-defense/Assets/Tests/EditMode/CombatSettlementServiceTest...

198 lines
9.4 KiB
C#

using System.Collections.Generic;
using System.Reflection;
using GeometryTD.CustomComponent;
using GeometryTD.DataTable;
using GeometryTD.Definition;
using NUnit.Framework;
using UnityEngine;
namespace GeometryTD.Tests.EditMode
{
public sealed class CombatSettlementServiceTests
{
private const int MaxParticipantTowerCount = 4;
private GameObject _inventoryObject;
private PlayerInventoryComponent _originalPlayerInventory;
[TearDown]
public void TearDown()
{
SetStaticPlayerInventory(_originalPlayerInventory);
if (_inventoryObject != null)
{
Object.DestroyImmediate(_inventoryObject);
_inventoryObject = null;
}
}
[Test]
public void BuildSettlementContext_Captures_CombatStart_Participant_Tower_Ids_And_Fixed_Endurance_Loss()
{
PlayerInventoryComponent inventoryComponent = CreateBoundPlayerInventory(CreateInventory(100f, 100f, 100f));
CombatRunResourceStore resourceStore = new CombatRunResourceStore();
DRLevel level = CreateLevel(baseHp: 100, startCoin: 20, rewardGold: 30);
resourceStore.InitializeForCombat(level);
BackpackInventoryData changedInventory = inventoryComponent.GetInventorySnapshot();
changedInventory.ParticipantTowerInstanceIds.Clear();
changedInventory.ParticipantTowerInstanceIds.Add(90003);
inventoryComponent.ReplaceInventorySnapshot(changedInventory);
CombatSettlementContext settlementContext = new CombatSettlementService().BuildSettlementContext(
didCombatWin: false,
currentLevel: level,
defeatedEnemyCount: 4,
resourceStore: resourceStore);
CollectionAssert.AreEqual(
new long[] { 90001, 90002 },
settlementContext.Result.Endurance.TargetTowerInstanceIds);
Assert.That(settlementContext.Result.Endurance.EnduranceLossPerComponent, Is.EqualTo(1f));
Assert.That(settlementContext.Flags.ShouldOpenRewardSelection, Is.False);
}
[Test]
public void CommitSettlementInventory_Reduces_Only_CombatStart_Participant_Towers()
{
PlayerInventoryComponent inventoryComponent = CreateBoundPlayerInventory(CreateInventory(100f, 100f, 100f));
CombatRunResourceStore resourceStore = new CombatRunResourceStore();
DRLevel level = CreateLevel(baseHp: 100, startCoin: 20, rewardGold: 30);
resourceStore.InitializeForCombat(level);
BackpackInventoryData changedInventory = inventoryComponent.GetInventorySnapshot();
changedInventory.ParticipantTowerInstanceIds.Clear();
changedInventory.ParticipantTowerInstanceIds.Add(90003);
inventoryComponent.ReplaceInventorySnapshot(changedInventory);
CombatSettlementService settlementService = new CombatSettlementService();
CombatSettlementContext settlementContext = settlementService.BuildSettlementContext(
didCombatWin: false,
currentLevel: level,
defeatedEnemyCount: 2,
resourceStore: resourceStore);
settlementService.CommitSettlementInventory(settlementContext);
BackpackInventoryData committedInventory = inventoryComponent.GetInventorySnapshot();
Assert.That(GetTowerComponents(committedInventory, 90001).Muzzle.Endurance, Is.EqualTo(99f));
Assert.That(GetTowerComponents(committedInventory, 90002).Muzzle.Endurance, Is.EqualTo(99f));
Assert.That(GetTowerComponents(committedInventory, 90003).Muzzle.Endurance, Is.EqualTo(100f));
Assert.That(settlementContext.Result.Endurance.AffectedTowerCount, Is.EqualTo(2));
}
[Test]
public void CommitSettlementInventory_Reduces_Endurance_To_Zero_And_Next_Validation_Fails()
{
PlayerInventoryComponent inventoryComponent = CreateBoundPlayerInventory(CreateInventory(1f, 100f, 100f));
CombatRunResourceStore resourceStore = new CombatRunResourceStore();
DRLevel level = CreateLevel(baseHp: 100, startCoin: 20, rewardGold: 30);
resourceStore.InitializeForCombat(level);
CombatSettlementService settlementService = new CombatSettlementService();
CombatSettlementContext settlementContext = settlementService.BuildSettlementContext(
didCombatWin: true,
currentLevel: level,
defeatedEnemyCount: 6,
resourceStore: resourceStore);
settlementService.CommitSettlementInventory(settlementContext);
BackpackInventoryData committedInventory = inventoryComponent.GetInventorySnapshot();
CombatParticipantTowerValidationSummary summary =
CombatParticipantTowerValidationService.ValidateParticipantTowers(committedInventory);
Assert.That(GetTowerComponents(committedInventory, 90001).Muzzle.Endurance, Is.EqualTo(0f));
Assert.That(summary.HasAnyValidParticipantTower, Is.True);
Assert.That(summary.InvalidResults.Count, Is.EqualTo(1));
Assert.That(
summary.InvalidResults[0].FailureReason,
Is.EqualTo(CombatParticipantTowerValidationFailureReason.BrokenMuzzleComponent));
}
private PlayerInventoryComponent CreateBoundPlayerInventory(BackpackInventoryData inventory)
{
_originalPlayerInventory = GameEntry.PlayerInventory;
_inventoryObject = new GameObject("TestPlayerInventory");
PlayerInventoryComponent inventoryComponent = _inventoryObject.AddComponent<PlayerInventoryComponent>();
SetStaticPlayerInventory(inventoryComponent);
inventoryComponent.ReplaceInventorySnapshot(inventory);
return inventoryComponent;
}
private static void SetStaticPlayerInventory(PlayerInventoryComponent inventoryComponent)
{
FieldInfo backingField = typeof(GameEntry).GetField(
"<PlayerInventory>k__BackingField",
BindingFlags.Static | BindingFlags.NonPublic);
Assert.That(backingField, Is.Not.Null);
backingField.SetValue(null, inventoryComponent);
}
private static DRLevel CreateLevel(int baseHp, int startCoin, int rewardGold)
{
DRLevel level = new DRLevel();
bool parsed = level.ParseDataRow(
$"\t1\t测试关卡\tPlain\t{baseHp}\t{startCoin}\tWaveCount\t10\t{rewardGold}",
null);
Assert.That(parsed, Is.True);
return level;
}
private static BackpackInventoryData CreateInventory(
float firstTowerEndurance,
float secondTowerEndurance,
float thirdTowerEndurance)
{
BackpackInventoryData inventory = new BackpackInventoryData();
AddTower(inventory, 90001, 10001, 20001, 30001, firstTowerEndurance, isParticipant: true);
AddTower(inventory, 90002, 10002, 20002, 30002, secondTowerEndurance, isParticipant: true);
AddTower(inventory, 90003, 10003, 20003, 30003, thirdTowerEndurance, isParticipant: false);
return inventory;
}
private static void AddTower(
BackpackInventoryData inventory,
long towerId,
long muzzleId,
long bearingId,
long baseId,
float endurance,
bool isParticipant)
{
inventory.MuzzleComponents.Add(new MuzzleCompItemData { InstanceId = muzzleId, Endurance = endurance });
inventory.BearingComponents.Add(new BearingCompItemData { InstanceId = bearingId, Endurance = endurance });
inventory.BaseComponents.Add(new BaseCompItemData { InstanceId = baseId, Endurance = endurance });
inventory.Towers.Add(new TowerItemData
{
InstanceId = towerId,
MuzzleComponentInstanceId = muzzleId,
BearingComponentInstanceId = bearingId,
BaseComponentInstanceId = baseId,
IsParticipatingInCombat = isParticipant,
Stats = new TowerStatsData()
});
if (isParticipant && inventory.ParticipantTowerInstanceIds.Count < MaxParticipantTowerCount)
{
inventory.ParticipantTowerInstanceIds.Add(towerId);
}
}
private static (MuzzleCompItemData Muzzle, BearingCompItemData Bearing, BaseCompItemData Base) GetTowerComponents(
BackpackInventoryData inventory,
long towerInstanceId)
{
TowerItemData tower = inventory.Towers.Find(item => item.InstanceId == towerInstanceId);
Assert.That(tower, Is.Not.Null);
MuzzleCompItemData muzzle = inventory.MuzzleComponents.Find(item => item.InstanceId == tower.MuzzleComponentInstanceId);
BearingCompItemData bearing = inventory.BearingComponents.Find(item => item.InstanceId == tower.BearingComponentInstanceId);
BaseCompItemData baseComp = inventory.BaseComponents.Find(item => item.InstanceId == tower.BaseComponentInstanceId);
Assert.That(muzzle, Is.Not.Null);
Assert.That(bearing, Is.Not.Null);
Assert.That(baseComp, Is.Not.Null);
return (muzzle, bearing, baseComp);
}
}
}