feat(app): FA2 -- fellowship/allegiance command routing for graphical + headless hosts
Both LiveSocialSessionBindings construction sites updated together (LiveSessionRuntimeFactory.cs, HeadlessSessionHost.cs) so the single GameEventWiring.WireAll registration site serves both hosts identically (the K-slice unification). CurrentGameRuntimeCommandAdapter implements IRuntimeFellowshipCommands/IRuntimeAllegianceCommands over the App command bus (LiveSessionCommandRouter gains 12 new *RuntimeCmd records + registrations + LiveSessionCommandBindings send delegates), mirroring DirectGameRuntimeCommandAdapter's direct-session shape including the identical Quit leader-hand-off rule read from RuntimeFellowshipState. CurrentGameRuntimeAdapter (the graphical IGameRuntimeView/ IGameRuntimeCommands composite) exposes the two new views/command groups. Headless's DirectGameRuntimeCommandAdapter needed no changes -- it already implements both new interfaces from the Runtime-layer commit. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
369729f06a
commit
cced83b483
8 changed files with 363 additions and 3 deletions
|
|
@ -50,6 +50,21 @@ internal sealed record LiveSessionCommandBindings(
|
||||||
// research §2.3-§2.7. No-ops when the batched module is clean, matching
|
// research §2.3-§2.7. No-ops when the batched module is clean, matching
|
||||||
// retail's CPlayerModule::SaveToServer(force: 0).
|
// retail's CPlayerModule::SaveToServer(force: 0).
|
||||||
Action SaveCharacterOptions,
|
Action SaveCharacterOptions,
|
||||||
|
// Campaign FA slice FA2 (2026-08-12): fellowship + allegiance send
|
||||||
|
// wrappers, the App-bus twin of DirectGameRuntimeCommandAdapter's
|
||||||
|
// direct session.SendXxx calls.
|
||||||
|
Action<string, bool> SendFellowshipCreate,
|
||||||
|
Action<uint> SendFellowshipRecruit,
|
||||||
|
Action<uint> SendFellowshipDismiss,
|
||||||
|
Action<bool> SendFellowshipQuit,
|
||||||
|
Action<uint> SendFellowshipAssignNewLeader,
|
||||||
|
Action<bool> SendFellowshipChangeOpenness,
|
||||||
|
Action<bool> SendFellowshipUpdateRequest,
|
||||||
|
Action<uint> SendAllegianceSwear,
|
||||||
|
Action<uint> SendAllegianceBreak,
|
||||||
|
Action<uint> SendAllegianceKick,
|
||||||
|
Action<string> SendAllegianceInfoRequest,
|
||||||
|
Action<bool> SendAllegianceUpdateRequest,
|
||||||
Action<string>? Log = null);
|
Action<string>? Log = null);
|
||||||
|
|
||||||
internal readonly record struct AddShortcutRuntimeCmd(ShortcutEntry Entry);
|
internal readonly record struct AddShortcutRuntimeCmd(ShortcutEntry Entry);
|
||||||
|
|
@ -91,6 +106,22 @@ internal readonly record struct ModifyGlobalSquelchRuntimeCmd(
|
||||||
bool Add,
|
bool Add,
|
||||||
uint MessageType);
|
uint MessageType);
|
||||||
|
|
||||||
|
// ── Fellowship / Allegiance (Campaign FA slice FA2, 2026-08-12) ────────────
|
||||||
|
internal readonly record struct FellowshipCreateRuntimeCmd(
|
||||||
|
string FellowshipName,
|
||||||
|
bool ShareXp);
|
||||||
|
internal readonly record struct FellowshipRecruitRuntimeCmd(uint TargetGuid);
|
||||||
|
internal readonly record struct FellowshipDismissRuntimeCmd(uint TargetGuid);
|
||||||
|
internal readonly record struct FellowshipQuitRuntimeCmd(bool Disband);
|
||||||
|
internal readonly record struct FellowshipAssignNewLeaderRuntimeCmd(uint NewLeaderGuid);
|
||||||
|
internal readonly record struct FellowshipChangeOpennessRuntimeCmd(bool IsOpen);
|
||||||
|
internal readonly record struct FellowshipUpdateRequestRuntimeCmd(bool PanelOpen);
|
||||||
|
internal readonly record struct AllegianceSwearRuntimeCmd(uint PatronGuid);
|
||||||
|
internal readonly record struct AllegianceBreakRuntimeCmd(uint TargetGuid);
|
||||||
|
internal readonly record struct AllegianceKickRuntimeCmd(uint VassalGuid);
|
||||||
|
internal readonly record struct AllegianceInfoRequestRuntimeCmd(string PlayerName);
|
||||||
|
internal readonly record struct AllegianceUpdateRequestRuntimeCmd(bool On);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Owns the command surface for one exact live-session generation. The router
|
/// Owns the command surface for one exact live-session generation. The router
|
||||||
/// itself is the published bus, so a retained reference becomes inert before
|
/// itself is the published bus, so a retained reference becomes inert before
|
||||||
|
|
@ -200,6 +231,43 @@ internal sealed class LiveSessionCommandRouter : ILiveSessionCommandRouting
|
||||||
command => SendIfActive(() => bindings.ModifyGlobalSquelch(
|
command => SendIfActive(() => bindings.ModifyGlobalSquelch(
|
||||||
command.Add,
|
command.Add,
|
||||||
command.MessageType)));
|
command.MessageType)));
|
||||||
|
commands.Register<FellowshipCreateRuntimeCmd>(
|
||||||
|
command => SendIfActive(() => bindings.SendFellowshipCreate(
|
||||||
|
command.FellowshipName,
|
||||||
|
command.ShareXp)));
|
||||||
|
commands.Register<FellowshipRecruitRuntimeCmd>(
|
||||||
|
command => SendIfActive(() =>
|
||||||
|
bindings.SendFellowshipRecruit(command.TargetGuid)));
|
||||||
|
commands.Register<FellowshipDismissRuntimeCmd>(
|
||||||
|
command => SendIfActive(() =>
|
||||||
|
bindings.SendFellowshipDismiss(command.TargetGuid)));
|
||||||
|
commands.Register<FellowshipQuitRuntimeCmd>(
|
||||||
|
command => SendIfActive(() =>
|
||||||
|
bindings.SendFellowshipQuit(command.Disband)));
|
||||||
|
commands.Register<FellowshipAssignNewLeaderRuntimeCmd>(
|
||||||
|
command => SendIfActive(() =>
|
||||||
|
bindings.SendFellowshipAssignNewLeader(command.NewLeaderGuid)));
|
||||||
|
commands.Register<FellowshipChangeOpennessRuntimeCmd>(
|
||||||
|
command => SendIfActive(() =>
|
||||||
|
bindings.SendFellowshipChangeOpenness(command.IsOpen)));
|
||||||
|
commands.Register<FellowshipUpdateRequestRuntimeCmd>(
|
||||||
|
command => SendIfActive(() =>
|
||||||
|
bindings.SendFellowshipUpdateRequest(command.PanelOpen)));
|
||||||
|
commands.Register<AllegianceSwearRuntimeCmd>(
|
||||||
|
command => SendIfActive(() =>
|
||||||
|
bindings.SendAllegianceSwear(command.PatronGuid)));
|
||||||
|
commands.Register<AllegianceBreakRuntimeCmd>(
|
||||||
|
command => SendIfActive(() =>
|
||||||
|
bindings.SendAllegianceBreak(command.TargetGuid)));
|
||||||
|
commands.Register<AllegianceKickRuntimeCmd>(
|
||||||
|
command => SendIfActive(() =>
|
||||||
|
bindings.SendAllegianceKick(command.VassalGuid)));
|
||||||
|
commands.Register<AllegianceInfoRequestRuntimeCmd>(
|
||||||
|
command => SendIfActive(() =>
|
||||||
|
bindings.SendAllegianceInfoRequest(command.PlayerName)));
|
||||||
|
commands.Register<AllegianceUpdateRequestRuntimeCmd>(
|
||||||
|
command => SendIfActive(() =>
|
||||||
|
bindings.SendAllegianceUpdateRequest(command.On)));
|
||||||
_commands = commands;
|
_commands = commands;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -258,7 +258,9 @@ internal sealed class LiveSessionRuntimeFactory
|
||||||
_domain.Communication.TurbineChat,
|
_domain.Communication.TurbineChat,
|
||||||
_domain.Communication.Friends,
|
_domain.Communication.Friends,
|
||||||
_domain.Communication.Squelch,
|
_domain.Communication.Squelch,
|
||||||
(text, type) => _domain.Communication.AddText(text, type)));
|
(text, type) => _domain.Communication.AddText(text, type),
|
||||||
|
Fellowship: _domain.Runtime.FellowshipOwner,
|
||||||
|
Allegiance: _domain.Runtime.AllegianceOwner));
|
||||||
return new GraphicalSessionEventRoute(
|
return new GraphicalSessionEventRoute(
|
||||||
route,
|
route,
|
||||||
_domain.Runtime,
|
_domain.Runtime,
|
||||||
|
|
@ -591,6 +593,20 @@ internal sealed class LiveSessionRuntimeFactory
|
||||||
CharacterState: _domain.Character,
|
CharacterState: _domain.Character,
|
||||||
SendSingleCharacterOption: SendSingleCharacterOption,
|
SendSingleCharacterOption: SendSingleCharacterOption,
|
||||||
SaveCharacterOptions: SaveCharacterOptionsIfDirty,
|
SaveCharacterOptions: SaveCharacterOptionsIfDirty,
|
||||||
|
// Campaign FA slice FA2 (2026-08-12): fellowship + allegiance send
|
||||||
|
// wrappers, matching the WorldSession.SendXxx methods FA2 added.
|
||||||
|
SendFellowshipCreate: session.SendFellowshipCreate,
|
||||||
|
SendFellowshipRecruit: session.SendFellowshipRecruit,
|
||||||
|
SendFellowshipDismiss: session.SendFellowshipDismiss,
|
||||||
|
SendFellowshipQuit: session.SendFellowshipQuit,
|
||||||
|
SendFellowshipAssignNewLeader: session.SendFellowshipAssignNewLeader,
|
||||||
|
SendFellowshipChangeOpenness: session.SendFellowshipChangeOpenness,
|
||||||
|
SendFellowshipUpdateRequest: session.SendFellowshipUpdateRequest,
|
||||||
|
SendAllegianceSwear: session.SendAllegianceSwear,
|
||||||
|
SendAllegianceBreak: session.SendAllegianceBreak,
|
||||||
|
SendAllegianceKick: session.SendAllegianceKick,
|
||||||
|
SendAllegianceInfoRequest: session.SendAllegianceInfoRequest,
|
||||||
|
SendAllegianceUpdateRequest: session.SendAllegianceUpdateRequest,
|
||||||
Log: _log);
|
Log: _log);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@ internal sealed class CurrentGameRuntimeAdapter
|
||||||
runtime.CharacterOwner,
|
runtime.CharacterOwner,
|
||||||
runtime.ActionOwner,
|
runtime.ActionOwner,
|
||||||
runtime.MovementOwner,
|
runtime.MovementOwner,
|
||||||
|
runtime.FellowshipOwner,
|
||||||
selection,
|
selection,
|
||||||
runtime.EventSink);
|
runtime.EventSink);
|
||||||
}
|
}
|
||||||
|
|
@ -88,6 +89,8 @@ internal sealed class CurrentGameRuntimeAdapter
|
||||||
public IRuntimeCharacterView Character => _runtime.Character;
|
public IRuntimeCharacterView Character => _runtime.Character;
|
||||||
public IRuntimeSocialView Social => _runtime.Social;
|
public IRuntimeSocialView Social => _runtime.Social;
|
||||||
public IRuntimeChatView Chat => _runtime.Chat;
|
public IRuntimeChatView Chat => _runtime.Chat;
|
||||||
|
public IRuntimeFellowshipView Fellowship => _runtime.Fellowship;
|
||||||
|
public IRuntimeAllegianceView Allegiance => _runtime.Allegiance;
|
||||||
public IRuntimeActionView Actions => _runtime.Actions;
|
public IRuntimeActionView Actions => _runtime.Actions;
|
||||||
public IRuntimeMovementView Movement => _runtime.Movement;
|
public IRuntimeMovementView Movement => _runtime.Movement;
|
||||||
public IRuntimeWorldEnvironmentView Environment => _runtime.Environment;
|
public IRuntimeWorldEnvironmentView Environment => _runtime.Environment;
|
||||||
|
|
@ -112,6 +115,10 @@ internal sealed class CurrentGameRuntimeAdapter
|
||||||
IRuntimeCharacterCommands IGameRuntimeCommands.Character => _commands;
|
IRuntimeCharacterCommands IGameRuntimeCommands.Character => _commands;
|
||||||
public IRuntimeSocialCommands SocialCommands => _commands;
|
public IRuntimeSocialCommands SocialCommands => _commands;
|
||||||
IRuntimeSocialCommands IGameRuntimeCommands.Social => _commands;
|
IRuntimeSocialCommands IGameRuntimeCommands.Social => _commands;
|
||||||
|
public IRuntimeFellowshipCommands FellowshipCommands => _commands;
|
||||||
|
IRuntimeFellowshipCommands IGameRuntimeCommands.Fellowship => _commands;
|
||||||
|
public IRuntimeAllegianceCommands AllegianceCommands => _commands;
|
||||||
|
IRuntimeAllegianceCommands IGameRuntimeCommands.Allegiance => _commands;
|
||||||
|
|
||||||
public RuntimeStateCheckpoint CaptureCheckpoint()
|
public RuntimeStateCheckpoint CaptureCheckpoint()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,9 @@ internal sealed class CurrentGameRuntimeCommandAdapter
|
||||||
IRuntimeInventoryStateCommands,
|
IRuntimeInventoryStateCommands,
|
||||||
IRuntimeSpellbookCommands,
|
IRuntimeSpellbookCommands,
|
||||||
IRuntimeCharacterCommands,
|
IRuntimeCharacterCommands,
|
||||||
IRuntimeSocialCommands
|
IRuntimeSocialCommands,
|
||||||
|
IRuntimeFellowshipCommands,
|
||||||
|
IRuntimeAllegianceCommands
|
||||||
{
|
{
|
||||||
private readonly LiveSessionController _session;
|
private readonly LiveSessionController _session;
|
||||||
private readonly LiveSessionHost _sessionHost;
|
private readonly LiveSessionHost _sessionHost;
|
||||||
|
|
@ -36,6 +38,7 @@ internal sealed class CurrentGameRuntimeCommandAdapter
|
||||||
private readonly RuntimeCharacterState _character;
|
private readonly RuntimeCharacterState _character;
|
||||||
private readonly RuntimeActionState _actions;
|
private readonly RuntimeActionState _actions;
|
||||||
private readonly RuntimeLocalPlayerMovementState _movement;
|
private readonly RuntimeLocalPlayerMovementState _movement;
|
||||||
|
private readonly RuntimeFellowshipState _fellowship;
|
||||||
private readonly SelectionInteractionController _selection;
|
private readonly SelectionInteractionController _selection;
|
||||||
private readonly IGameRuntimeEventSink _events;
|
private readonly IGameRuntimeEventSink _events;
|
||||||
|
|
||||||
|
|
@ -48,6 +51,7 @@ internal sealed class CurrentGameRuntimeCommandAdapter
|
||||||
RuntimeCharacterState character,
|
RuntimeCharacterState character,
|
||||||
RuntimeActionState actions,
|
RuntimeActionState actions,
|
||||||
RuntimeLocalPlayerMovementState movement,
|
RuntimeLocalPlayerMovementState movement,
|
||||||
|
RuntimeFellowshipState fellowship,
|
||||||
SelectionInteractionController selection,
|
SelectionInteractionController selection,
|
||||||
IGameRuntimeEventSink events)
|
IGameRuntimeEventSink events)
|
||||||
{
|
{
|
||||||
|
|
@ -61,6 +65,8 @@ internal sealed class CurrentGameRuntimeCommandAdapter
|
||||||
?? throw new ArgumentNullException(nameof(actions));
|
?? throw new ArgumentNullException(nameof(actions));
|
||||||
_movement = movement
|
_movement = movement
|
||||||
?? throw new ArgumentNullException(nameof(movement));
|
?? throw new ArgumentNullException(nameof(movement));
|
||||||
|
_fellowship = fellowship
|
||||||
|
?? throw new ArgumentNullException(nameof(fellowship));
|
||||||
_selection = selection ?? throw new ArgumentNullException(nameof(selection));
|
_selection = selection ?? throw new ArgumentNullException(nameof(selection));
|
||||||
_events = events ?? throw new ArgumentNullException(nameof(events));
|
_events = events ?? throw new ArgumentNullException(nameof(events));
|
||||||
}
|
}
|
||||||
|
|
@ -793,6 +799,249 @@ internal sealed class CurrentGameRuntimeCommandAdapter
|
||||||
command.Name);
|
command.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── Fellowship / Allegiance (Campaign FA slice FA2, 2026-08-12) ────────
|
||||||
|
|
||||||
|
public RuntimeCommandResult Create(
|
||||||
|
RuntimeGenerationToken expectedGeneration,
|
||||||
|
string fellowshipName,
|
||||||
|
bool shareXp)
|
||||||
|
{
|
||||||
|
RuntimeCommandStatus gate = Validate(expectedGeneration, requireWorld: true);
|
||||||
|
if (gate != RuntimeCommandStatus.Accepted)
|
||||||
|
return Result(gate);
|
||||||
|
if (string.IsNullOrWhiteSpace(fellowshipName))
|
||||||
|
{
|
||||||
|
return EmitResult(
|
||||||
|
RuntimeCommandDomain.Fellowship,
|
||||||
|
operation: 0,
|
||||||
|
RuntimeCommandStatus.Rejected);
|
||||||
|
}
|
||||||
|
_commands.Publish(new FellowshipCreateRuntimeCmd(fellowshipName, shareXp));
|
||||||
|
return EmitResult(
|
||||||
|
RuntimeCommandDomain.Fellowship,
|
||||||
|
operation: 0,
|
||||||
|
RuntimeCommandStatus.Accepted);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RuntimeCommandResult Recruit(
|
||||||
|
RuntimeGenerationToken expectedGeneration,
|
||||||
|
uint targetGuid)
|
||||||
|
{
|
||||||
|
RuntimeCommandStatus gate = Validate(expectedGeneration, requireWorld: true);
|
||||||
|
if (gate != RuntimeCommandStatus.Accepted)
|
||||||
|
return Result(gate);
|
||||||
|
if (targetGuid == 0u)
|
||||||
|
{
|
||||||
|
return EmitResult(
|
||||||
|
RuntimeCommandDomain.Fellowship,
|
||||||
|
operation: 1,
|
||||||
|
RuntimeCommandStatus.Rejected,
|
||||||
|
targetGuid);
|
||||||
|
}
|
||||||
|
_commands.Publish(new FellowshipRecruitRuntimeCmd(targetGuid));
|
||||||
|
return EmitResult(
|
||||||
|
RuntimeCommandDomain.Fellowship,
|
||||||
|
operation: 1,
|
||||||
|
RuntimeCommandStatus.Accepted,
|
||||||
|
targetGuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RuntimeCommandResult Dismiss(
|
||||||
|
RuntimeGenerationToken expectedGeneration,
|
||||||
|
uint targetGuid)
|
||||||
|
{
|
||||||
|
RuntimeCommandStatus gate = Validate(expectedGeneration, requireWorld: true);
|
||||||
|
if (gate != RuntimeCommandStatus.Accepted)
|
||||||
|
return Result(gate);
|
||||||
|
if (targetGuid == 0u)
|
||||||
|
{
|
||||||
|
return EmitResult(
|
||||||
|
RuntimeCommandDomain.Fellowship,
|
||||||
|
operation: 2,
|
||||||
|
RuntimeCommandStatus.Rejected,
|
||||||
|
targetGuid);
|
||||||
|
}
|
||||||
|
_commands.Publish(new FellowshipDismissRuntimeCmd(targetGuid));
|
||||||
|
return EmitResult(
|
||||||
|
RuntimeCommandDomain.Fellowship,
|
||||||
|
operation: 2,
|
||||||
|
RuntimeCommandStatus.Accepted,
|
||||||
|
targetGuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Retail's Quit-button leader hand-off (lane B §2.5/§3.6) — see
|
||||||
|
/// <see cref="DirectGameRuntimeCommandAdapter.Quit"/>'s identical rule.
|
||||||
|
/// </summary>
|
||||||
|
public RuntimeCommandResult Quit(
|
||||||
|
RuntimeGenerationToken expectedGeneration,
|
||||||
|
bool disband)
|
||||||
|
{
|
||||||
|
RuntimeCommandStatus gate = Validate(expectedGeneration, requireWorld: true);
|
||||||
|
if (gate != RuntimeCommandStatus.Accepted)
|
||||||
|
return Result(gate);
|
||||||
|
if (_fellowship.RequiresLeaderHandoffBeforeQuit(
|
||||||
|
_view.Lifecycle.PlayerGuid,
|
||||||
|
disband,
|
||||||
|
out uint newLeaderGuid))
|
||||||
|
{
|
||||||
|
_commands.Publish(new FellowshipAssignNewLeaderRuntimeCmd(newLeaderGuid));
|
||||||
|
}
|
||||||
|
_commands.Publish(new FellowshipQuitRuntimeCmd(disband));
|
||||||
|
return EmitResult(
|
||||||
|
RuntimeCommandDomain.Fellowship,
|
||||||
|
operation: 3,
|
||||||
|
RuntimeCommandStatus.Accepted);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RuntimeCommandResult AssignLeader(
|
||||||
|
RuntimeGenerationToken expectedGeneration,
|
||||||
|
uint newLeaderGuid)
|
||||||
|
{
|
||||||
|
RuntimeCommandStatus gate = Validate(expectedGeneration, requireWorld: true);
|
||||||
|
if (gate != RuntimeCommandStatus.Accepted)
|
||||||
|
return Result(gate);
|
||||||
|
if (newLeaderGuid == 0u)
|
||||||
|
{
|
||||||
|
return EmitResult(
|
||||||
|
RuntimeCommandDomain.Fellowship,
|
||||||
|
operation: 4,
|
||||||
|
RuntimeCommandStatus.Rejected,
|
||||||
|
newLeaderGuid);
|
||||||
|
}
|
||||||
|
_commands.Publish(new FellowshipAssignNewLeaderRuntimeCmd(newLeaderGuid));
|
||||||
|
return EmitResult(
|
||||||
|
RuntimeCommandDomain.Fellowship,
|
||||||
|
operation: 4,
|
||||||
|
RuntimeCommandStatus.Accepted,
|
||||||
|
newLeaderGuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RuntimeCommandResult SetOpen(
|
||||||
|
RuntimeGenerationToken expectedGeneration,
|
||||||
|
bool isOpen)
|
||||||
|
{
|
||||||
|
RuntimeCommandStatus gate = Validate(expectedGeneration, requireWorld: true);
|
||||||
|
if (gate != RuntimeCommandStatus.Accepted)
|
||||||
|
return Result(gate);
|
||||||
|
_commands.Publish(new FellowshipChangeOpennessRuntimeCmd(isOpen));
|
||||||
|
return EmitResult(
|
||||||
|
RuntimeCommandDomain.Fellowship,
|
||||||
|
operation: 5,
|
||||||
|
RuntimeCommandStatus.Accepted);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RuntimeCommandResult SetPanelOpen(
|
||||||
|
RuntimeGenerationToken expectedGeneration,
|
||||||
|
bool panelOpen)
|
||||||
|
{
|
||||||
|
RuntimeCommandStatus gate = Validate(expectedGeneration, requireWorld: true);
|
||||||
|
if (gate != RuntimeCommandStatus.Accepted)
|
||||||
|
return Result(gate);
|
||||||
|
_commands.Publish(new FellowshipUpdateRequestRuntimeCmd(panelOpen));
|
||||||
|
return EmitResult(
|
||||||
|
RuntimeCommandDomain.Fellowship,
|
||||||
|
operation: 6,
|
||||||
|
RuntimeCommandStatus.Accepted);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RuntimeCommandResult Swear(
|
||||||
|
RuntimeGenerationToken expectedGeneration,
|
||||||
|
uint patronGuid)
|
||||||
|
{
|
||||||
|
RuntimeCommandStatus gate = Validate(expectedGeneration, requireWorld: true);
|
||||||
|
if (gate != RuntimeCommandStatus.Accepted)
|
||||||
|
return Result(gate);
|
||||||
|
if (patronGuid == 0u)
|
||||||
|
{
|
||||||
|
return EmitResult(
|
||||||
|
RuntimeCommandDomain.Allegiance,
|
||||||
|
operation: 0,
|
||||||
|
RuntimeCommandStatus.Rejected,
|
||||||
|
patronGuid);
|
||||||
|
}
|
||||||
|
_commands.Publish(new AllegianceSwearRuntimeCmd(patronGuid));
|
||||||
|
return EmitResult(
|
||||||
|
RuntimeCommandDomain.Allegiance,
|
||||||
|
operation: 0,
|
||||||
|
RuntimeCommandStatus.Accepted,
|
||||||
|
patronGuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RuntimeCommandResult Break(
|
||||||
|
RuntimeGenerationToken expectedGeneration,
|
||||||
|
uint targetGuid)
|
||||||
|
{
|
||||||
|
RuntimeCommandStatus gate = Validate(expectedGeneration, requireWorld: true);
|
||||||
|
if (gate != RuntimeCommandStatus.Accepted)
|
||||||
|
return Result(gate);
|
||||||
|
if (targetGuid == 0u)
|
||||||
|
{
|
||||||
|
return EmitResult(
|
||||||
|
RuntimeCommandDomain.Allegiance,
|
||||||
|
operation: 1,
|
||||||
|
RuntimeCommandStatus.Rejected,
|
||||||
|
targetGuid);
|
||||||
|
}
|
||||||
|
_commands.Publish(new AllegianceBreakRuntimeCmd(targetGuid));
|
||||||
|
return EmitResult(
|
||||||
|
RuntimeCommandDomain.Allegiance,
|
||||||
|
operation: 1,
|
||||||
|
RuntimeCommandStatus.Accepted,
|
||||||
|
targetGuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RuntimeCommandResult Kick(
|
||||||
|
RuntimeGenerationToken expectedGeneration,
|
||||||
|
uint vassalGuid)
|
||||||
|
{
|
||||||
|
RuntimeCommandStatus gate = Validate(expectedGeneration, requireWorld: true);
|
||||||
|
if (gate != RuntimeCommandStatus.Accepted)
|
||||||
|
return Result(gate);
|
||||||
|
if (vassalGuid == 0u)
|
||||||
|
{
|
||||||
|
return EmitResult(
|
||||||
|
RuntimeCommandDomain.Allegiance,
|
||||||
|
operation: 2,
|
||||||
|
RuntimeCommandStatus.Rejected,
|
||||||
|
vassalGuid);
|
||||||
|
}
|
||||||
|
_commands.Publish(new AllegianceKickRuntimeCmd(vassalGuid));
|
||||||
|
return EmitResult(
|
||||||
|
RuntimeCommandDomain.Allegiance,
|
||||||
|
operation: 2,
|
||||||
|
RuntimeCommandStatus.Accepted,
|
||||||
|
vassalGuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RuntimeCommandResult RequestInfo(
|
||||||
|
RuntimeGenerationToken expectedGeneration,
|
||||||
|
string playerName)
|
||||||
|
{
|
||||||
|
RuntimeCommandStatus gate = Validate(expectedGeneration, requireWorld: true);
|
||||||
|
if (gate != RuntimeCommandStatus.Accepted)
|
||||||
|
return Result(gate);
|
||||||
|
_commands.Publish(new AllegianceInfoRequestRuntimeCmd(playerName ?? string.Empty));
|
||||||
|
return EmitResult(
|
||||||
|
RuntimeCommandDomain.Allegiance,
|
||||||
|
operation: 3,
|
||||||
|
RuntimeCommandStatus.Accepted);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RuntimeCommandResult SetUpdateSubscription(
|
||||||
|
RuntimeGenerationToken expectedGeneration,
|
||||||
|
bool on)
|
||||||
|
{
|
||||||
|
RuntimeCommandStatus gate = Validate(expectedGeneration, requireWorld: true);
|
||||||
|
if (gate != RuntimeCommandStatus.Accepted)
|
||||||
|
return Result(gate);
|
||||||
|
_commands.Publish(new AllegianceUpdateRequestRuntimeCmd(on));
|
||||||
|
return EmitResult(
|
||||||
|
RuntimeCommandDomain.Allegiance,
|
||||||
|
operation: 4,
|
||||||
|
RuntimeCommandStatus.Accepted);
|
||||||
|
}
|
||||||
|
|
||||||
private RuntimeCommandStatus Validate(
|
private RuntimeCommandStatus Validate(
|
||||||
RuntimeGenerationToken expectedGeneration,
|
RuntimeGenerationToken expectedGeneration,
|
||||||
bool requireWorld)
|
bool requireWorld)
|
||||||
|
|
|
||||||
|
|
@ -782,7 +782,9 @@ internal sealed class HeadlessSessionHost : IDisposable
|
||||||
Runtime.CommunicationOwner.TurbineChat,
|
Runtime.CommunicationOwner.TurbineChat,
|
||||||
Runtime.CommunicationOwner.Friends,
|
Runtime.CommunicationOwner.Friends,
|
||||||
Runtime.CommunicationOwner.Squelch,
|
Runtime.CommunicationOwner.Squelch,
|
||||||
(text, type) => Runtime.CommunicationOwner.AddText(text, type)));
|
(text, type) => Runtime.CommunicationOwner.AddText(text, type),
|
||||||
|
Fellowship: Runtime.FellowshipOwner,
|
||||||
|
Allegiance: Runtime.AllegianceOwner));
|
||||||
var eventRoute = new HeadlessSessionEventRoute(
|
var eventRoute = new HeadlessSessionEventRoute(
|
||||||
route,
|
route,
|
||||||
Runtime,
|
Runtime,
|
||||||
|
|
|
||||||
|
|
@ -234,6 +234,8 @@ public sealed class InteractionUiRuntimeSourcesTests
|
||||||
public IRuntimeCharacterView Character => null!;
|
public IRuntimeCharacterView Character => null!;
|
||||||
public IRuntimeSocialView Social => null!;
|
public IRuntimeSocialView Social => null!;
|
||||||
public IRuntimeChatView Chat => null!;
|
public IRuntimeChatView Chat => null!;
|
||||||
|
public IRuntimeFellowshipView Fellowship => null!;
|
||||||
|
public IRuntimeAllegianceView Allegiance => null!;
|
||||||
public IRuntimeActionView Actions => null!;
|
public IRuntimeActionView Actions => null!;
|
||||||
public IRuntimeMovementView Movement => null!;
|
public IRuntimeMovementView Movement => null!;
|
||||||
public AcDream.Runtime.World.IRuntimeWorldEnvironmentView Environment =>
|
public AcDream.Runtime.World.IRuntimeWorldEnvironmentView Environment =>
|
||||||
|
|
@ -250,6 +252,8 @@ public sealed class InteractionUiRuntimeSourcesTests
|
||||||
IRuntimeSpellbookCommands IGameRuntimeCommands.Spellbook => this;
|
IRuntimeSpellbookCommands IGameRuntimeCommands.Spellbook => this;
|
||||||
IRuntimeCharacterCommands IGameRuntimeCommands.Character => this;
|
IRuntimeCharacterCommands IGameRuntimeCommands.Character => this;
|
||||||
IRuntimeSocialCommands IGameRuntimeCommands.Social => null!;
|
IRuntimeSocialCommands IGameRuntimeCommands.Social => null!;
|
||||||
|
IRuntimeFellowshipCommands IGameRuntimeCommands.Fellowship => null!;
|
||||||
|
IRuntimeAllegianceCommands IGameRuntimeCommands.Allegiance => null!;
|
||||||
|
|
||||||
public RuntimeStateCheckpoint CaptureCheckpoint() => default;
|
public RuntimeStateCheckpoint CaptureCheckpoint() => default;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -227,6 +227,8 @@ public sealed class GameplayInputCommandControllerTests
|
||||||
throw new NotSupportedException();
|
throw new NotSupportedException();
|
||||||
public IRuntimeSocialView Social => throw new NotSupportedException();
|
public IRuntimeSocialView Social => throw new NotSupportedException();
|
||||||
public IRuntimeChatView Chat => throw new NotSupportedException();
|
public IRuntimeChatView Chat => throw new NotSupportedException();
|
||||||
|
public IRuntimeFellowshipView Fellowship => throw new NotSupportedException();
|
||||||
|
public IRuntimeAllegianceView Allegiance => throw new NotSupportedException();
|
||||||
public IRuntimeActionView Actions => throw new NotSupportedException();
|
public IRuntimeActionView Actions => throw new NotSupportedException();
|
||||||
public IRuntimeMovementView Movement => throw new NotSupportedException();
|
public IRuntimeMovementView Movement => throw new NotSupportedException();
|
||||||
public AcDream.Runtime.World.IRuntimeWorldEnvironmentView Environment =>
|
public AcDream.Runtime.World.IRuntimeWorldEnvironmentView Environment =>
|
||||||
|
|
|
||||||
|
|
@ -617,6 +617,18 @@ public sealed class LiveSessionCommandRouterTests
|
||||||
CharacterState: characterState ?? new RuntimeCharacterState(),
|
CharacterState: characterState ?? new RuntimeCharacterState(),
|
||||||
SendSingleCharacterOption: sendSingleCharacterOption ?? ((_, _) => { }),
|
SendSingleCharacterOption: sendSingleCharacterOption ?? ((_, _) => { }),
|
||||||
SaveCharacterOptions: saveCharacterOptions ?? (() => { }),
|
SaveCharacterOptions: saveCharacterOptions ?? (() => { }),
|
||||||
|
SendFellowshipCreate: (_, _) => { },
|
||||||
|
SendFellowshipRecruit: _ => { },
|
||||||
|
SendFellowshipDismiss: _ => { },
|
||||||
|
SendFellowshipQuit: _ => { },
|
||||||
|
SendFellowshipAssignNewLeader: _ => { },
|
||||||
|
SendFellowshipChangeOpenness: _ => { },
|
||||||
|
SendFellowshipUpdateRequest: _ => { },
|
||||||
|
SendAllegianceSwear: _ => { },
|
||||||
|
SendAllegianceBreak: _ => { },
|
||||||
|
SendAllegianceKick: _ => { },
|
||||||
|
SendAllegianceInfoRequest: _ => { },
|
||||||
|
SendAllegianceUpdateRequest: _ => { },
|
||||||
Log: log));
|
Log: log));
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue