Events and Delegates¶
This page documents all events fired by FWPartySystem, their flow through the beacon architecture, and patterns for binding them in C++ and Blueprints.
Delegate Summary¶
Party Lifecycle¶
| Delegate | Fires On | Signature |
|---|---|---|
OnPartyCreated |
Leader only | (const FFWPartyInfo& PartyInfo) |
OnPartyDisbanded |
All members | () |
OnPartyUpdated |
All members | (const FFWPartyInfo& PartyInfo) |
Membership¶
| Delegate | Fires On | Signature |
|---|---|---|
OnMemberJoined |
All existing members | (const FFWPartyMemberInfo& MemberInfo) |
OnMemberLeft |
All remaining members | (const FFWPartyMemberInfo& MemberInfo) |
OnMemberKicked |
All remaining members | (const FFWPartyMemberInfo& MemberInfo) |
OnLeaderChanged |
All members | (const FFWPartyMemberInfo& NewLeader) |
Local Player¶
| Delegate | Fires On | Signature |
|---|---|---|
OnLocalPlayerJoinedParty |
Joining player | (const FFWPartyInfo& PartyInfo) |
OnLocalPlayerLeftParty |
Leaving/kicked player | () |
OnJoinPartyResult |
Joining player | (EFWPartyJoinResult Result) |
Invitations¶
| Delegate | Fires On | Signature |
|---|---|---|
OnInvitationReceived |
Target player | (const FFWPartyInvitation& Invitation) |
OnInvitationExpired |
Target player | (const FString& InvitationId) |
Binding Patterns¶
C++ Dynamic Binding¶
void AMyPlayerController::BeginPlay()
{
Super::BeginPlay();
// Bind lifecycle events
PartyManager->OnPartyCreated.AddDynamic(this, &AMyPlayerController::HandlePartyCreated);
PartyManager->OnPartyDisbanded.AddDynamic(this, &AMyPlayerController::HandlePartyDisbanded);
PartyManager->OnPartyUpdated.AddDynamic(this, &AMyPlayerController::HandlePartyUpdated);
// Bind membership events
PartyManager->OnMemberJoined.AddDynamic(this, &AMyPlayerController::HandleMemberJoined);
PartyManager->OnMemberLeft.AddDynamic(this, &AMyPlayerController::HandleMemberLeft);
PartyManager->OnMemberKicked.AddDynamic(this, &AMyPlayerController::HandleMemberKicked);
PartyManager->OnLeaderChanged.AddDynamic(this, &AMyPlayerController::HandleLeaderChanged);
// Bind local player events
PartyManager->OnJoinPartyResult.AddDynamic(this, &AMyPlayerController::HandleJoinResult);
PartyManager->OnLocalPlayerJoinedParty.AddDynamic(this, &AMyPlayerController::HandleLocalJoined);
PartyManager->OnLocalPlayerLeftParty.AddDynamic(this, &AMyPlayerController::HandleLocalLeft);
// Bind invitation events
PartyManager->OnInvitationReceived.AddDynamic(this, &AMyPlayerController::HandleInvitationReceived);
PartyManager->OnInvitationExpired.AddDynamic(this, &AMyPlayerController::HandleInvitationExpired);
}
UFUNCTION Requirement
All dynamic delegate handler functions must be marked with UFUNCTION(). Forgetting this macro will compile but crash at runtime when the delegate attempts to fire.
Blueprint Binding¶
In Blueprints, drag from the Party Manager Component reference and select Assign on the desired event. The editor will create an event node automatically.
Common pattern for a party HUD widget:
- Get a reference to the owning Player Controller's Party Manager Component.
- Bind On Party Updated to refresh the member roster.
- Bind On Invitation Received to show an invitation popup.
- Bind On Local Player Left Party to hide the party UI.
Event Flow Diagrams¶
Create Party Flow¶
Player A calls CreateParty()
|
v
BeaconClient -> SendCreatePartyRequest() -> [Network] -> BeaconHost
|
v
BeaconHost: Validate (not already in party)
|
v
BeaconHost: Create AFWPartyHostObject
|
v
BeaconHost: Generate JoinCode, assign PartyId
|
v
BeaconHost -> ClientReceivePartyUpdate() -> [Network] -> BeaconClient
|
v
PartyManagerComponent:
+-- OnPartyCreated(PartyInfo)
+-- OnLocalPlayerJoinedParty(PartyInfo)
Join by Code Flow¶
Player B calls JoinPartyByCode("ABC123")
|
v
BeaconClient -> SendJoinByCodeRequest("ABC123") -> [Network] -> BeaconHost
|
v
BeaconHost: FindPartyByCode("ABC123")
|
+--[Not Found]-> ClientReceiveJoinResult(InvalidCode)
| |
| v
| Player B: OnJoinPartyResult(InvalidCode)
|
+--[Found, Full]-> ClientReceiveJoinResult(PartyFull)
|
+--[Found, InviteOnly]-> ClientReceiveJoinResult(InviteOnly)
|
+--[Found, OK]--> HostObject: AddMember(PlayerB_Info)
|
v
HostObject: BroadcastStateUpdate()
|
+---> Player B: OnJoinPartyResult(Success)
| OnLocalPlayerJoinedParty(PartyInfo)
|
+---> Player A: OnMemberJoined(PlayerB_Info)
OnPartyUpdated(PartyInfo)
Invitation Flow¶
Player A calls InvitePlayer(PlayerB_NetId)
|
v
BeaconClient -> SendInviteRequest(PlayerB_NetId) -> [Network] -> BeaconHost
|
v
BeaconHost: Validate (A is in party, B is not, party not full)
|
v
BeaconHost: Create FFWPartyInvitation, start expiry timer
|
v
BeaconHost -> ClientReceiveInvitation(Invitation) -> [Network] -> Player B's BeaconClient
|
v
Player B: OnInvitationReceived(Invitation)
|
+--[Accept]-> Player B calls AcceptInvitation(InvitationId)
| |
| v
| (Same flow as JoinByCode, but bypasses privacy check)
|
+--[Decline]-> Player B calls DeclineInvitation(InvitationId)
| |
| v
| Invitation removed locally, no notification to sender
|
+--[Timeout]-> Expiry timer fires on BeaconHost
|
v
BeaconHost -> ClientReceiveInvitationExpired(InvitationId)
|
v
Player B: OnInvitationExpired(InvitationId)
Leave / Kick Flow¶
Leave:
Player calls LeaveParty()
|
v
BeaconClient -> SendLeaveRequest() -> BeaconHost
|
v
BeaconHost: RemoveMember()
|
+--[Was Leader, others remain]-> TransferLeadership()
| |
| v
| All members: OnLeaderChanged(NewLeader)
|
+--[No members remain]-> Disband party
| |
| v
| (All clients already left)
|
v
Leaving player: OnLocalPlayerLeftParty()
Remaining members: OnMemberLeft(LeavingMemberInfo)
OnPartyUpdated(PartyInfo)
Kick:
Leader calls KickMember(TargetId)
|
v
(Same as Leave, but kicked player receives OnLocalPlayerLeftParty
and remaining members receive OnMemberKicked instead of OnMemberLeft)
Event Ordering Guarantees¶
The following ordering guarantees are maintained:
OnJoinPartyResult(Success)always fires beforeOnLocalPlayerJoinedParty.OnMemberJoinedalways fires on existing members beforeOnPartyUpdated.OnLeaderChangedalways fires beforeOnMemberLeftwhen a leader leaves.OnLocalPlayerLeftPartyalways fires after all server-side cleanup is complete.OnPartyDisbandedfires only once per party lifecycle, and only after all members have been notified.
No Guaranteed Cross-Client Ordering
Events are delivered reliably but the order in which different clients receive the same event is not guaranteed. Client A may see OnMemberJoined before Client B, depending on network conditions.
Next Steps¶
- See Party Manager Component for the full function API.
- See Types Reference for delegate type declarations.
- See Tutorial for practical examples of event handling in a complete implementation.