diff --git a/src/MHServerEmu.PlayerManagement/Matchmaking/Match.cs b/src/MHServerEmu.PlayerManagement/Matchmaking/Match.cs index 99c1ec0c..c8841e72 100644 --- a/src/MHServerEmu.PlayerManagement/Matchmaking/Match.cs +++ b/src/MHServerEmu.PlayerManagement/Matchmaking/Match.cs @@ -27,7 +27,13 @@ namespace MHServerEmu.PlayerManagement.Matchmaking QueueParams = queueParams; int[] teamLimits = Queue.Prototype.TeamLimits; - if (teamLimits.HasValue()) + + if (queueParams.TeamSizeOverride > 0) + { + _teams.Add(new MatchTeam(0, queueParams.TeamSizeOverride)); + _teams.Add(new MatchTeam(1, queueParams.TeamSizeOverride)); + } + else if (teamLimits.HasValue()) { for (int i = 0; i < teamLimits.Length; i++) { @@ -97,6 +103,11 @@ namespace MHServerEmu.PlayerManagement.Matchmaking return true; } + public bool IsCompatibleWith(in RegionRequestQueueParams queueParams) + { + return QueueParams.TeamSizeOverride == queueParams.TeamSizeOverride; + } + public bool IsReady() { if (IsFull() == false && IsBypass == false && Queue.Prototype.QueueDoNotWaitToFull == false) diff --git a/src/MHServerEmu.PlayerManagement/Matchmaking/RegionRequestQueue.cs b/src/MHServerEmu.PlayerManagement/Matchmaking/RegionRequestQueue.cs index 35b458e5..58729d24 100644 --- a/src/MHServerEmu.PlayerManagement/Matchmaking/RegionRequestQueue.cs +++ b/src/MHServerEmu.PlayerManagement/Matchmaking/RegionRequestQueue.cs @@ -45,7 +45,7 @@ namespace MHServerEmu.PlayerManagement.Matchmaking foreach (Match match in _matches) { - if (match.IsLookingForMore()) + if (match.IsLookingForMore() && match.IsCompatibleWith(queueParams)) lfmMatches.Add(match); } diff --git a/src/MHServerEmu.PlayerManagement/Matchmaking/RegionRequestQueueCommandHandler.cs b/src/MHServerEmu.PlayerManagement/Matchmaking/RegionRequestQueueCommandHandler.cs index b622c041..232d53c4 100644 --- a/src/MHServerEmu.PlayerManagement/Matchmaking/RegionRequestQueueCommandHandler.cs +++ b/src/MHServerEmu.PlayerManagement/Matchmaking/RegionRequestQueueCommandHandler.cs @@ -22,7 +22,7 @@ namespace MHServerEmu.PlayerManagement.Matchmaking } public void HandleCommand(PrototypeId regionRef, PrototypeId difficultyTierRef, PrototypeId metaStateRef, - RegionRequestQueueCommandVar command, ulong regionRequestGroupId, ulong targetPlayerDbId) + RegionRequestQueueCommandVar command, ulong regionRequestGroupId, ulong targetPlayerDbId, int teamSizeOverride = -1) { Logger.Trace($"HandleCommand(): command=[{command}], region=[{regionRef.GetNameFormatted()}], player=[{_player}]"); @@ -31,7 +31,7 @@ namespace MHServerEmu.PlayerManagement.Matchmaking case RegionRequestQueueCommandVar.eRRQC_AddToQueueSolo: case RegionRequestQueueCommandVar.eRRQC_AddToQueueParty: case RegionRequestQueueCommandVar.eRRQC_AddToQueueBypass: - OnAddToQueue(regionRef, difficultyTierRef, metaStateRef, command); + OnAddToQueue(regionRef, difficultyTierRef, metaStateRef, command, teamSizeOverride); break; case RegionRequestQueueCommandVar.eRRQC_RemoveFromQueue: @@ -53,7 +53,8 @@ namespace MHServerEmu.PlayerManagement.Matchmaking } } - private bool OnAddToQueue(PrototypeId regionRef, PrototypeId difficultyTierRef, PrototypeId metaStateRef, RegionRequestQueueCommandVar command) + private bool OnAddToQueue(PrototypeId regionRef, PrototypeId difficultyTierRef, PrototypeId metaStateRef, + RegionRequestQueueCommandVar command, int teamSizeOverride = -1) { RegionRequestQueue queue = PlayerManagerService.Instance.RegionRequestQueueManager.GetRegionRequestQueue(regionRef); if (queue == null) @@ -74,7 +75,7 @@ namespace MHServerEmu.PlayerManagement.Matchmaking // Create region request group MasterParty party = command == RegionRequestQueueCommandVar.eRRQC_AddToQueueParty ? _player.CurrentParty : null; - RegionRequestQueueParams queueParams = new(difficultyTierRef, metaStateRef, command == RegionRequestQueueCommandVar.eRRQC_AddToQueueBypass); + RegionRequestQueueParams queueParams = new(difficultyTierRef, metaStateRef, command == RegionRequestQueueCommandVar.eRRQC_AddToQueueBypass, teamSizeOverride); RegionRequestGroup group = RegionRequestGroup.Create(queue, queueParams, _player, party); if (group == null) diff --git a/src/MHServerEmu.PlayerManagement/Matchmaking/RegionRequestQueueParams.cs b/src/MHServerEmu.PlayerManagement/Matchmaking/RegionRequestQueueParams.cs index 306cae9d..90f8fc74 100644 --- a/src/MHServerEmu.PlayerManagement/Matchmaking/RegionRequestQueueParams.cs +++ b/src/MHServerEmu.PlayerManagement/Matchmaking/RegionRequestQueueParams.cs @@ -10,17 +10,19 @@ namespace MHServerEmu.PlayerManagement.Matchmaking public readonly PrototypeId DifficultyTierRef; public readonly PrototypeId MetaStateRef; public readonly bool IsBypass; + public readonly int TeamSizeOverride; - public RegionRequestQueueParams(PrototypeId difficultyTierRef, PrototypeId metaStateRef, bool isBypass) + public RegionRequestQueueParams(PrototypeId difficultyTierRef, PrototypeId metaStateRef, bool isBypass, int teamSizeOverride) { DifficultyTierRef = difficultyTierRef; MetaStateRef = metaStateRef; IsBypass = isBypass; + TeamSizeOverride = teamSizeOverride; } public override string ToString() { - return $"difficulty={DifficultyTierRef.GetNameFormatted()}, metaState={MetaStateRef.GetNameFormatted()}, isBypass={IsBypass}"; + return $"difficulty={DifficultyTierRef.GetNameFormatted()}, metaState={MetaStateRef.GetNameFormatted()}, isBypass={IsBypass}, teamSizeOverride={TeamSizeOverride}"; } public override int GetHashCode() @@ -40,7 +42,8 @@ namespace MHServerEmu.PlayerManagement.Matchmaking { return DifficultyTierRef == other.DifficultyTierRef && MetaStateRef == other.MetaStateRef && - IsBypass == other.IsBypass; + IsBypass == other.IsBypass && + TeamSizeOverride == other.TeamSizeOverride; } public static bool operator ==(RegionRequestQueueParams left, RegionRequestQueueParams right) diff --git a/src/MHServerEmu.PlayerManagement/PlayerManagerService.cs b/src/MHServerEmu.PlayerManagement/PlayerManagerService.cs index dca9ec71..3b576e61 100644 --- a/src/MHServerEmu.PlayerManagement/PlayerManagerService.cs +++ b/src/MHServerEmu.PlayerManagement/PlayerManagerService.cs @@ -147,6 +147,11 @@ namespace MHServerEmu.PlayerManagement statusDict["PlayerManagerPendingSessions"] = SessionManager.PendingSessionCount; } + public PlayerHandle GetPlayer(ulong playerDbId) + { + return ClientManager.GetPlayer(playerDbId); + } + private void OnRouteMessageBuffer(in ServiceMessage.RouteMessageBuffer routeMessageBuffer) { IFrontendClient client = routeMessageBuffer.Client; diff --git a/src/MHServerEmu.PlayerManagement/Players/PlayerHandle.cs b/src/MHServerEmu.PlayerManagement/Players/PlayerHandle.cs index 60f4215c..71b3b2fa 100644 --- a/src/MHServerEmu.PlayerManagement/Players/PlayerHandle.cs +++ b/src/MHServerEmu.PlayerManagement/Players/PlayerHandle.cs @@ -814,9 +814,9 @@ namespace MHServerEmu.PlayerManagement.Players } public void ReceiveRegionRequestQueueCommand(PrototypeId regionRef, PrototypeId difficultyTierRef, PrototypeId metaStateRef, - RegionRequestQueueCommandVar command, ulong regionRequestGroupId, ulong targetPlayerDbId) + RegionRequestQueueCommandVar command, ulong regionRequestGroupId, ulong targetPlayerDbId, int teamSizeOverride = -1) { - _regionRequestQueueCommandHandler.HandleCommand(regionRef, difficultyTierRef, metaStateRef, command, regionRequestGroupId, targetPlayerDbId); + _regionRequestQueueCommandHandler.HandleCommand(regionRef, difficultyTierRef, metaStateRef, command, regionRequestGroupId, targetPlayerDbId, teamSizeOverride); } public void AddToChatRoom(ChatRoomTypes roomType, ulong roomId) diff --git a/src/MHServerEmu/Commands/Implementations/PvPCommands.cs b/src/MHServerEmu/Commands/Implementations/PvPCommands.cs new file mode 100644 index 00000000..b3966644 --- /dev/null +++ b/src/MHServerEmu/Commands/Implementations/PvPCommands.cs @@ -0,0 +1,73 @@ +using Gazillion; +using MHServerEmu.Commands.Attributes; +using MHServerEmu.Core.Network; +using MHServerEmu.DatabaseAccess.Models; +using MHServerEmu.Games.GameData; +using MHServerEmu.Games.Network; +using MHServerEmu.PlayerManagement; +using MHServerEmu.PlayerManagement.Players; + +namespace MHServerEmu.Commands.Implementations +{ + [CommandGroup("pvp")] + [CommandGroupDescription("Commands related to PvP matchmaking.")] + [CommandGroupUserLevel(AccountUserLevel.User)] + public class PvPCommands : CommandGroup + { + private static readonly PrototypeId RegionRef = + GameDatabase.GetPrototypeRefByName("Metagame/DefenderPvP/Regions/PvPDefenderTier5Region.prototype"); + + private static readonly PrototypeId DifficultyRef = + GameDatabase.GetPrototypeRefByName("Difficulty/Tiers/Tier1Normal.prototype"); + + private string JoinQueue(int size, NetClient client) + { + PlayerConnection playerConnection = (PlayerConnection)client; + var player = playerConnection.Player; + if (player == null) return "Player not found."; + + bool isInParty = player.Party != null && player.Party.NumMembers > 1; + var command = isInParty + ? RegionRequestQueueCommandVar.eRRQC_AddToQueueParty + : RegionRequestQueueCommandVar.eRRQC_AddToQueueSolo; + + var playerManager = ServerManager.Instance.GetGameService(GameServiceType.PlayerManager) as PlayerManagerService; + if (playerManager == null) return "Failed to connect to the player manager."; + + PlayerHandle destPlayer = playerManager.GetPlayer(playerConnection.PlayerDbId); + destPlayer.ReceiveRegionRequestQueueCommand(RegionRef, DifficultyRef, PrototypeId.Invalid, command, 0, 0, size); + + return $"Queued for {size}v{size} PvP! ({(isInParty ? "Party" : "Solo")})"; + } + + [Command("1v1")] + [CommandDescription("Join 1v1 PvP queue.")] + [CommandUsage("pvp 1v1")] + [CommandInvokerType(CommandInvokerType.Client)] + public string Queue1v1(string[] @params, NetClient client) => JoinQueue(1, client); + + [Command("2v2")] + [CommandDescription("Join 2v2 PvP queue.")] + [CommandUsage("pvp 2v2")] + [CommandInvokerType(CommandInvokerType.Client)] + public string Queue2v2(string[] @params, NetClient client) => JoinQueue(2, client); + + [Command("3v3")] + [CommandDescription("Join 3v3 PvP queue.")] + [CommandUsage("pvp 3v3")] + [CommandInvokerType(CommandInvokerType.Client)] + public string Queue3v3(string[] @params, NetClient client) => JoinQueue(3, client); + + [Command("4v4")] + [CommandDescription("Join 4v4 PvP queue.")] + [CommandUsage("pvp 4v4")] + [CommandInvokerType(CommandInvokerType.Client)] + public string Queue4v4(string[] @params, NetClient client) => JoinQueue(4, client); + + [Command("5v5")] + [CommandDescription("Join 5v5 PvP queue.")] + [CommandUsage("pvp 5v5")] + [CommandInvokerType(CommandInvokerType.Client)] + public string Queue5v5(string[] @params, NetClient client) => JoinQueue(-1, client); + } +}