Peppy BOM fix
This commit is contained in:
+119
-26
@@ -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
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user