1
0
Fork 0
mirror of https://github.com/ninjamuffin99/Funkin.git synced 2025-05-22 07:01:27 +00:00

Properly sort difficulties/variations. Validate variation IDs (alphanumeric only)

This commit is contained in:
EliteMasterEric 2024-09-27 12:21:17 -04:00
parent 378179d1f7
commit b5f3996236

View file

@ -156,6 +156,11 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry<SongMeta
{ {
for (vari in _data.playData.songVariations) for (vari in _data.playData.songVariations)
{ {
if (!validateVariationId(vari)) {
trace(' [WARN] Variation id "$vari" is invalid, skipping...');
continue;
}
var variMeta:Null<SongMetadata> = fetchVariationMetadata(id, vari); var variMeta:Null<SongMetadata> = fetchVariationMetadata(id, vari);
if (variMeta != null) if (variMeta != null)
{ {
@ -407,7 +412,6 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry<SongMeta
if (possibleVariations == null) if (possibleVariations == null)
{ {
possibleVariations = getVariationsByCharacter(currentCharacter); possibleVariations = getVariationsByCharacter(currentCharacter);
possibleVariations.sort(SortUtil.defaultsThenAlphabetically.bind(Constants.DEFAULT_VARIATION_LIST));
} }
if (diffId == null) diffId = listDifficulties(null, possibleVariations)[0]; if (diffId == null) diffId = listDifficulties(null, possibleVariations)[0];
@ -428,7 +432,12 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry<SongMeta
*/ */
public function getVariationsByCharacter(?char:PlayableCharacter):Array<String> public function getVariationsByCharacter(?char:PlayableCharacter):Array<String>
{ {
if (char == null) return variations; if (char == null)
{
var result = variations;
result.sort(SortUtil.defaultsThenAlphabetically.bind(Constants.DEFAULT_VARIATION_LIST));
return result;
}
var result = []; var result = [];
trace('Evaluating variations for ${this.id} ${char.id}: ${this.variations}'); trace('Evaluating variations for ${this.id} ${char.id}: ${this.variations}');
@ -445,6 +454,8 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry<SongMeta
} }
} }
result.sort(SortUtil.defaultsThenAlphabetically.bind(Constants.DEFAULT_VARIATION_LIST));
return result; return result;
} }
@ -465,18 +476,11 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry<SongMeta
if (variationIds.length == 0) return []; if (variationIds.length == 0) return [];
// The difficulties array contains entries like 'normal', 'nightmare-erect', and 'normal-pico', var diffFiltered:Array<String> = variationIds.map(function(variationId:String):Array<String> {
// so we have to map it to the actual difficulty names. var metadata = _metadata.get(variationId);
// We also filter out difficulties that don't match the variation or that don't exist. return metadata?.playData?.difficulties ?? [];
})
var diffFiltered:Array<String> = difficulties.keys() .flatten()
.array()
.map(function(diffId:String):Null<String> {
var difficulty:Null<SongDifficulty> = difficulties.get(diffId);
if (difficulty == null) return null;
if (variationIds.length > 0 && !variationIds.contains(difficulty.variation)) return null;
return difficulty.difficulty;
})
.filterNull() .filterNull()
.distinct(); .distinct();
@ -489,11 +493,15 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry<SongMeta
return false; return false;
}); });
diffFiltered.sort(SortUtil.defaultsThenAlphabetically.bind(Constants.DEFAULT_DIFFICULTY_LIST)); diffFiltered.sort(SortUtil.defaultsThenAlphabetically.bind(Constants.DEFAULT_DIFFICULTY_LIST_FULL));
return diffFiltered; return diffFiltered;
} }
/**
* TODO: This line of code makes me sad, but you can't really fix it without a breaking migration.
* @return `easy`, `erect`, `normal-pico`, etc.
*/
public function listSuffixedDifficulties(variationIds:Array<String>, ?showLocked:Bool, ?showHidden:Bool):Array<String> public function listSuffixedDifficulties(variationIds:Array<String>, ?showLocked:Bool, ?showHidden:Bool):Array<String>
{ {
var result = []; var result = [];
@ -509,6 +517,8 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry<SongMeta
} }
} }
result.sort(SortUtil.defaultsThenAlphabetically.bind(Constants.DEFAULT_DIFFICULTY_LIST_FULL));
return result; return result;
} }
@ -629,6 +639,19 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry<SongMeta
var meta:Null<SongMetadata> = SongRegistry.instance.parseEntryMetadataWithMigration(id, vari, version); var meta:Null<SongMetadata> = SongRegistry.instance.parseEntryMetadataWithMigration(id, vari, version);
return meta; return meta;
} }
static final VARIATION_REGEX = ~/^[a-z][a-z0-9]+$/;
/**
* Validate that the variation ID is valid.
* Auto-accept if it's one of the base game default variations.
* Reject if the ID starts with a number, or contains invalid characters.
*/
static function validateVariationId(variation:String):Bool {
if (Constants.DEFAULT_VARIATION_LIST.contains(variation)) return true;
return VARIATION_REGEX.match(variation);
}
} }
class SongDifficulty class SongDifficulty