Skip to content

Allow playlist items with both freestyle and mods #12074

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

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 5 additions & 7 deletions app/Models/Multiplayer/PlaylistItem.php
Original file line number Diff line number Diff line change
Expand Up @@ -172,11 +172,9 @@ private function assertValidRuleset()

private function assertValidMods()
{
if ($this->freestyle) {
if (count($this->allowed_mods) !== 0 || count($this->required_mods) !== 0) {
throw new InvariantException("mod isn't allowed in freestyle");
}
return;
// Freestyle unconditionally allows all freemods, so we'll expect them to not be specified.
if ($this->freestyle && count($this->allowed_mods) !== 0) {
throw new InvariantException('allowed mods cannot be specified on freestyle items');
}

$allowedModIds = array_column($this->allowed_mods, 'acronym');
Expand All @@ -189,8 +187,8 @@ private function assertValidMods()

$isRealtimeRoom = $this->room->isRealtime();
$modsHelper = app('mods');
$modsHelper->assertValidForMultiplayer($this->ruleset_id, $allowedModIds, $isRealtimeRoom, false);
$modsHelper->assertValidForMultiplayer($this->ruleset_id, $requiredModIds, $isRealtimeRoom, true);
$modsHelper->assertValidForMultiplayer($this->ruleset_id, $allowedModIds, false, $isRealtimeRoom, $this->freestyle);
$modsHelper->assertValidForMultiplayer($this->ruleset_id, $requiredModIds, true, $isRealtimeRoom, $this->freestyle);
$modsHelper->assertValidMultiplayerExclusivity($this->ruleset_id, $requiredModIds, $allowedModIds);
}
}
22 changes: 18 additions & 4 deletions app/Singletons/Mods.php
Original file line number Diff line number Diff line change
Expand Up @@ -92,21 +92,35 @@ public function __construct()
}
}

public function assertValidForMultiplayer(int $rulesetId, array $ids, bool $isRealtime, bool $isRequired): void
/**
* Determines whether the given mods are valid for a playlist item.
*
* @param int $rulesetId The ruleset from which the mods originate.
* @param array $ids An array containing the mod acronyms to test.
* @param bool $required True if the mods are intended as "required" mods on the target playlist item. False if they're intended as "allowed" mods.
* @param bool $realtime Whether the room is a realtime match.
* @param bool $freestyle Whether the target playlist item enables freestyle mode.
* @throws InvariantException When any of the given mods are not valid.
*/
public function assertValidForMultiplayer(int $rulesetId, array $ids, bool $required, bool $realtime, bool $freestyle): void
{
$this->validateSelection($rulesetId, $ids);

if ($isRealtime) {
$attr = $isRequired ? 'ValidForMultiplayer' : 'ValidForMultiplayerAsFreeMod';
if ($realtime) {
$attr = $required ? 'ValidForMultiplayer' : 'ValidForMultiplayerAsFreeMod';
} else {
$attr = 'UserPlayable';
}

foreach ($ids as $id) {
$mod = $this->mods[$rulesetId][$id];

if ($freestyle && $required && !$mod['ValidForFreestyleAsRequiredMod']) {
throw new InvariantException("mod cannot be set as required on freestyle items: {$id}");
}

if (!$mod[$attr]) {
$messageType = $isRequired ? 'required' : 'allowed';
$messageType = $required ? 'required' : 'allowed';
throw new InvariantException("mod cannot be set as {$messageType}: {$id}");
}
}
Expand Down
1 change: 1 addition & 0 deletions database/factories/Multiplayer/PlaylistItemFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public function definition(): array
'allowed_mods' => [],
'required_mods' => [],
'owner_id' => User::factory(),
'freestyle' => false,
];
}
}
Loading
Loading