diff --git a/dist/app/Http/Controllers/Api/Matchmaking/MatchmakingController.php b/dist/app/Http/Controllers/Api/Matchmaking/MatchmakingController.php index ea62b04..0b6035d 100644 --- a/dist/app/Http/Controllers/Api/Matchmaking/MatchmakingController.php +++ b/dist/app/Http/Controllers/Api/Matchmaking/MatchmakingController.php @@ -109,6 +109,19 @@ public function seedFilePost(string $gameVersion, string $seed, string $mapName) return response('', 200); } + public function deleteUserFromMatch(string $matchId, string $userId) + { + $foundGame = Game::find($matchId); + $userToRemove = User::find($userId); + $requestUser = Auth::user(); + + // Block request if it doesn't come from the host + if($foundGame === null || $foundGame->creator != $requestUser) + return response('Action not allowed, you are not the creator of the match.', 403); + + $foundGame->players()->detach($userToRemove); + } + public function endOfMatch(EndOfMatchRequest $request) { $game = Game::find($request->matchId); @@ -264,12 +277,6 @@ protected function processQueue(): void if($availableMatchConfigs->isEmpty()) return; - $selectedConfig = MatchConfiguration::selectRandomConfigByWeight($availableMatchConfigs); - - // Should never happen, but just to be careful - if($selectedConfig === null) - return; - $runners = new Collection(); $hunters = new Collection(); @@ -281,6 +288,14 @@ protected function processQueue(): void $runners->add($player); }); + $this->tryFillOpenGames($hunters, $runners); + + $selectedConfig = MatchConfiguration::selectRandomConfigByWeight($availableMatchConfigs); + + // Should never happen, but just to be careful + if($selectedConfig === null) + return; + $hunterGroupsSet = $this->determineMatchingPlayers($hunters, $selectedConfig->hunters); $runnerGroupsSet = $this->determineMatchingPlayers($runners, $selectedConfig->runners); @@ -316,6 +331,59 @@ protected function processQueue(): void $newGame->determineHost(); } + protected function tryFillOpenGames(Collection|array &$hunters, Collection|array &$runners) + { + $openGames = Game::where('status', '=', MatchStatus::Opened->value)->get(); + + foreach ($openGames as $game) { + $neededPlayers = $game->remainingPlayerCount(); + + // game is full and doesn't need filling + if($neededPlayers->getTotal() == 0) + continue; + + if($neededPlayers->hunters > 0) { + $hunterGroupsSet = $this->determineMatchingPlayers($hunters, $neededPlayers->hunters); + + // see if there are any group combinations possible to fill the game + if(count($hunterGroupsSet) === 0) + continue; + + // use biggest groups first + rsort($hunterGroupsSet, SORT_NUMERIC); + + foreach ($hunterGroupsSet as $groupSize) { + $foundQueuedPlayerIndex = $hunters->search(function (QueuedPlayer $hunter) use ($groupSize) { + return ($hunter->following_users_count + 1) === $groupSize; + }); + + $foundHunter = $hunters->pull($foundQueuedPlayerIndex); + $game->addQueuedPlayer($foundHunter); + } + } + + if($neededPlayers->runners > 0) { + $runnerGroupSet = $this->determineMatchingPlayers($runners, $neededPlayers->runners); + + // see if there are any group combinations possible to fill the game + if(count($runnerGroupSet) === 0) + continue; + + // use biggest groups first + rsort($runnerGroupSet, SORT_NUMERIC); + + foreach ($runnerGroupSet as $groupSize) { + $foundQueuedPlayerIndex = $hunters->search(function (QueuedPlayer $hunter) use ($groupSize) { + return ($hunter->following_users_count + 1) === $groupSize; + }); + + $foundRunner = $hunters->pull($foundQueuedPlayerIndex); + $game->addQueuedPlayer($foundRunner); + } + } + } + } + protected function removeUserFromGame(User $user, Game $game) { $game->players()->detach($user); diff --git a/dist/app/Models/Game/Matchmaking/Game.php b/dist/app/Models/Game/Matchmaking/Game.php index becc9c3..60eddd0 100644 --- a/dist/app/Models/Game/Matchmaking/Game.php +++ b/dist/app/Models/Game/Matchmaking/Game.php @@ -66,6 +66,11 @@ public function determineHost(): void $this->save(); } + /** + * Get the number of needed players to fill the game. + * + * @return MatchmakingPlayerCount + */ public function remainingPlayerCount(): MatchmakingPlayerCount { $players = $this->players; diff --git a/dist/routes/deathgardenApi.php b/dist/routes/deathgardenApi.php index 91609ee..c4478d3 100644 --- a/dist/routes/deathgardenApi.php +++ b/dist/routes/deathgardenApi.php @@ -71,9 +71,7 @@ Route::put('match/{matchId}/Close', [MatchmakingController::class, 'close']); Route::put('match/{matchId}/Kill', [MatchmakingController::class, 'kill']); Route::put('match/{matchId}/Quit', [MatchmakingController::class, 'quit']); - - Route::post('file/{gameVersion}/{seed}/{mapName}', [MatchmakingController::class, 'seedFilePost']); - Route::get('file/{gameVersion}/{seed}/{mapName}', [MatchmakingController::class, 'seedFileGet']); + Route::delete('match/{matchId}/user/{$userId}', [MatchmakingController::class, 'deleteUserFromMatch']); }); diff --git a/dist/routes/web.php b/dist/routes/web.php index 3f1f71f..4ddb4ea 100644 --- a/dist/routes/web.php +++ b/dist/routes/web.php @@ -1,5 +1,6 @@