Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for "freestyle" in multiplayer #11760

Merged
merged 15 commits into from
Jan 16, 2025
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

use App\Http\Controllers\Controller as BaseController;
use App\Libraries\ClientCheck;
use App\Models\Beatmap;
use App\Models\Multiplayer\PlaylistItem;
use App\Models\Multiplayer\PlaylistItemUserHighScore;
use App\Models\Multiplayer\Room;
Expand Down
6 changes: 6 additions & 0 deletions app/Models/Multiplayer/PlaylistItem.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
* @property int $owner_id
* @property int|null $playlist_order
* @property json|null $required_mods
* @property bool $freestyle
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

needs to be added into $casts as well.

(unrelated to this, why is the mods cast of this object but DailyChallengeQueueItem array 🤔 )

* @property Room $room
* @property int $room_id
* @property int|null $ruleset_id
Expand Down Expand Up @@ -64,6 +65,7 @@ public static function fromJsonParams(User $owner, $json)
$obj->$field = $value;
}

$obj->freestyle = get_bool($json['freestyle'] ?? false);
$obj->max_attempts = get_int($json['max_attempts'] ?? null);

$modsHelper = app('mods');
Expand Down Expand Up @@ -169,6 +171,10 @@ private function assertValidRuleset()

private function assertValidMods()
{
if ($this->freestyle && (count($this->allowed_mods) === 0 || count($this->required_mods) === 0)) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't these be !== 0?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes indeed 🤨

throw new InvariantException("mod isn't allowed in freestyle");
}

$allowedModIds = array_column($this->allowed_mods, 'acronym');
$requiredModIds = array_column($this->required_mods, 'acronym');

Expand Down
37 changes: 30 additions & 7 deletions app/Models/Multiplayer/Room.php
Original file line number Diff line number Diff line change
Expand Up @@ -662,9 +662,21 @@ public function startPlay(User $user, PlaylistItem $playlistItem, array $rawPara
{
priv_check_user($user, 'MultiplayerScoreSubmit', $this)->ensureCan();

$this->assertValidStartPlay($user, $playlistItem);
$params = get_params($rawParams, null, [
'beatmap_hash',
'beatmap_id:int',
'build_id',
'ruleset_id:int',
], ['null_missing' => true]);

if (!$playlistItem->freestyle) {
$params['beatmap_id'] = $playlistItem->beatmap_id;
$params['ruleset_id'] = $playlistItem->ruleset_id;
}

return $this->getConnection()->transaction(function () use ($playlistItem, $rawParams, $user) {
$this->assertValidStartPlay($user, $playlistItem, $params);

return $this->getConnection()->transaction(function () use ($params, $playlistItem, $user) {
$agg = UserScoreAggregate::new($user, $this);
if ($agg->wasRecentlyCreated) {
$this->incrementInstance('participant_count');
Expand All @@ -676,11 +688,11 @@ public function startPlay(User $user, PlaylistItem $playlistItem, array $rawPara
$playlistItemAgg->updateUserAttempts();

return ScoreToken::create([
'beatmap_hash' => get_string($rawParams['beatmap_hash'] ?? null),
'beatmap_id' => $playlistItem->beatmap_id,
'build_id' => $rawParams['build_id'],
'beatmap_hash' => $params['beatmap_hash'],
'beatmap_id' => $params['beatmap_id'],
'build_id' => $params['build_id'],
'playlist_item_id' => $playlistItem->getKey(),
'ruleset_id' => $playlistItem->ruleset_id,
'ruleset_id' => $params['ruleset_id'],
'user_id' => $user->getKey(),
]);
});
Expand Down Expand Up @@ -741,14 +753,25 @@ private function assertValidStartGame()
}
}

private function assertValidStartPlay(User $user, PlaylistItem $playlistItem)
private function assertValidStartPlay(User $user, PlaylistItem $playlistItem, array $params): void
{
// todo: check against room's end time (to see if player has enough time to play this beatmap) and is under the room's max attempts limit

if ($this->hasEnded()) {
throw new InvariantException('Room has already ended.');
}

if ($playlistItem->freestyle) {
// assert the beatmap_id is part of playlist item's beatmapset
$beatmapsetIdCount = Beatmap
::whereKey([$playlistItem->beatmap_id, $params['beatmap_id']])
->distinct('beatmapset_id')
->count();
if ($beatmapsetIdCount !== 1) {
throw new InvariantException('Specified beatmap_id is not allowed');
}
}

$userId = $user->getKey();
if ($this->max_attempts !== null) {
$roomStats = $this->userHighScores()->where('user_id', $userId)->first();
Expand Down
1 change: 1 addition & 0 deletions app/Transformers/Multiplayer/PlaylistItemTransformer.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public function transform(PlaylistItem $item)
'ruleset_id' => $item->ruleset_id,
'allowed_mods' => $item->allowed_mods,
'required_mods' => $item->required_mods,
'freestyle' => $item->freestyle,
'expired' => $item->expired,
'owner_id' => $item->owner_id,
'playlist_order' => $item->playlist_order,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

// Copyright (c) ppy Pty Ltd <[email protected]>. Licensed under the GNU Affero General Public License v3.0.
// See the LICENCE file in the repository root for full licence text.

declare(strict_types=1);

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('multiplayer_playlist_items', function (Blueprint $table) {
$table->boolean('freestyle')->after('required_mods')->default(false);
});
}

/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('multiplayer_playlist_items', function (Blueprint $table) {
$table->dropColumn('freestyle');
});
}
};
Loading