Peppy BOM fix
This commit is contained in:
@@ -17,7 +17,10 @@ Pull requests are welcome! I doubt this project would get any traffic, so feel f
|
|||||||
- [x] Replace all backgrounds with 1x1 black images
|
- [x] Replace all backgrounds with 1x1 black images
|
||||||
- [x] Remove storyboard specific files
|
- [x] Remove storyboard specific files
|
||||||
- [x] Remove background videos
|
- [x] Remove background videos
|
||||||
- [x] Remove junk files (skins, hitsounds, leftovers from mapping etc.)
|
- [x] Remove beatmap skins
|
||||||
|
- [x] Remove beatmap keyed hitsounds
|
||||||
|
- [x] Remove beatmap default hitsounds
|
||||||
|
- [x] Remove junk files (mapping garbage, unused storyboard, random files, etc.)
|
||||||
- [ ] Export maps to .osz
|
- [ ] Export maps to .osz
|
||||||
- [ ] Delete maps based on star difficulty
|
- [ ] Delete maps based on star difficulty
|
||||||
- [ ] Blacklist: the maps that should not be touched by this program
|
- [ ] Blacklist: the maps that should not be touched by this program
|
||||||
|
|||||||
+119
-26
@@ -1,6 +1,44 @@
|
|||||||
<?php
|
<?php
|
||||||
class optimizer
|
class optimizer
|
||||||
{
|
{
|
||||||
|
public static function is_default_hitsound(string $path) : bool
|
||||||
|
{
|
||||||
|
$string = strtolower(basename($path));
|
||||||
|
$pattern = '(taiko-)?(drum|normal|soft|nightcore)-((hit|slider)(normal|clap|finish|whistle|tick|slide))\d*\.([wW][aA][vV]|[mM][pP]3|[oO][gG][gG])';
|
||||||
|
return mb_ereg_match($pattern, $string);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function is_skinnable_sound(string $path) : bool
|
||||||
|
{
|
||||||
|
$string = strtolower(basename($path));
|
||||||
|
// take your time to appreciate this extremely performance penalty inducing line, then look for a skin image one too
|
||||||
|
$pattern = '((heartbeat|seeya|welcome|key-(confirm|delete|movement|press)|back-button-(click|hover)|check-(on|off)|click-(close|short|short-confirm)|(menu|pause)(click|back|hit|-(back|charts|direct|edit|exit|freeplay|multiplayer|options|play|continue|retry|loop))?(-(click|hover))?|select-(expand|difficulty)|shutter|sliderbar|whoosh|match-(confirm|join|leave|(not)?ready|start)|metronomelow|count(\d+s)?|gos|readys|comboburst|combobreak|failsound|section(pass|fail)|applause|spinner(spin|bonus))|(taiko-)?(drum|normal|soft|nightcore)-((hit|slider)(normal|clap|finish|whistle|tick|slide)))-?\d*\.([wW][aA][vV]|[mM][pP]3|[oO][gG][gG])';
|
||||||
|
return mb_ereg_match($pattern, $string);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function is_skinnable_image(string $path) : bool
|
||||||
|
{
|
||||||
|
$string = strtolower(basename($path));
|
||||||
|
// take a look at the sound version too
|
||||||
|
$pattern = '(mania-|taiko-?)?((key|note)(\d+|[sS])[dDhHlLtT]?|stage-(right|left|bottom|light|hint)|warningarrow|pippidon(clear|fail|idle|kiai)|bigcircle|drum-(inner|outer)|roll-(middle|end)|bar-(left|right)(-glow)?|mode-(osu|taiko|fruits|mania)(-med|-small)?|menu-(osu|background|snow|back|button-background)|button-(left|middle|right)|cursor(middle|trail|-(smoke|ripple))?|welcome_text|playfield|selection-(selectoptions(-over)?|mod-(novideo|autoplay|cinema|doubletime|easy|fadein|flashlight|halftime|hardrock|hidden|key(\d+|coop)|mirror|nightcore|nofail|perfect|random|relax2?|spunout|suddendeath|target|freemodallowed|touchdevice)|(mod[es]|random|options)(-over)?|tab)|options-offset-tick|play-(skip|unranked|warningarrow)|arrow-(pause|warning)|masking-border|multi-skipped|section-(fail|pass)|count|go|ready|hit|inputoverlay-(background|key)|pause-(overlay|back|continue|replay|retry)|scorebar-(bg|colou?r|ki|kidanger2?|marker)|score(entry)?(-(percent|x))?|ranking-([xXsSaAbBcCdD][hH]?|back|accuracy|graph|maxcombo|panel|perfect|title|replay|retry|winner)(-small)?|fail-background|volume-bg|comboburst(-(fruits|mania))?|default|(approach|hit)circle(select)?|followpoint|lighting[lLnN]?|slider((start|end)circle|(score)?point|followcircle|b(-(nd|spec))?|-(fail|flower-group))?|reversearrow|spinner-(approachcircle|rpm|clear|spin|background|circle|metre|osu|glow|bottom|top|middle2?|warning)|particle|fruit-(catcher-(idle|fail|kiai)|ryuuta|pear|grapes|apple|orange|bananas|drop)|star|coin|fps(-fps)?)(-?overlay)?(-?(\d+|comma|dot)[kg]?)*(@2x)?\.([pP][nN][gG]|[jJ][pP][eE]?[gG])(-effect)?';
|
||||||
|
return mb_ereg_match($pattern, $string);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function is_skinnable_other(string $path) : bool
|
||||||
|
{
|
||||||
|
$string = strtolower(basename($path));
|
||||||
|
if (strtolower($string) == "skin.ini") return true;
|
||||||
|
if (mb_stripos($string, "k.ini") !== false) return true; // legacy mania ini
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function is_skinnable(string $path) : bool
|
||||||
|
{
|
||||||
|
return self::is_skinnable_sound($path) ||
|
||||||
|
self::is_skinnable_image($path) ||
|
||||||
|
self::is_skinnable_other($path);
|
||||||
|
}
|
||||||
|
|
||||||
public static function blacken_image(string $file) : void
|
public static function blacken_image(string $file) : void
|
||||||
{
|
{
|
||||||
$black_png = "./resources/black.png";
|
$black_png = "./resources/black.png";
|
||||||
@@ -27,7 +65,7 @@ class optimizer
|
|||||||
{
|
{
|
||||||
foreach ($library->get_videos() as $file)
|
foreach ($library->get_videos() as $file)
|
||||||
{
|
{
|
||||||
unlink($file);
|
if (file_exists($file)) unlink($file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,12 +73,12 @@ class optimizer
|
|||||||
{
|
{
|
||||||
foreach ($library->get_storyboards() as $file)
|
foreach ($library->get_storyboards() as $file)
|
||||||
{
|
{
|
||||||
unlink($file);
|
if (file_exists($file)) unlink($file);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($library->get_osb_files() as $file)
|
foreach ($library->get_osb_files() as $file)
|
||||||
{
|
{
|
||||||
unlink($file);
|
if (file_exists($file)) unlink($file);
|
||||||
}
|
}
|
||||||
|
|
||||||
$empty = self::build_empty_dir_list($library);
|
$empty = self::build_empty_dir_list($library);
|
||||||
@@ -53,30 +91,40 @@ class optimizer
|
|||||||
private static function build_removand_sublist(string $folder) : array
|
private static function build_removand_sublist(string $folder) : array
|
||||||
{
|
{
|
||||||
$queue = array();
|
$queue = array();
|
||||||
|
$lowercase = array();
|
||||||
|
|
||||||
foreach (glob(utils::globsafe($folder) . "/*") as $file)
|
foreach (glob(utils::globsafe($folder) . "/*") as $file)
|
||||||
{
|
{
|
||||||
if (is_dir($file))
|
if (is_dir($file))
|
||||||
{
|
{
|
||||||
$queue = array_merge($queue, self::build_removand_sublist($file)); // recursion
|
list($new_queue, $new_lowercase) = self::build_removand_sublist($file); // recursion
|
||||||
|
|
||||||
|
$lowercase = array_merge($lowercase, $new_lowercase);
|
||||||
|
$queue = array_merge($queue, $new_queue);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$queue[] = strtolower($file);
|
$queue[] = $file;
|
||||||
|
$lowercase[] = strtolower($file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $queue;
|
return array($queue, $lowercase);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function build_removand_list(osu_library $library) : array
|
public static function build_removand_list(osu_library $library) : array
|
||||||
{
|
{
|
||||||
$queue = array();
|
$queue = array();
|
||||||
|
$lowercase = array();
|
||||||
|
|
||||||
foreach ($library->get_folders() as $folder)
|
foreach ($library->get_folders() as $folder)
|
||||||
{
|
{
|
||||||
$queue = array_merge($queue, self::build_removand_sublist($folder));
|
list($new_queue, $new_lowercase) = self::build_removand_sublist($folder);
|
||||||
|
$queue = array_merge($queue, $new_queue);
|
||||||
|
$lowercase = array_merge($lowercase, $new_lowercase);
|
||||||
}
|
}
|
||||||
return $queue;
|
|
||||||
|
return array($queue, $lowercase);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function build_empty_dir_sublist(string $folder) : array
|
public static function build_empty_dir_sublist(string $folder) : array
|
||||||
@@ -114,44 +162,89 @@ class optimizer
|
|||||||
|
|
||||||
public static function build_excluded_list(osu_library $library) : array
|
public static function build_excluded_list(osu_library $library) : array
|
||||||
{
|
{
|
||||||
$bg = $library->get_backgrounds();
|
$background_files = $library->get_backgrounds();
|
||||||
$vid = $library->get_videos();
|
$video_files = $library->get_videos();
|
||||||
$sb = $library->get_storyboards();
|
$storyboard_files = $library->get_storyboards();
|
||||||
$a = $library->get_audiofiles();
|
$hitsound_files = $library->get_hitsounds();
|
||||||
$sbf = $library->get_osb_files();
|
$audio_files = $library->get_audiofiles();
|
||||||
$osf = $library->get_osu_files();
|
$osb_files = $library->get_osb_files();
|
||||||
$excluded = array_merge($bg, $vid, $sb, $a, $sbf, $osf);
|
$osu_files = $library->get_osu_files();
|
||||||
|
|
||||||
$lowercase = array();
|
$essential_excluded = array_merge($background_files, $video_files, $audio_files);
|
||||||
|
$physical_excluded = array_merge($osb_files, $osu_files);
|
||||||
|
$other_excluded = array_merge($storyboard_files, $hitsound_files);
|
||||||
|
$excluded = array_merge($essential_excluded, $physical_excluded, $other_excluded);
|
||||||
|
|
||||||
|
$lowercase_excluded = array();
|
||||||
foreach ($excluded as $key => $value)
|
foreach ($excluded as $key => $value)
|
||||||
{
|
{
|
||||||
$lowercase[$key] = strtolower($value);
|
$lowercase_excluded[$key] = strtolower($value);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $lowercase;
|
$peppy_excluded_lowercase = array();
|
||||||
|
foreach ($lowercase_excluded as $value)
|
||||||
|
{
|
||||||
|
$extension = pathinfo($value, PATHINFO_EXTENSION) ?? "";
|
||||||
|
|
||||||
|
$directory = pathinfo($value, PATHINFO_DIRNAME) ?? "";
|
||||||
|
$directory = !empty($directory) ? $directory. "/" : ""; // append slash if set
|
||||||
|
|
||||||
|
$filename = pathinfo($value, PATHINFO_FILENAME);
|
||||||
|
|
||||||
|
if (mb_ereg_match("([jJ][pP][eE]?[gG]|[pP][nN][gG])", $extension))
|
||||||
|
{
|
||||||
|
$image_extensions = [ "png", "jpg", "jpeg", strtolower($extension) ];
|
||||||
|
$image_extensions = array_unique($image_extensions);
|
||||||
|
foreach ($image_extensions as $image_extension)
|
||||||
|
{
|
||||||
|
$peppy_excluded_lowercase[] = $directory . $filename . "." . $image_extension;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (mb_ereg_match("([wW][aA][vV]|[mM][pP]3|[oO][gG][gG])", $extension))
|
||||||
|
{
|
||||||
|
$sound_extensions = [ "wav", "mp3", "ogg", strtolower($extension) ];
|
||||||
|
$sound_extensions = array_unique($sound_extensions);
|
||||||
|
foreach ($sound_extensions as $sound_extension)
|
||||||
|
{
|
||||||
|
$peppy_excluded_lowercase[] = $directory . $filename . "." . $sound_extension;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$peppy_excluded_lowercase[] = $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $peppy_excluded_lowercase;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function remove_other(osu_library $library) : void
|
public static function remove_other(osu_library $library) : void
|
||||||
{
|
{
|
||||||
// $time_start = microtime(true);
|
// get the path and lowercase paths
|
||||||
|
list($removand, $removand_lower) = self::build_removand_list($library);
|
||||||
|
|
||||||
$removand = self::build_removand_list($library);
|
// get the lowercase exclusions
|
||||||
$exclusions = self::build_excluded_list($library);
|
$exclusions = self::build_excluded_list($library);
|
||||||
$final = array_diff($removand, $exclusions);
|
|
||||||
|
// subtract the exclusions (lowercase because osu! is case-insensitive)
|
||||||
|
$check = array_diff($removand_lower, $exclusions);
|
||||||
|
|
||||||
|
// take the original paths based on the keys from the subtraction above
|
||||||
|
// (this is only important for case-sensitive file systems like unix)
|
||||||
|
$final = array_intersect_key($removand, $check);
|
||||||
|
|
||||||
foreach ($final as $file)
|
foreach ($final as $file)
|
||||||
{
|
{
|
||||||
unlink($file);
|
if (self::is_skinnable($file)) continue; // ignore default hitsounds
|
||||||
|
// if (file_exists($file)) unlink($file);
|
||||||
|
echo $file . "<br />";
|
||||||
}
|
}
|
||||||
|
exit(0);
|
||||||
|
|
||||||
$empty = self::build_empty_dir_list($library);
|
$empty = self::build_empty_dir_list($library);
|
||||||
foreach ($empty as $folder)
|
foreach ($empty as $folder)
|
||||||
{
|
{
|
||||||
rmdir($folder);
|
rmdir($folder);
|
||||||
}
|
}
|
||||||
|
|
||||||
// $time_end = microtime(true);
|
|
||||||
// $time = $time_end - $time_start;
|
|
||||||
// echo " in {$time} seconds.";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+125
-25
@@ -273,7 +273,8 @@ class osu_library
|
|||||||
if (!empty($beatmap["background"]))
|
if (!empty($beatmap["background"]))
|
||||||
{
|
{
|
||||||
$path = $beatmapset["path"] . "/" . $beatmap["background"];
|
$path = $beatmapset["path"] . "/" . $beatmap["background"];
|
||||||
if (file_exists($path)) $backgrounds[] = $path;
|
// if (file_exists($path))
|
||||||
|
$backgrounds[] = $path;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -295,7 +296,8 @@ class osu_library
|
|||||||
if (!empty($beatmap["video"]))
|
if (!empty($beatmap["video"]))
|
||||||
{
|
{
|
||||||
$path = $beatmapset["path"] . "/" . $beatmap["video"];
|
$path = $beatmapset["path"] . "/" . $beatmap["video"];
|
||||||
if (file_exists($path)) $videos[] = $path;
|
// if (file_exists($path))
|
||||||
|
$videos[] = $path;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -305,52 +307,71 @@ class osu_library
|
|||||||
return $videos;
|
return $videos;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get_osu_files() : array
|
public function get_parsed_files() : array
|
||||||
{
|
{
|
||||||
$db = $this->get_library();
|
$db = $this->get_library();
|
||||||
|
|
||||||
$osu_files = array();
|
$files = array();
|
||||||
foreach ($db as $beatmapset)
|
foreach ($db as $beatmapset)
|
||||||
{
|
{
|
||||||
foreach($beatmapset["difficulties"] as $beatmap)
|
foreach($beatmapset["difficulties"] as $beatmap)
|
||||||
{
|
{
|
||||||
if (!empty($beatmap["format"]) && $beatmap["format"] != "storyboard")
|
if (!empty($beatmap["path"]) && !empty($beatmap["format"]))
|
||||||
{
|
{
|
||||||
if (file_exists($beatmap["path"]))
|
$files[] = $beatmap;
|
||||||
{
|
|
||||||
$osu_files[] = $beatmap["path"];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$osu_files = array_unique($osu_files);
|
return $files;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get_osu_files() : array
|
||||||
|
{
|
||||||
|
$files = $this->get_parsed_files();
|
||||||
|
|
||||||
|
$osu_files = array();
|
||||||
|
foreach ($files as $file)
|
||||||
|
{
|
||||||
|
if (mb_strpos($beatmap["format"], "osu file format " !== false))
|
||||||
|
{
|
||||||
|
$osu_files[] = $beatmap["path"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return $osu_files;
|
return $osu_files;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get_osb_files() : array
|
public function get_osb_files() : array
|
||||||
{
|
{
|
||||||
$db = $this->get_library();
|
$files = $this->get_parsed_files();
|
||||||
|
|
||||||
$storyboard_files = array();
|
$osb_files = array();
|
||||||
foreach ($db as $beatmapset)
|
foreach ($files as $file)
|
||||||
{
|
{
|
||||||
foreach($beatmapset["difficulties"] as $beatmap)
|
if ($beatmap["format"] == "storyboard")
|
||||||
{
|
{
|
||||||
if (!empty($beatmap["format"]) && $beatmap["format"] == "storyboard")
|
$osb_files[] = $beatmap["path"];
|
||||||
{
|
|
||||||
if (file_exists($beatmap["path"]))
|
|
||||||
{
|
|
||||||
$storyboard_files[] = $beatmap["path"];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$storyboard_files = array_unique($storyboard_files);
|
return $osb_files;
|
||||||
|
}
|
||||||
|
|
||||||
return $storyboard_files;
|
public function get_broken_files() : array
|
||||||
|
{
|
||||||
|
$files = $this->get_parsed_files();
|
||||||
|
|
||||||
|
$broken_files = array();
|
||||||
|
foreach ($files as $file)
|
||||||
|
{
|
||||||
|
if ($beatmap["format"] == "unknown")
|
||||||
|
{
|
||||||
|
$broken_files[] = $beatmap["path"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $broken_files;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get_storyboards() : array
|
public function get_storyboards() : array
|
||||||
@@ -365,7 +386,8 @@ class osu_library
|
|||||||
foreach ($beatmap["storyboard"] ?? array() as $storyelement)
|
foreach ($beatmap["storyboard"] ?? array() as $storyelement)
|
||||||
{
|
{
|
||||||
$path = $beatmapset["path"] . "/" . $storyelement;
|
$path = $beatmapset["path"] . "/" . $storyelement;
|
||||||
if (file_exists($path)) $storyboards[] = $path;
|
// if (file_exists($path))
|
||||||
|
$storyboards[] = $path;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -375,6 +397,29 @@ class osu_library
|
|||||||
return $storyboards;
|
return $storyboards;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function get_hitsounds() : array
|
||||||
|
{
|
||||||
|
$db = $this->get_library();
|
||||||
|
|
||||||
|
$hitsounds = array();
|
||||||
|
foreach ($db as $beatmapset)
|
||||||
|
{
|
||||||
|
foreach($beatmapset["difficulties"] as $beatmap)
|
||||||
|
{
|
||||||
|
foreach ($beatmap["hitsounds"] ?? array() as $hitsound)
|
||||||
|
{
|
||||||
|
$path = $beatmapset["path"] . "/" . $hitsound;
|
||||||
|
// if (file_exists($path))
|
||||||
|
$hitsounds[] = $path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$hitsounds = array_unique($hitsounds);
|
||||||
|
|
||||||
|
return $hitsounds;
|
||||||
|
}
|
||||||
|
|
||||||
public function get_audiofiles() : array
|
public function get_audiofiles() : array
|
||||||
{
|
{
|
||||||
$db = $this->get_library();
|
$db = $this->get_library();
|
||||||
@@ -387,7 +432,8 @@ class osu_library
|
|||||||
if (!empty($beatmap["General"]["AudioFilename"]))
|
if (!empty($beatmap["General"]["AudioFilename"]))
|
||||||
{
|
{
|
||||||
$path = $beatmapset["path"] . "/" . $beatmap["General"]["AudioFilename"];
|
$path = $beatmapset["path"] . "/" . $beatmap["General"]["AudioFilename"];
|
||||||
if (file_exists($path)) $audiofiles[] = $path;
|
// if (file_exists($path))
|
||||||
|
$audiofiles[] = $path;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -396,4 +442,58 @@ class osu_library
|
|||||||
|
|
||||||
return $audiofiles;
|
return $audiofiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function get_missing_files() : array
|
||||||
|
{
|
||||||
|
$db = $this->get_library();
|
||||||
|
|
||||||
|
$missing = array();
|
||||||
|
foreach ($db as $beatmapset)
|
||||||
|
{
|
||||||
|
foreach($beatmapset["difficulties"] as $beatmap)
|
||||||
|
{
|
||||||
|
if (!empty($beatmap["General"]["AudioFilename"]))
|
||||||
|
{
|
||||||
|
$path = $beatmapset["path"] . "/" . $beatmap["General"]["AudioFilename"];
|
||||||
|
if (!file_exists($path)) $missing[] = $path;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($beatmap["background"]))
|
||||||
|
{
|
||||||
|
$path = $beatmapset["path"] . "/" . $beatmap["background"];
|
||||||
|
if (!file_exists($path)) $missing[] = $path;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($beatmap["video"]))
|
||||||
|
{
|
||||||
|
$path = $beatmapset["path"] . "/" . $beatmap["video"];
|
||||||
|
if (!file_exists($path)) $missing[] = $path;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($beatmap["storyboard"] ?? array() as $storyelement)
|
||||||
|
{
|
||||||
|
$path = $beatmapset["path"] . "/" . $storyelement;
|
||||||
|
if (!file_exists($path)) $missing[] = $path;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($beatmap["hitsounds"] ?? array() as $hitsound)
|
||||||
|
{
|
||||||
|
$path = $beatmapset["path"] . "/" . $hitsound;
|
||||||
|
if (!file_exists($path)) $missing[] = $path;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($beatmap["format"]))
|
||||||
|
{
|
||||||
|
if (!file_exists($beatmap["path"]))
|
||||||
|
{
|
||||||
|
$missing[] = $beatmap["path"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$missing = array_unique($missing);
|
||||||
|
|
||||||
|
return $missing;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,263 +0,0 @@
|
|||||||
<?php
|
|
||||||
class osu_old_parser
|
|
||||||
{
|
|
||||||
public static function scan_parse_osu_file(string $osu_file) : array
|
|
||||||
{
|
|
||||||
$time_start = microtime(true);
|
|
||||||
$file = file($osu_file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
|
|
||||||
// osu files can get big, but why not load the full thing :3
|
|
||||||
|
|
||||||
if (stripos($file[0], "osu file format") === false) return [ "error..." ];
|
|
||||||
|
|
||||||
// some files had "ZERO WIDTH NO-BREAK SPACE" characters...
|
|
||||||
$format = explode("osu file format ", $file[0])[1];
|
|
||||||
unset($file[0]); // no longer needed
|
|
||||||
|
|
||||||
$osu = array("Format" => $format);
|
|
||||||
$current_section = "UnofficialComments";
|
|
||||||
$osu[$current_section] = array();
|
|
||||||
$storyboard = array();
|
|
||||||
foreach ($file as $key => $line)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (mb_strpos($line, "[") === 0 && mb_strpos($line, "]") === (strlen($line)-1))
|
|
||||||
{
|
|
||||||
$current_section = str_replace([ "[", "]" ], "", $line);
|
|
||||||
if (!isset($osu[$current_section]))
|
|
||||||
{
|
|
||||||
$osu[$current_section] = array();
|
|
||||||
}
|
|
||||||
|
|
||||||
// peppy is retarded so i have to do this...
|
|
||||||
switch ($current_section) {
|
|
||||||
case "General":
|
|
||||||
case "Editor":
|
|
||||||
$section_type = "key-value pairs";
|
|
||||||
$delimiter = ": ";
|
|
||||||
break;
|
|
||||||
case "Metadata":
|
|
||||||
case "Difficulty":
|
|
||||||
$section_type = "key-value pairs";
|
|
||||||
$delimiter = ":"; // notice the missing space
|
|
||||||
break;
|
|
||||||
case "Colours":
|
|
||||||
$section_type = "key-value pairs";
|
|
||||||
$delimiter = " : "; // WHY WOULD YOU DO THIS IF YOU ALREADY HAVE TWO TYPES OF KEY-VALUE PAIRS???????????????????
|
|
||||||
break;
|
|
||||||
case "Events":
|
|
||||||
case "TimingPoints":
|
|
||||||
case "HitObjects":
|
|
||||||
$section_type = "lists"; // yes, listS because one list per line
|
|
||||||
$delimiter = ",";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
$section_type = "unknown";
|
|
||||||
}
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// only parse the ones needed
|
|
||||||
switch ($current_section) {
|
|
||||||
case "General":
|
|
||||||
case "Metadata":
|
|
||||||
case "Difficulty":
|
|
||||||
case "Events":
|
|
||||||
$skip = false;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
$skip = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($skip) continue;
|
|
||||||
|
|
||||||
|
|
||||||
if (mb_strpos($line, "//") === 0) // there were commented files that broke my script
|
|
||||||
{
|
|
||||||
}
|
|
||||||
else if ($section_type == "key-value pairs")
|
|
||||||
{
|
|
||||||
$delimiter_position = mb_strpos($line, $delimiter);
|
|
||||||
|
|
||||||
$value = mb_substr($line, $delimiter_position + strlen($delimiter_position));
|
|
||||||
$osu[$current_section][mb_substr($line, 0, $delimiter_position)] = $value;
|
|
||||||
}
|
|
||||||
else if ($section_type == "lists")
|
|
||||||
{
|
|
||||||
$list = explode($delimiter, $line);
|
|
||||||
|
|
||||||
// group events by type and start time
|
|
||||||
if ($current_section == "Events")
|
|
||||||
{
|
|
||||||
if (mb_strpos($line, " ") === 0) continue; // skip storyboard details lines
|
|
||||||
|
|
||||||
// event types: https://github.com/ppy/osu/blob/master/osu.Game/Beatmaps/Legacy/LegacyEventType.cs
|
|
||||||
$list[0] = str_replace(
|
|
||||||
[ "Background", "Video", "Break", "Colour", "Sprite", "Sample", "Animation" ],
|
|
||||||
[ "0", "1", "2", "3", "4", "5", "6" ],
|
|
||||||
$list[0]
|
|
||||||
);
|
|
||||||
|
|
||||||
if ($list[0] == "5" || $list[0] == "4")
|
|
||||||
{
|
|
||||||
$storyboard[] = trim(str_replace("\\", "/", $list[3]), "\"");
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($list[0] == "6")
|
|
||||||
{
|
|
||||||
$story_base = pathinfo(trim(str_replace("\\", "/", $list[3]), "\""));
|
|
||||||
if (empty($story_base["extension"])) $ext = "";
|
|
||||||
else $ext = "." . $story_base["extension"];
|
|
||||||
if (empty($story_base["dirname"])) $dir = "";
|
|
||||||
else $dir = $story_base["dirname"] . "/";
|
|
||||||
|
|
||||||
for ($i = 0; $i < intval($list[6]); $i++)
|
|
||||||
{
|
|
||||||
$storyboard[] = $dir . $story_base["filename"] . $i . $ext;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isset($osu[$current_section][$list[0]]))
|
|
||||||
{
|
|
||||||
$osu[$current_section][$list[0]] = array();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isset($osu[$current_section][$list[0]][$list[1]]))
|
|
||||||
{
|
|
||||||
$osu[$current_section][$list[0]][$list[1]] = array();
|
|
||||||
}
|
|
||||||
|
|
||||||
$osu[$current_section][$list[0]][$list[1]][] = $list;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$osu[$current_section][] = $list;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$osu[$current_section][] = $line; // just dump the unknown...
|
|
||||||
}
|
|
||||||
}
|
|
||||||
unset($file); // remove the memory leak
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// return $osu;
|
|
||||||
|
|
||||||
$set_id = $osu["Metadata"]["BeatmapSetID"] ?? false;
|
|
||||||
if ($set_id === false)
|
|
||||||
{
|
|
||||||
$temp = explode(" ", basename(dirname($osu_file)))[0];
|
|
||||||
if (is_numeric($temp))
|
|
||||||
{
|
|
||||||
$set_id = $temp;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$set_id = "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$background = str_replace("\\", "/", trim($osu["Events"][0][0][0][2] ?? "", "\""));
|
|
||||||
$audio = str_replace("\\", "/", trim($osu["General"]["AudioFilename"] ?? "", "\""));
|
|
||||||
$video = str_replace("\\", "/", trim($osu["Events"][1][array_key_first($osu["Events"][1] ?? array())][0][2] ?? "", "\""));
|
|
||||||
$storyboard = array_unique($storyboard);
|
|
||||||
|
|
||||||
$map_id = intval($osu["Metadata"]["BeatmapID"] ?? 0);
|
|
||||||
if ($map_id < 1) $map_id = "";
|
|
||||||
$return = array(
|
|
||||||
"format" => $osu["Format"] ?? "",
|
|
||||||
"title" => $osu["Metadata"]["Title"] ?? "",
|
|
||||||
"artist" => $osu["Metadata"]["Artist"] ?? "",
|
|
||||||
"mapper" => $osu["Metadata"]["Creator"] ?? "",
|
|
||||||
"difficulty" => $osu["Metadata"]["Version"] ?? "",
|
|
||||||
"tags" => $osu["Metadata"]["Tags"] ?? "",
|
|
||||||
"background" => $background,
|
|
||||||
"audio" => $audio,
|
|
||||||
"video" => $video,
|
|
||||||
"storyboard" => $storyboard,
|
|
||||||
"id" => $map_id,
|
|
||||||
"set_id" => $set_id,
|
|
||||||
);
|
|
||||||
|
|
||||||
$time_end = microtime(true);
|
|
||||||
$time = $time_end - $time_start;
|
|
||||||
$return["process_time"] = $time;
|
|
||||||
$return["hash"] = hash_file("md5", $osu_file);
|
|
||||||
|
|
||||||
return $return;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function scan_parse_osb_file(string $osb_file) : array
|
|
||||||
{
|
|
||||||
$time_start = microtime(true);
|
|
||||||
$file = file($osb_file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
|
|
||||||
|
|
||||||
$storyboard = array();
|
|
||||||
$current_section = "UnofficialComments";
|
|
||||||
foreach ($file as $key => $line)
|
|
||||||
{
|
|
||||||
if (mb_strpos($line, "[") === 0 && mb_strpos($line, "]") === (strlen($line)-1))
|
|
||||||
{
|
|
||||||
$current_section = str_replace([ "[", "]" ], "", $line);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!($current_section == "Events")) continue; // skip rest
|
|
||||||
|
|
||||||
$list = explode(",", $line);
|
|
||||||
|
|
||||||
$list[0] = str_replace(
|
|
||||||
[ "Background", "Video", "Break", "Colour", "Sprite", "Sample", "Animation" ],
|
|
||||||
[ "0", "1", "2", "3", "4", "5", "6" ],
|
|
||||||
$list[0]
|
|
||||||
);
|
|
||||||
|
|
||||||
if ($list[0] == "5" || $list[0] == "4")
|
|
||||||
{
|
|
||||||
$storyboard[] = trim(str_replace("\\", "/", $list[3]), "\"");
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($list[0] == "6")
|
|
||||||
{
|
|
||||||
$story_base = pathinfo(trim(str_replace("\\", "/", $list[3]), "\""));
|
|
||||||
if (empty($story_base["extension"])) $ext = "";
|
|
||||||
else $ext = "." . $story_base["extension"];
|
|
||||||
if (empty($story_base["dirname"])) $dir = "";
|
|
||||||
else $dir = $story_base["dirname"] . "/";
|
|
||||||
|
|
||||||
for ($i = 0; $i < intval($list[6]); $i++)
|
|
||||||
{
|
|
||||||
$storyboard[] = $dir . $story_base["filename"] . $i . $ext;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$temp = explode(" ", basename(dirname($osb_file)))[0];
|
|
||||||
if (is_numeric($temp))
|
|
||||||
{
|
|
||||||
$set_id = $temp;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$set_id = "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$storyboard = array_unique($storyboard);
|
|
||||||
|
|
||||||
$return = array(
|
|
||||||
"format" => "storyboard",
|
|
||||||
"storyboard" => $storyboard,
|
|
||||||
"set_id" => $set_id,
|
|
||||||
);
|
|
||||||
|
|
||||||
$time_end = microtime(true);
|
|
||||||
$time = $time_end - $time_start;
|
|
||||||
$return["process_time"] = $time;
|
|
||||||
$return["hash"] = hash_file("md5", $osb_file);
|
|
||||||
|
|
||||||
return $return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+85
-11
@@ -31,6 +31,29 @@ class osu_parser
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// fix backslash and double quotes
|
||||||
|
public static function fix_filename(string $filename) : string
|
||||||
|
{
|
||||||
|
return trim(str_replace("\\", "/", $filename), "\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function file_ver_peppy(string $path)// : array|bool // see you in php8
|
||||||
|
{
|
||||||
|
if (!file_exists($path)) return false;
|
||||||
|
$file = file_get_contents($path); // read normally
|
||||||
|
if (empty($file)) return false;
|
||||||
|
|
||||||
|
$bom = "\xef\xbb\xbf"; // the BOM character
|
||||||
|
$file = str_replace($bom, "", $file); // removing BOM
|
||||||
|
$file = str_replace("\r\n", "\n", $file); // win CRLF to unix LF
|
||||||
|
$file = str_replace("\r", "\n", $file); // old mac CR to unix LF
|
||||||
|
$lines = explode("\n", $file); // split using LF
|
||||||
|
$lines = array_filter($lines); // remove empty lines
|
||||||
|
$lines = array_values($lines); // reindex array
|
||||||
|
|
||||||
|
return $lines;
|
||||||
|
}
|
||||||
|
|
||||||
public function parse_osu_file_format(string $path, bool $skip_cache = false)// : array|bool // see you again in php8
|
public function parse_osu_file_format(string $path, bool $skip_cache = false)// : array|bool // see you again in php8
|
||||||
{
|
{
|
||||||
if (!file_exists($path)) return false;
|
if (!file_exists($path)) return false;
|
||||||
@@ -43,28 +66,35 @@ class osu_parser
|
|||||||
|
|
||||||
$time_start = microtime(true); // measure parsing time
|
$time_start = microtime(true); // measure parsing time
|
||||||
|
|
||||||
$file = file($path, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
|
$file = self::file_ver_peppy($path);
|
||||||
|
if ($file === false) return false;
|
||||||
|
|
||||||
$parsed = array();
|
$parsed = array();
|
||||||
|
|
||||||
// file format declaration
|
$osu_file_format_declaration = "osu file format ";
|
||||||
if (stripos($file[0], "osu file format ") !== false)
|
if (stripos($file[0], $osu_file_format_declaration) !== false)
|
||||||
{
|
{
|
||||||
// the ranker script had a bug where random "ZERO WIDTH NO-BREAK SPACE"
|
// random characters were at beginning of the .osu files...
|
||||||
// characters were at beginning of the .osu files
|
$format = $osu_file_format_declaration . explode($osu_file_format_declaration, $file[0])[1];
|
||||||
$parsed["format"] = explode("osu file format ", $file[0])[1];
|
|
||||||
unset($file[0]); // no longer needed
|
unset($file[0]); // no longer needed
|
||||||
}
|
}
|
||||||
else if (pathinfo($path, PATHINFO_EXTENSION) == "osb")
|
else if (pathinfo($path, PATHINFO_EXTENSION) == "osb")
|
||||||
{
|
{
|
||||||
$parsed["format"] = "storyboard";
|
$format = "storyboard";
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$format = "unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
$parsed["format"] = $format;
|
||||||
|
|
||||||
|
|
||||||
$current_section = false;
|
$current_section = false;
|
||||||
$section_type = false;
|
$section_type = false;
|
||||||
$delimiter = false;
|
$delimiter = false;
|
||||||
$variables = [ "keys" => array(), "values" => array()]; // variables for osb files $key=value pairs
|
$variables = [ "keys" => array(), "values" => array()]; // variables for osb files $key=value pairs
|
||||||
$needed_sections = [ "General", "Metadata", "Difficulty", "Variables", "Events" ];
|
$needed_sections = [ "General", "Metadata", "Difficulty", "Variables", "Events", "HitObjects" ];
|
||||||
foreach ($file as $key => $line)
|
foreach ($file as $key => $line)
|
||||||
{
|
{
|
||||||
if (mb_strpos($line, "[") === 0 && mb_strpos($line, "]") === (strlen($line)-1))
|
if (mb_strpos($line, "[") === 0 && mb_strpos($line, "]") === (strlen($line)-1))
|
||||||
@@ -135,6 +165,33 @@ class osu_parser
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if ($current_section == "HitObjects") // saving the whole thing would take up too much space v2
|
||||||
|
{
|
||||||
|
$last = array_key_last($list);
|
||||||
|
if (!empty($list[$last]) && mb_strpos($list[$last], ":") !== false)
|
||||||
|
{
|
||||||
|
$hitSample = explode(":", $list[$last]);
|
||||||
|
$last_sample = array_key_last($hitSample);
|
||||||
|
if (!empty($hitSample[$last_sample]))
|
||||||
|
{
|
||||||
|
$filename = $hitSample[$last_sample];
|
||||||
|
$filename = self::fix_filename($filename);
|
||||||
|
|
||||||
|
// some maps leave out the extensions
|
||||||
|
// (and some maps have .wav filess pointing to .ogg files........)
|
||||||
|
if (empty(pathinfo($filename, PATHINFO_EXTENSION)))
|
||||||
|
{
|
||||||
|
$filename = $filename . ".wav"; // just to signal it's an "audio file"
|
||||||
|
}
|
||||||
|
|
||||||
|
// init empty array
|
||||||
|
if (!isset($parsed["hitsounds"])) $parsed["hitsounds"] = array();
|
||||||
|
|
||||||
|
// add the element to the hitsounds
|
||||||
|
$parsed["hitsounds"][] = $filename;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// init empty array
|
// init empty array
|
||||||
@@ -151,8 +208,9 @@ class osu_parser
|
|||||||
}
|
}
|
||||||
unset($file); // remove the memory leak
|
unset($file); // remove the memory leak
|
||||||
|
|
||||||
// storyboards are overloaded with dupes (renumber to make json export to arrays)
|
// storyboards/hitsounds are overloaded with dupes (renumber to make json export to arrays)
|
||||||
if (!empty($parsed["storyboard"])) $parsed["storyboard"] = array_values(array_unique($parsed["storyboard"]));
|
if (!empty($parsed["storyboard"])) $parsed["storyboard"] = array_values(array_unique($parsed["storyboard"]));
|
||||||
|
if (!empty($parsed["hitsounds"])) $parsed["hitsounds"] = array_values(array_unique($parsed["hitsounds"]));
|
||||||
|
|
||||||
$time_end = microtime(true);
|
$time_end = microtime(true);
|
||||||
$parsing_time = $time_end - $time_start;
|
$parsing_time = $time_end - $time_start;
|
||||||
@@ -193,8 +251,7 @@ class osu_parser
|
|||||||
$source_file = str_replace($variables["keys"], $variables["values"], $source_file);
|
$source_file = str_replace($variables["keys"], $variables["values"], $source_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
// fix backslash and double quotes
|
if ($source_file !== false) $source_file = self::fix_filename($source_file);
|
||||||
if ($source_file !== false) $source_file = trim(str_replace("\\", "/", $source_file), "\"");
|
|
||||||
|
|
||||||
// fix leading dot slash
|
// fix leading dot slash
|
||||||
if (mb_strpos($source_file, "./") === 0) $source_file = mb_substr($source_file, 2);
|
if (mb_strpos($source_file, "./") === 0) $source_file = mb_substr($source_file, 2);
|
||||||
@@ -222,6 +279,23 @@ class osu_parser
|
|||||||
$source_files = array($source_file); // pack the single-source resources into an array
|
$source_files = array($source_file); // pack the single-source resources into an array
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// artificially add a "good" extension
|
||||||
|
foreach ($source_files as $source_key => $source_file)
|
||||||
|
{
|
||||||
|
// some maps leave out the extensions...
|
||||||
|
if (empty(pathinfo($source_file, PATHINFO_EXTENSION)))
|
||||||
|
{
|
||||||
|
if ($event_type == 5)
|
||||||
|
{
|
||||||
|
$source_files[$source_key] = $source_file . ".wav"; // just to signal it's an "audio file"
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$source_files[$source_key] = $source_file . ".png"; // just to signal it's an "image file"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return array(self::reverse_event_type($event_type), $source_files);
|
return array(self::reverse_event_type($event_type), $source_files);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
// todo: repack osz file
|
// todo: repack osz file
|
||||||
// todo: dupe checker
|
// todo: dupe checker
|
||||||
// todo: stardiff deleter
|
// todo: stardiff deleter
|
||||||
|
// todo: mode deleter
|
||||||
|
|
||||||
|
|
||||||
// imports
|
// imports
|
||||||
@@ -68,7 +69,7 @@ if (isset($_GET["purify"]))
|
|||||||
$start = file_get_contents("resources/start.html");
|
$start = file_get_contents("resources/start.html");
|
||||||
$start = str_replace("{{ STYLE }}", file_get_contents("resources/style.css"), $start);
|
$start = str_replace("{{ STYLE }}", file_get_contents("resources/style.css"), $start);
|
||||||
echo $start;
|
echo $start;
|
||||||
dump($lib, "lib");
|
// dump($lib, "lib");
|
||||||
echo '<a href="./?scan">[Scan]</a> ';
|
echo '<a href="./?scan">[Scan]</a> ';
|
||||||
echo '<a href="./?rescan">[Force rescan]</a> ';
|
echo '<a href="./?rescan">[Force rescan]</a> ';
|
||||||
echo '<a href="./?blacken">[Blacken]</a> ';
|
echo '<a href="./?blacken">[Blacken]</a> ';
|
||||||
|
|||||||
@@ -0,0 +1,109 @@
|
|||||||
|
check-off.wav
|
||||||
|
check-on.wav
|
||||||
|
click-close.wav
|
||||||
|
click-short-confirm.wav
|
||||||
|
menuback.wav
|
||||||
|
menuhit.wav
|
||||||
|
select-difficulty.wav
|
||||||
|
select-expand.wav
|
||||||
|
shutter.wav
|
||||||
|
sliderbar.wav
|
||||||
|
count.wav
|
||||||
|
count1s.wav
|
||||||
|
count2s.wav
|
||||||
|
count3s.wav
|
||||||
|
gos.wav
|
||||||
|
readys.wav
|
||||||
|
drum-hitclap.wav
|
||||||
|
drum-hitfinish.wav
|
||||||
|
drum-hitnormal.wav
|
||||||
|
drum-hitwhistle.wav
|
||||||
|
drum-sliderslide.wav
|
||||||
|
drum-slidertick.wav
|
||||||
|
drum-sliderwhistle.wav
|
||||||
|
applause.wav
|
||||||
|
combobreak.wav
|
||||||
|
comboburst(-n).wav
|
||||||
|
failsound.wav
|
||||||
|
metronomelow.wav
|
||||||
|
sectionfail.wav
|
||||||
|
sectionpass.wav
|
||||||
|
menu-background.jpg
|
||||||
|
back-button-click.wav
|
||||||
|
back-button-hover.wav
|
||||||
|
menu-back-click.wav
|
||||||
|
menu-back-hover.wav
|
||||||
|
menu-charts-click.wav
|
||||||
|
menu-charts-hover.wav
|
||||||
|
menu-direct-click.wav
|
||||||
|
menu-direct-hover.wav
|
||||||
|
menu-edit-click.wav
|
||||||
|
menu-edit-hover.wav
|
||||||
|
menu-exit-click.wav
|
||||||
|
menu-exit-hover.wav
|
||||||
|
menu-freeplay-click.wav
|
||||||
|
menu-freeplay-hover.wav
|
||||||
|
menu-multiplayer-click.wav
|
||||||
|
menu-multiplayer-hover.wav
|
||||||
|
menu-options-click.wav
|
||||||
|
menu-options-hover.wav
|
||||||
|
menu-play-click.wav
|
||||||
|
menu-play-hover.wav
|
||||||
|
heartbeat.wav
|
||||||
|
seeya.wav
|
||||||
|
welcome.wav
|
||||||
|
click-short.wav
|
||||||
|
menuclick.wav
|
||||||
|
key-confirm.wav
|
||||||
|
key-delete.wav
|
||||||
|
key-movement.wav
|
||||||
|
key-press-1.wav
|
||||||
|
key-press-2.wav
|
||||||
|
key-press-3.wav
|
||||||
|
key-press-4.wav
|
||||||
|
match-confirm.wav
|
||||||
|
match-join.wav
|
||||||
|
match-leave.wav
|
||||||
|
match-notready.wav
|
||||||
|
match-ready.wav
|
||||||
|
match-start.wav
|
||||||
|
nightcore-clap.wav
|
||||||
|
nightcore-finish.wav
|
||||||
|
nightcore-hat.wav
|
||||||
|
nightcore-kick.wav
|
||||||
|
normal-hitclap.wav
|
||||||
|
normal-hitfinish.wav
|
||||||
|
normal-hitnormal.wav
|
||||||
|
normal-hitwhistle.wav
|
||||||
|
normal-sliderslide.wav
|
||||||
|
normal-slidertick.wav
|
||||||
|
normal-sliderwhistle.wav
|
||||||
|
spinnerbonus.wav
|
||||||
|
spinnerspin.wav
|
||||||
|
taiko-drum-hitclap.wav
|
||||||
|
taiko-drum-hitfinish.wav
|
||||||
|
taiko-drum-hitnormal.wav
|
||||||
|
taiko-drum-hitwhistle.wav
|
||||||
|
taiko-normal-hitclap.wav
|
||||||
|
taiko-normal-hitfinish.wav
|
||||||
|
taiko-normal-hitnormal.wav
|
||||||
|
taiko-normal-hitwhistle.wav
|
||||||
|
taiko-soft-hitclap.wav
|
||||||
|
taiko-soft-hitfinish.wav
|
||||||
|
taiko-soft-hitnormal.wav
|
||||||
|
taiko-soft-hitwhistle.wav
|
||||||
|
pause-back-click.wav
|
||||||
|
pause-back-hover.wav
|
||||||
|
pause-continue-click.wav
|
||||||
|
pause-continue-hover.wav
|
||||||
|
pause-hover.wav
|
||||||
|
pause-loop.wav
|
||||||
|
pause-retry-click.wav
|
||||||
|
pause-retry-hover.wav
|
||||||
|
soft-hitclap.wav
|
||||||
|
soft-hitfinish.wav
|
||||||
|
soft-hitnormal.wav
|
||||||
|
soft-hitwhistle.wav
|
||||||
|
soft-sliderslide.wav
|
||||||
|
soft-slidertick.wav
|
||||||
|
soft-sliderwhistle.wav
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
113273 HTT - Gohan wa Okazu/HTT - Gohan wa Okazu (YunoFanatic) [S.Star's 7K Another].osu
|
||||||
|
360118 LamazeP - Koi no Program Hatsudou (feat Hatsune Miku)/LamazeP - Koi no Program Hatsudou (feat. Hatsune Miku) (Sonnyc) [Euny's Hard].osu
|
||||||
|
661398 Baby's breath - Habataki no Birthday/Baby's breath - Habataki no Birthday (ShogunMoon) [Nao's Advanced].osu
|
||||||
Reference in New Issue
Block a user