201 lines
7.5 KiB
C#
201 lines
7.5 KiB
C#
using AcDream.Plugin.Abstractions;
|
|
|
|
namespace AcDream.Plugins.MossTank.Tests;
|
|
|
|
public sealed class FellowshipManagerTests
|
|
{
|
|
[Fact]
|
|
public void XpTellQueuesAndRecruitsANearbyPlayerThroughTheHostCommand()
|
|
{
|
|
var automation = new FakeAutomation();
|
|
automation.AddTell(2u, "Alice", "xp");
|
|
var manager = new FellowshipManager(new FakeHost(automation));
|
|
|
|
manager.Tick(0.1d, enabled: true);
|
|
|
|
Assert.Equal(2u, automation.RecruitedObjectId);
|
|
Assert.Contains(automation.Submitted, value => value.Contains(
|
|
"I will recruit you in a moment", StringComparison.Ordinal));
|
|
Assert.Contains("Alice", manager.WaitingNames);
|
|
|
|
automation.Roster.Add(Member(2u, "Alice"));
|
|
manager.Tick(0.1d, enabled: true);
|
|
Assert.DoesNotContain("Alice", manager.WaitingNames);
|
|
}
|
|
|
|
[Fact]
|
|
public void MemberVoteExecutesGiveLeaderAfterTheOfficialTwoMinuteWindow()
|
|
{
|
|
var automation = new FakeAutomation();
|
|
automation.Roster.Add(Member(2u, "Alice"));
|
|
automation.Roster.Add(Member(3u, "Bob"));
|
|
var manager = new FellowshipManager(new FakeHost(automation));
|
|
automation.AddTell(2u, "Alice", "startvote giveleader Bob");
|
|
|
|
manager.Tick(0.1d, enabled: true);
|
|
automation.AddTell(3u, "Bob", "vote 1 yes");
|
|
manager.Tick(0.1d, enabled: true);
|
|
manager.Tick(120d, enabled: true);
|
|
|
|
Assert.Equal(3u, automation.AssignedLeaderObjectId);
|
|
Assert.Contains(automation.Submitted, value => value.Contains(
|
|
"passed (2/0)", StringComparison.Ordinal));
|
|
}
|
|
|
|
private static PluginFellowMember Member(uint id, string name) => new(
|
|
id, name, 100u, 100u, 100u, 100u, 100u, 100u, 0f);
|
|
|
|
private sealed class FakeHost(FakeAutomation automation) : IPluginHost
|
|
{
|
|
public bool HasUi => false;
|
|
public IPluginLogger Log { get; } = new StubLogger();
|
|
public IGameState State { get; } = new StubState();
|
|
public IEvents Events { get; } = new StubEvents();
|
|
public ISelectionService Selection { get; } = new StubSelection();
|
|
public IUiRegistry Ui => NoOpUiRegistry.Instance;
|
|
public IAutomationSurface Automation { get; } = automation;
|
|
}
|
|
|
|
private sealed class StubLogger : IPluginLogger
|
|
{
|
|
public void Info(string message) { }
|
|
public void Warn(string message) { }
|
|
public void Error(string message, Exception? exception = null) { }
|
|
}
|
|
|
|
private sealed class StubState : IGameState
|
|
{
|
|
public IReadOnlyList<WorldEntitySnapshot> Entities => [];
|
|
}
|
|
|
|
private sealed class StubEvents : IEvents
|
|
{
|
|
public event Action<WorldEntitySnapshot> EntitySpawned
|
|
{
|
|
add { }
|
|
remove { }
|
|
}
|
|
public event Action<double> Tick
|
|
{
|
|
add { }
|
|
remove { }
|
|
}
|
|
}
|
|
|
|
private sealed class StubSelection : ISelectionService
|
|
{
|
|
public uint? SelectedObjectId => null;
|
|
public uint? PreviousObjectId => null;
|
|
public event Action<SelectionChangedEvent> Changed
|
|
{
|
|
add { }
|
|
remove { }
|
|
}
|
|
public bool Select(uint objectId) => false;
|
|
public bool Clear() => false;
|
|
}
|
|
|
|
private sealed class FakeAutomation
|
|
: IAutomationSurface, ICharacterInfo, IPluginChat,
|
|
IFellowshipAutomation, INavigationAutomation
|
|
{
|
|
private ulong _sequence;
|
|
private readonly List<PluginChatMessage> _messages = [];
|
|
|
|
public bool IsAvailable => true;
|
|
public ICharacterInfo Character => this;
|
|
public ISpellCatalog Spells => NoOpAutomationSurface.Instance;
|
|
public IMagicCommands Magic => NoOpAutomationSurface.Instance;
|
|
public IPluginChat Chat => this;
|
|
public IFellowshipAutomation Fellowship => this;
|
|
public INavigationAutomation Navigation => this;
|
|
public bool IsInWorld => true;
|
|
public string Name => "Leader";
|
|
public uint ObjectId => 1u;
|
|
public uint CurrentHealth => 100u;
|
|
public uint MaxHealth => 100u;
|
|
public uint CurrentStamina => 100u;
|
|
public uint MaxStamina => 100u;
|
|
public uint CurrentMana => 100u;
|
|
public uint MaxMana => 100u;
|
|
public IReadOnlyList<PluginSkillInfo> Skills => [];
|
|
public IReadOnlyList<PluginAttributeInfo> Attributes => [];
|
|
public IReadOnlyList<PluginActiveEnchantment> ActiveEnchantments => [];
|
|
public bool TryGetSkill(uint skillId, out PluginSkillInfo skill)
|
|
{
|
|
skill = default;
|
|
return false;
|
|
}
|
|
|
|
public bool IsInFellowship => true;
|
|
string IFellowshipAutomation.Name => "Test Fellow";
|
|
public uint LeaderObjectId => 1u;
|
|
public bool IsOpen { get; private set; } = true;
|
|
public bool IsLocked => false;
|
|
public int MemberCount => Roster.Count;
|
|
public List<PluginFellowMember> Roster { get; } = [Member(1u, "Leader")];
|
|
public IReadOnlyList<PluginFellowMember> CaptureMembers() =>
|
|
Roster.Where(static member => member.ObjectId != 1u).ToArray();
|
|
public IReadOnlyList<PluginFellowMember> CaptureRoster() => Roster.ToArray();
|
|
public uint RecruitedObjectId { get; private set; }
|
|
public uint DismissedObjectId { get; private set; }
|
|
public uint AssignedLeaderObjectId { get; private set; }
|
|
public PluginFellowshipCommandResult Recruit(uint targetObjectId)
|
|
{
|
|
RecruitedObjectId = targetObjectId;
|
|
return new(PluginFellowshipCommandStatus.Accepted);
|
|
}
|
|
public PluginFellowshipCommandResult Dismiss(uint targetObjectId)
|
|
{
|
|
DismissedObjectId = targetObjectId;
|
|
return new(PluginFellowshipCommandStatus.Accepted);
|
|
}
|
|
public PluginFellowshipCommandResult AssignLeader(uint targetObjectId)
|
|
{
|
|
AssignedLeaderObjectId = targetObjectId;
|
|
return new(PluginFellowshipCommandStatus.Accepted);
|
|
}
|
|
public PluginFellowshipCommandResult SetOpen(bool isOpen)
|
|
{
|
|
IsOpen = isOpen;
|
|
return new(PluginFellowshipCommandStatus.Accepted);
|
|
}
|
|
|
|
public PluginNavigationSnapshot Snapshot => new(
|
|
true,
|
|
false,
|
|
1u,
|
|
Position(0d),
|
|
false,
|
|
false);
|
|
public bool TryGetObject(uint objectId, out PluginNavigationObject value)
|
|
{
|
|
value = objectId == 2u
|
|
? new PluginNavigationObject(2u, "Alice", Position(0.02d))
|
|
: default;
|
|
return value.ObjectId != 0u;
|
|
}
|
|
public PluginNavigationCommandStatus SetMovementIntent(
|
|
in PluginMovementIntent intent) => PluginNavigationCommandStatus.Accepted;
|
|
public PluginNavigationCommandStatus ClearMovementIntent() =>
|
|
PluginNavigationCommandStatus.Accepted;
|
|
|
|
public List<string> Submitted { get; } = [];
|
|
public IReadOnlyList<PluginChatMessage> CaptureMessages(ulong afterSequence) =>
|
|
_messages.Where(value => value.Sequence > afterSequence).ToArray();
|
|
public void PostSystemMessage(string text)
|
|
{
|
|
}
|
|
public bool Submit(string text)
|
|
{
|
|
Submitted.Add(text);
|
|
return true;
|
|
}
|
|
public void AddTell(uint senderId, string sender, string text) =>
|
|
_messages.Add(new PluginChatMessage(
|
|
++_sequence, senderId, 3, sender, text, string.Empty));
|
|
|
|
private static PluginNavigationPosition Position(double eastWest) => new(
|
|
0x00010001u, eastWest, 0d, 0d, 0f, true);
|
|
}
|
|
}
|