// // Licensed under the MIT License. See LICENSE file in the project root for full license information. // namespace MUnique.OpenMU.GameLogic.MuHelper; using MUnique.OpenMU.Interfaces; /// /// Handles auto-accepting incoming party requests from friends and guild members /// based on the player's MU Helper settings flags. /// public static class PartyRequestHandler { /// /// Automatically accepts a party request if the receiver has the relevant flag enabled. /// /// The player receiving the party request. /// The player who sent the party request. /// True if the criteria matched (auto-accept was attempted, regardless of success); false if no criteria matched. public static async ValueTask TryAutoAcceptPartyRequestAsync(Player receiver, Player requester) { var settings = receiver.MuHelperSettings; if (settings is null) { return false; } if (settings.AutoAcceptGuild && AreGuildMembers(receiver, requester)) { await AcceptPartyRequestAsync(receiver, requester).ConfigureAwait(false); return true; } if (settings.AutoAcceptFriend && await AreFriendsAsync(receiver, requester).ConfigureAwait(false)) { await AcceptPartyRequestAsync(receiver, requester).ConfigureAwait(false); return true; } if (settings.AutoAcceptAnyone && await Bots.BotPartyHandler.TryScheduleAcceptAsync(receiver, requester).ConfigureAwait(false)) { // The actual accept happens shortly afterwards in the bot's own tick (a human-like delay); // all bot-specific safeguards live in the handler, so this stays a thin criteria branch. return true; } return false; } private static bool AreGuildMembers(Player receiver, Player requester) { return receiver.GuildStatus?.GuildId != null && receiver.GuildStatus.GuildId == requester.GuildStatus?.GuildId; } private static async ValueTask AreFriendsAsync(Player receiver, Player requester) { if (receiver.SelectedCharacter is null || requester.SelectedCharacter is null) { return false; } var friendServer = (receiver.GameContext as IGameServerContext)?.FriendServer; if (friendServer is null) { return false; } return await friendServer.IsFriendAsync(receiver.SelectedCharacter.Name, requester.SelectedCharacter.Name).ConfigureAwait(false); } private static async ValueTask AcceptPartyRequestAsync(Player receiver, Player requester) { bool success = false; try { if (receiver.Party != null) { if (requester.Party == null) { // Receiver is the offline party master; add the solo requester to the existing party. success = await receiver.Party.AddAsync(requester).ConfigureAwait(false); } } else if (requester.Party != null) { // Requester already has a party; add the offline receiver to it. success = await requester.Party.AddAsync(receiver).ConfigureAwait(false); } else { // Neither side has a party; create a new one. var party = receiver.GameContext.PartyManager.CreateParty(); success = await party.AddAsync(requester).ConfigureAwait(false) && await party.AddAsync(receiver).ConfigureAwait(false); } } finally { await receiver.PlayerState.TryAdvanceToAsync(PlayerState.EnteredWorld).ConfigureAwait(false); receiver.LastPartyRequester = null; } return success; } }