Peppy BOM fix

This commit is contained in:
2020-12-27 12:32:55 +01:00
parent 22e3d31acb
commit 439f2cc9df
8 changed files with 448 additions and 328 deletions
+4 -1
View File
@@ -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] Remove storyboard specific files
- [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
- [ ] Delete maps based on star difficulty
- [ ] Blacklist: the maps that should not be touched by this program
+119 -26
View File
@@ -1,6 +1,44 @@
<?php
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
{
$black_png = "./resources/black.png";
@@ -27,7 +65,7 @@ class optimizer
{
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)
{
unlink($file);
if (file_exists($file)) unlink($file);
}
foreach ($library->get_osb_files() as $file)
{
unlink($file);
if (file_exists($file)) unlink($file);
}
$empty = self::build_empty_dir_list($library);
@@ -53,30 +91,40 @@ class optimizer
private static function build_removand_sublist(string $folder) : array
{
$queue = array();
$lowercase = array();
foreach (glob(utils::globsafe($folder) . "/*") as $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
{
$queue[] = strtolower($file);
$queue[] = $file;
$lowercase[] = strtolower($file);
}
}
return $queue;
return array($queue, $lowercase);
}
public static function build_removand_list(osu_library $library) : array
{
$queue = array();
$lowercase = array();
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
@@ -114,44 +162,89 @@ class optimizer
public static function build_excluded_list(osu_library $library) : array
{
$bg = $library->get_backgrounds();
$vid = $library->get_videos();
$sb = $library->get_storyboards();
$a = $library->get_audiofiles();
$sbf = $library->get_osb_files();
$osf = $library->get_osu_files();
$excluded = array_merge($bg, $vid, $sb, $a, $sbf, $osf);
$background_files = $library->get_backgrounds();
$video_files = $library->get_videos();
$storyboard_files = $library->get_storyboards();
$hitsound_files = $library->get_hitsounds();
$audio_files = $library->get_audiofiles();
$osb_files = $library->get_osb_files();
$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)
{
$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
{
// $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);
$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)
{
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);
foreach ($empty as $folder)
{
rmdir($folder);
}
// $time_end = microtime(true);
// $time = $time_end - $time_start;
// echo " in {$time} seconds.";
}
}
+126 -26
View File
@@ -127,7 +127,7 @@ class osu_library
$difficulty = $parser->parse_osu_file_format($file);
$difficulty["key"] = $difficulty_key;
$difficulty["path"] = $file;
$difficulties[$difficulty_key] = $difficulty;
}
@@ -273,7 +273,8 @@ class osu_library
if (!empty($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"]))
{
$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;
}
public function get_osu_files() : array
public function get_parsed_files() : array
{
$db = $this->get_library();
$osu_files = array();
$files = array();
foreach ($db as $beatmapset)
{
foreach($beatmapset["difficulties"] as $beatmap)
{
if (!empty($beatmap["format"]) && $beatmap["format"] != "storyboard")
if (!empty($beatmap["path"]) && !empty($beatmap["format"]))
{
if (file_exists($beatmap["path"]))
{
$osu_files[] = $beatmap["path"];
}
$files[] = $beatmap;
}
}
}
$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;
}
public function get_osb_files() : array
{
$db = $this->get_library();
$files = $this->get_parsed_files();
$storyboard_files = array();
foreach ($db as $beatmapset)
$osb_files = array();
foreach ($files as $file)
{
foreach($beatmapset["difficulties"] as $beatmap)
if ($beatmap["format"] == "storyboard")
{
if (!empty($beatmap["format"]) && $beatmap["format"] == "storyboard")
{
if (file_exists($beatmap["path"]))
{
$storyboard_files[] = $beatmap["path"];
}
}
$osb_files[] = $beatmap["path"];
}
}
$storyboard_files = array_unique($storyboard_files);
return $osb_files;
}
public function get_broken_files() : array
{
$files = $this->get_parsed_files();
return $storyboard_files;
$broken_files = array();
foreach ($files as $file)
{
if ($beatmap["format"] == "unknown")
{
$broken_files[] = $beatmap["path"];
}
}
return $broken_files;
}
public function get_storyboards() : array
@@ -365,7 +386,8 @@ class osu_library
foreach ($beatmap["storyboard"] ?? array() as $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;
}
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
{
$db = $this->get_library();
@@ -387,7 +432,8 @@ class osu_library
if (!empty($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;
}
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;
}
}
-263
View File
@@ -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
View File
@@ -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
{
if (!file_exists($path)) return false;
@@ -43,28 +66,35 @@ class osu_parser
$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();
// file format declaration
if (stripos($file[0], "osu file format ") !== false)
$osu_file_format_declaration = "osu file format ";
if (stripos($file[0], $osu_file_format_declaration) !== false)
{
// the ranker script had a bug where random "ZERO WIDTH NO-BREAK SPACE"
// characters were at beginning of the .osu files
$parsed["format"] = explode("osu file format ", $file[0])[1];
// random characters were at beginning of the .osu files...
$format = $osu_file_format_declaration . explode($osu_file_format_declaration, $file[0])[1];
unset($file[0]); // no longer needed
}
else if (pathinfo($path, PATHINFO_EXTENSION) == "osb")
{
$parsed["format"] = "storyboard";
$format = "storyboard";
}
else
{
$format = "unknown";
}
$parsed["format"] = $format;
$current_section = false;
$section_type = false;
$delimiter = false;
$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)
{
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
{
// init empty array
@@ -151,8 +208,9 @@ class osu_parser
}
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["hitsounds"])) $parsed["hitsounds"] = array_values(array_unique($parsed["hitsounds"]));
$time_end = microtime(true);
$parsing_time = $time_end - $time_start;
@@ -193,8 +251,7 @@ class osu_parser
$source_file = str_replace($variables["keys"], $variables["values"], $source_file);
}
// fix backslash and double quotes
if ($source_file !== false) $source_file = trim(str_replace("\\", "/", $source_file), "\"");
if ($source_file !== false) $source_file = self::fix_filename($source_file);
// fix leading dot slash
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
}
// 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);
}
+2 -1
View File
@@ -3,6 +3,7 @@
// todo: repack osz file
// todo: dupe checker
// todo: stardiff deleter
// todo: mode deleter
// imports
@@ -68,7 +69,7 @@ if (isset($_GET["purify"]))
$start = file_get_contents("resources/start.html");
$start = str_replace("{{ STYLE }}", file_get_contents("resources/style.css"), $start);
echo $start;
dump($lib, "lib");
// dump($lib, "lib");
echo '<a href="./?scan">[Scan]</a> ';
echo '<a href="./?rescan">[Force rescan]</a> ';
echo '<a href="./?blacken">[Blacken]</a> ';
+109
View File
@@ -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
+3
View File
@@ -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