Compare commits
10 Commits
5687992157
..
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
8bf8dd333f
|
|||
|
209aee5632
|
|||
|
f5b751409e
|
|||
|
72a5003c3a
|
|||
|
397c7d3436
|
|||
|
2eddcd905d
|
|||
|
1fcb640029
|
|||
|
05117f6836
|
|||
|
0fa7358c4b
|
|||
|
dd3085ca1d
|
@@ -1,10 +1,10 @@
|
|||||||
# osu! optimizer (PHP)
|
# osu! optimizer (PHP)
|
||||||
|
|
||||||
**Current version: Version 0.1**
|
**Current version: Version 0.1a**
|
||||||
|
|
||||||
[round boi](https://osu.ppy.sh/users/7357064) has seen most of my works and it was his idea to combine them together before I start writing another one from scratch.
|
[round boi][round-boi-osu] has seen most of my works and it was his idea to combine them together before I start writing another one from scratch.
|
||||||
|
|
||||||
> "Swiss Army Knife style osu! library manager" -- [round boi](https://osu.ppy.sh/users/7357064)
|
> "Swiss Army Knife style osu! library manager" -- [round boi][round-boi-osu]
|
||||||
|
|
||||||
## What's this?
|
## What's this?
|
||||||
|
|
||||||
@@ -60,3 +60,4 @@ If you know what you're doing, you could run it on a dedicated server that can h
|
|||||||
|
|
||||||
[Windows-PHP]: https://www.php.net/manual/en/install.windows.tools.php
|
[Windows-PHP]: https://www.php.net/manual/en/install.windows.tools.php
|
||||||
[Mac-OS-PHP]: https://www.php.net/manual/en/install.macosx.bundled.php
|
[Mac-OS-PHP]: https://www.php.net/manual/en/install.macosx.bundled.php
|
||||||
|
[round-boi-osu]: https://osu.ppy.sh/users/7357064
|
||||||
|
|||||||
+80
-69
@@ -65,28 +65,17 @@ class optimizer
|
|||||||
|
|
||||||
public static function remove_videos(osu_library $library)
|
public static function remove_videos(osu_library $library)
|
||||||
{
|
{
|
||||||
foreach ($library->get_videos() as $file)
|
utils::array_delete_if_exists($library->get_videos());
|
||||||
{
|
|
||||||
if (file_exists($file)) unlink($file);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function remove_storyboards(osu_library $library) : void
|
public static function remove_storyboards(osu_library $library) : void
|
||||||
{
|
{
|
||||||
// exclude vital files if they are used in the storyboard
|
// exclude vital files if they are used in the storyboard
|
||||||
$storyboards_safe = $library->get_storyboards();
|
$vital = array_merge($library->get_backgrounds(), $library->get_audiofiles());
|
||||||
$storyboards_safe = array_diff($storyboards_safe, $library->get_backgrounds());
|
$sb_safe = array_diff($library->get_storyboards(), $vital);
|
||||||
$storyboards_safe = array_diff($storyboards_safe, $library->get_audiofiles());
|
|
||||||
|
|
||||||
foreach ($storyboards_safe as $file)
|
utils::array_delete_if_exists($sb_safe);
|
||||||
{
|
utils::array_delete_if_exists($library->get_osb_files());
|
||||||
if (file_exists($file)) unlink($file);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($library->get_osb_files() as $file)
|
|
||||||
{
|
|
||||||
if (file_exists($file)) unlink($file);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function build_removand_sublist(array &$queue, string $folder, bool $single_level = false)
|
private static function build_removand_sublist(array &$queue, string $folder, bool $single_level = false)
|
||||||
@@ -116,45 +105,58 @@ class optimizer
|
|||||||
return $queue;
|
return $queue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function build_excluded_list(osu_library $library, array $except = array()) : array
|
public static function build_single_level_removand_list(osu_library $library)
|
||||||
{
|
{
|
||||||
if (in_array("backgrounds", $except)) $background_files = array();
|
return self::build_removand_list($library);
|
||||||
else $background_files = $library->get_backgrounds();
|
}
|
||||||
|
|
||||||
if (in_array("videos", $except)) $video_files = array();
|
public static function copy_unless_excluded(string $needle, array $value, array $excluded_list)
|
||||||
else $video_files = $library->get_videos();
|
{
|
||||||
|
if (in_array($needle, $excluded_list))
|
||||||
if (in_array("audio", $except)) $audio_files = array();
|
|
||||||
else $audio_files = $library->get_audiofiles();
|
|
||||||
|
|
||||||
$essential_excluded = array_merge($background_files, $video_files, $audio_files);
|
|
||||||
|
|
||||||
|
|
||||||
if (in_array("osu", $except) ||in_array("osb", $except))
|
|
||||||
{
|
{
|
||||||
if (in_array("osu", $except)) $osu_files = array();
|
return array();
|
||||||
else $osu_files = $library->get_osu_files();
|
|
||||||
|
|
||||||
if (in_array("osb", $except)) $osb_files = array();
|
|
||||||
else $osb_files = $library->get_osb_files();
|
|
||||||
|
|
||||||
$physical_excluded = array_merge($osu_files, $osb_files);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (in_array("parsed", $except)) $physical_excluded = array();
|
return $value;
|
||||||
else $physical_excluded = $library->get_parsed_files();
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function build_essential_list(osu_library $library, array $except = array()) : array
|
||||||
|
{
|
||||||
|
$bg = self::copy_unless_excluded("backgrounds", $library->get_backgrounds(), $except);
|
||||||
|
$vid = self::copy_unless_excluded("videos", $library->get_videos(), $except);
|
||||||
|
$aud = self::copy_unless_excluded("audio", $library->get_audiofiles(), $except);
|
||||||
|
|
||||||
|
return array_merge($bg, $vid, $aud);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function build_physical_list(osu_library $library, array $except = array()) : array
|
||||||
|
{
|
||||||
|
if (in_array("osu", $except) || in_array("osb", $except))
|
||||||
|
{
|
||||||
|
$osu_files = self::copy_unless_excluded("osu", $library->get_osu_files(), $except);
|
||||||
|
$osb_files = self::copy_unless_excluded("osb", $library->get_osb_files(), $except);
|
||||||
|
|
||||||
|
return array_merge($osu_files, $osb_files);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return self::copy_unless_excluded("parsed", $library->get_parsed_files(), $except);
|
||||||
|
}
|
||||||
|
|
||||||
if (in_array("storyboard", $except)) $storyboard_files = array();
|
public static function build_other_list(osu_library $library, array $except = array()) : array
|
||||||
else $storyboard_files = $library->get_storyboards();
|
{
|
||||||
|
$storyboards = self::copy_unless_excluded("storyboard", $library->get_storyboards(), $except);
|
||||||
|
$hitsounds = self::copy_unless_excluded("hitsounds", $library->get_hitsounds(), $except);
|
||||||
|
|
||||||
if (in_array("hitsounds", $except)) $hitsound_files = array();
|
return array_merge($storyboards, $hitsounds);
|
||||||
else $hitsound_files = $library->get_hitsounds();
|
}
|
||||||
|
|
||||||
$other_excluded = array_merge($storyboard_files, $hitsound_files);
|
|
||||||
|
|
||||||
|
public static function build_excluded_list(osu_library $library, array $except = array()) : array
|
||||||
|
{
|
||||||
|
$essential_excluded = self::build_essential_list($library, $except);
|
||||||
|
$physical_excluded = self::build_physical_list($library, $except);
|
||||||
|
$other_excluded = self::build_other_list($library, $except);
|
||||||
|
|
||||||
return array_merge($essential_excluded, $physical_excluded, $other_excluded);
|
return array_merge($essential_excluded, $physical_excluded, $other_excluded);
|
||||||
}
|
}
|
||||||
@@ -189,44 +191,51 @@ class optimizer
|
|||||||
return array_intersect_key($files, array_diff($files_lowercase, $exclusions_lowercase));
|
return array_intersect_key($files, array_diff($files_lowercase, $exclusions_lowercase));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function get_junk_files(osu_library $library, $excluded = array(), $single_level = false) : array
|
||||||
|
{
|
||||||
|
$removand = self::build_removand_list($library, $single_level);
|
||||||
|
$exclusions = self::build_excluded_list($library, $excluded);
|
||||||
|
return self::array_diff_ver_peppy($removand, $exclusions);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function get_single_level_junk_files(osu_library $library, $excluded = array()) : array
|
||||||
|
{
|
||||||
|
return self::get_junk_files($library, $excluded, true);
|
||||||
|
}
|
||||||
|
|
||||||
public static function remove_skins(osu_library $library) : void
|
public static function remove_skins(osu_library $library) : void
|
||||||
{
|
{
|
||||||
$removand = self::build_removand_list($library, true);
|
$junk_files = self::get_single_level_junk_files($library);
|
||||||
$exclusions = self::build_excluded_list($library);
|
|
||||||
|
|
||||||
$junk_files = self::array_diff_ver_peppy($removand, $exclusions);
|
foreach ($junk_files as $key => $file)
|
||||||
|
|
||||||
foreach ($junk_files as $file)
|
|
||||||
{
|
{
|
||||||
if (self::is_skinnable_image($file) || self::is_skinnable_other($file))
|
if ((!self::is_skinnable_image($file) || self::is_skinnable_other($file)))
|
||||||
{
|
{
|
||||||
if (file_exists($file)) unlink($file);
|
unset($junk_files[$key]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
utils::array_delete_if_exists($junk_files);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function remove_hitsounds(osu_library $library) : void
|
public static function remove_hitsounds(osu_library $library) : void
|
||||||
{
|
{
|
||||||
$removand = self::build_removand_list($library, true);
|
$junk_files = self::get_single_level_junk_files($library, $exclusions);
|
||||||
$exclusions = self::build_excluded_list($library, [ "hitsounds" ]);
|
|
||||||
|
|
||||||
$junk_files = self::array_diff_ver_peppy($removand, $exclusions);
|
foreach ($junk_files as $key => $file)
|
||||||
|
|
||||||
foreach ($junk_files as $file)
|
|
||||||
{
|
{
|
||||||
if (self::is_skinnable_sound($file))
|
if (!self::is_skinnable_sound($file))
|
||||||
{
|
{
|
||||||
if (file_exists($file)) unlink($file);
|
unset($junk_files[$key]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
utils::array_delete_if_exists($junk_files);
|
||||||
|
|
||||||
$hitsounds_safe = $library->get_hitsounds();
|
$hitsounds_safe = $library->get_hitsounds();
|
||||||
$hitsounds_safe = array_diff($hitsounds_safe, $library->get_audiofiles());
|
$hitsounds_safe = array_diff($hitsounds_safe, $library->get_audiofiles());
|
||||||
|
|
||||||
foreach ($hitsounds_safe as $file)
|
utils::array_delete_if_exists($hitsounds_safe);
|
||||||
{
|
|
||||||
if (file_exists($file)) unlink($file);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function full_nuke(osu_library $library) : void
|
public static function full_nuke(osu_library $library) : void
|
||||||
@@ -244,16 +253,18 @@ class optimizer
|
|||||||
{
|
{
|
||||||
$excluded_arg = array();
|
$excluded_arg = array();
|
||||||
}
|
}
|
||||||
$removand = self::build_removand_list($library);
|
|
||||||
$exclusions = self::build_excluded_list($library, $excluded_arg);
|
|
||||||
|
|
||||||
$junk_files = self::array_diff_ver_peppy($removand, $exclusions);
|
$junk_files = self::get_junk_files($library, $excluded_arg, false);
|
||||||
|
|
||||||
foreach ($junk_files as $file)
|
foreach ($junk_files as $key => $file)
|
||||||
{
|
{
|
||||||
if (!$nuke && self::is_skinnable($file)) continue; // ignore default hitsounds
|
if (!$nuke && self::is_skinnable($file))
|
||||||
if (file_exists($file)) unlink($file);
|
{
|
||||||
|
unset($junk_files[$key]);;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
utils::array_delete_if_exists($junk_files);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function repack_all(osu_library $library) : void
|
public static function repack_all(osu_library $library) : void
|
||||||
@@ -293,7 +304,7 @@ class optimizer
|
|||||||
|
|
||||||
public static function cleanup_dir(string $dir, bool $recursion = false) : void
|
public static function cleanup_dir(string $dir, bool $recursion = false) : void
|
||||||
{
|
{
|
||||||
$dir = rtrim(str_replace("\\", "/", $dir), "/");
|
$dir = utils::to_unix_slashes_without_trail($dir);
|
||||||
$glob = glob(utils::globsafe($dir) . "/*");
|
$glob = glob(utils::globsafe($dir) . "/*");
|
||||||
foreach ($glob as $file)
|
foreach ($glob as $file)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,36 +8,32 @@ class optimizer_settings
|
|||||||
public function __construct(string $path)
|
public function __construct(string $path)
|
||||||
{
|
{
|
||||||
$this->path = $path;
|
$this->path = $path;
|
||||||
|
|
||||||
if (file_exists($path))
|
if (file_exists($path))
|
||||||
{
|
{
|
||||||
$this->load();
|
$this->load();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function load()
|
public function load() : void
|
||||||
{
|
{
|
||||||
$raw = file_get_contents($this->path);
|
$json = utils::load_json($this->path);
|
||||||
$json = json_decode($raw, true);
|
|
||||||
|
|
||||||
$this->osu_path = $json["osu_path"] ?? "";
|
$this->osu_path = $json["osu_path"] ?? "";
|
||||||
}
|
}
|
||||||
|
|
||||||
public function save()
|
public function save() : void
|
||||||
{
|
{
|
||||||
$json = array();
|
$json = [ "osu_path" => $this->osu_path ];
|
||||||
$json["osu_path"] = $this->osu_path;
|
|
||||||
|
|
||||||
$raw = json_encode($json);
|
file_put_contents($this->path, json_encode($json));
|
||||||
file_put_contents($this->path, $raw);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function set_osu_path($path) : void
|
public function set_osu_path($path) : void
|
||||||
{
|
{
|
||||||
$sanitized = str_replace("\\", "/", $path);
|
|
||||||
$sanitized = rtrim($sanitized, "/");
|
|
||||||
if (file_exists($path))
|
if (file_exists($path))
|
||||||
{
|
{
|
||||||
$this->osu_path = $sanitized;
|
$this->osu_path = utils::to_unix_slashes_without_trail($path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+29
-20
@@ -1,22 +1,23 @@
|
|||||||
<?php
|
<?php
|
||||||
|
require_once "libraries/utils.php";
|
||||||
|
|
||||||
class osu_cacher
|
class osu_cacher
|
||||||
{
|
{
|
||||||
public static $hash_function = "md5";
|
public static $hash_function = "md5"; // crc32 was another option, but md5 produced better filesizes
|
||||||
// public static $hash_function = "crc32";
|
|
||||||
|
|
||||||
private $root;
|
private $original_root;
|
||||||
private $cache_root;
|
private $cache_root;
|
||||||
|
|
||||||
public function __construct(string $root, string $cache_root)
|
public function __construct(string $original_root, string $cache_root)
|
||||||
{
|
{
|
||||||
$this->root = $root;
|
$this->original_root = $original_root;
|
||||||
$this->cache_root = $cache_root;
|
$this->cache_root = $cache_root;
|
||||||
if (!file_exists($cache_root)) mkdir($cache_root, 0777, true);
|
utils::make_directory($cache_root);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get_root() : string
|
public function get_original_root() : string
|
||||||
{
|
{
|
||||||
return $this->root;
|
return $this->original_root;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get_cache_root() : string
|
public function get_cache_root() : string
|
||||||
@@ -26,7 +27,7 @@ class osu_cacher
|
|||||||
|
|
||||||
public function get_cached_path(string $path) : string
|
public function get_cached_path(string $path) : string
|
||||||
{
|
{
|
||||||
return str_replace($this->root, $this->cache_root, $path) . ".json";
|
return str_replace($this->get_original_root(), $this->cache_root, $path) . ".json";
|
||||||
}
|
}
|
||||||
|
|
||||||
public function is_cached(string $path) : bool
|
public function is_cached(string $path) : bool
|
||||||
@@ -34,29 +35,37 @@ class osu_cacher
|
|||||||
return file_exists($this->get_cached_path($path));
|
return file_exists($this->get_cached_path($path));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get_cache(string $path, $hash=false)// : array|bool // see you again in php8
|
public static function is_hash_invalid(array $json, string $hash) : bool
|
||||||
|
{
|
||||||
|
if (empty($hash)) return false; // empty means hash check has to be skipped
|
||||||
|
if (empty($json["hash"])) return true; // json without a hash is invalid
|
||||||
|
|
||||||
|
return $json["hash"] == $hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get_cache(string $path, string $hash="")// : array|bool // see you again in php8
|
||||||
{
|
{
|
||||||
if (!$this->is_cached($path)) return false;
|
if (!$this->is_cached($path)) return false;
|
||||||
|
|
||||||
$raw = file_get_contents($this->get_cached_path($path));
|
$json = utils::load_json($this->get_cached_path($path));
|
||||||
$json = json_decode($raw, true);
|
|
||||||
|
|
||||||
if (empty($json)) return false; // cache had empty save
|
if (empty($json)) return false; // cache had empty save
|
||||||
|
if (self::is_hash_invalid($json, $hash)) return false;
|
||||||
if ($hash !== false && $hash != ($json["hash"] ?? false)) return false; // hash check failed
|
|
||||||
|
|
||||||
return $json;
|
return $json;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function set_hash_if_not_present(array &$json, string $path) : void
|
||||||
|
{
|
||||||
|
if (!isset($json["hash"])) $json["hash"] = hash_file(self::$hash_function, $path);
|
||||||
|
}
|
||||||
|
|
||||||
public function set_cache(string $path, array $content) : void
|
public function set_cache(string $path, array $content) : void
|
||||||
{
|
{
|
||||||
$cache_path = $this->get_cached_path($path);
|
$cache_path = $this->get_cached_path($path);
|
||||||
$cache_dir = dirname($cache_path);
|
self::set_hash_if_not_present($content, $path);
|
||||||
if (!file_exists($cache_dir)) mkdir($cache_dir, 0777, true);
|
|
||||||
|
|
||||||
if (!isset($content["hash"])) $content["hash"] = hash_file(self::$hash_function, $path);
|
utils::make_directory(dirname($cache_path));
|
||||||
|
file_put_contents($cache_path, json_encode($content));
|
||||||
$encoded = json_encode($content);
|
|
||||||
file_put_contents($cache_path, $encoded);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -24,11 +24,10 @@ class osu_library
|
|||||||
public function scan_library(string $root) : void
|
public function scan_library(string $root) : void
|
||||||
{
|
{
|
||||||
$time_start = microtime(true); // measure scanning time
|
$time_start = microtime(true); // measure scanning time
|
||||||
$root = str_ireplace("\\", "/", $root); // fuck windows backslash
|
$root = utils::to_unix_slashes_without_trail($root);
|
||||||
$root = rtrim($root, "/"); // remove trailing slash(es)
|
|
||||||
|
|
||||||
// giving a different library should always cause a full rescan
|
// giving a different library should always cause a full rescan
|
||||||
if ($this->get_root() !== $root)
|
if ($this->get_osu_root() !== $root)
|
||||||
{
|
{
|
||||||
$this->rescan_library($root);
|
$this->rescan_library($root);
|
||||||
}
|
}
|
||||||
@@ -176,7 +175,7 @@ class osu_library
|
|||||||
if (isset($this->db["library"][$key])) unset($this->db["library"][$key]);
|
if (isset($this->db["library"][$key])) unset($this->db["library"][$key]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get_root() : string
|
public function get_osu_root() : string
|
||||||
{
|
{
|
||||||
return $this->db["root"] ?? "";
|
return $this->db["root"] ?? "";
|
||||||
}
|
}
|
||||||
@@ -228,7 +227,7 @@ class osu_library
|
|||||||
|
|
||||||
public function get_library_folder() : string
|
public function get_library_folder() : string
|
||||||
{
|
{
|
||||||
return $this->get_root() . "/" . self::$song_library_folder;
|
return $this->get_osu_root() . "/" . self::$song_library_folder;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get_library() : array
|
public function get_library() : array
|
||||||
|
|||||||
+92
-95
@@ -34,7 +34,7 @@ class osu_parser
|
|||||||
// fix backslash and double quotes
|
// fix backslash and double quotes
|
||||||
public static function fix_filename(string $filename) : string
|
public static function fix_filename(string $filename) : string
|
||||||
{
|
{
|
||||||
return trim(str_replace("\\", "/", $filename), "\"");
|
return trim(utils::to_unix_slashes($filename), "\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function file_ver_peppy(string $path)// : array|bool // see you in php8
|
public static function file_ver_peppy(string $path)// : array|bool // see you in php8
|
||||||
@@ -106,105 +106,102 @@ class osu_parser
|
|||||||
continue; // this line has been analyzed
|
continue; // this line has been analyzed
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mb_strpos($line, "//") === 0 || // the editor puts hella lot of comments in the files
|
if (!(mb_strpos($line, "//") === 0 || // the editor puts hella lot of comments in the files
|
||||||
$section_type === false)
|
$section_type === false))
|
||||||
{
|
{
|
||||||
}
|
if ($section_type == "key-value pairs")
|
||||||
else if ($section_type == "key-value pairs")
|
|
||||||
{
|
|
||||||
// init empty array
|
|
||||||
if (!isset($parsed[$current_section])) $parsed[$current_section] = array();
|
|
||||||
|
|
||||||
$delimiter_position = mb_strpos($line, $delimiter);
|
|
||||||
|
|
||||||
// old maps had random lines and lines with different delimiters (why?)
|
|
||||||
if ($delimiter_position !== false)
|
|
||||||
{
|
|
||||||
$kv_key = mb_substr($line, 0, $delimiter_position);
|
|
||||||
$kv_value = mb_substr($line, $delimiter_position + strlen($delimiter));
|
|
||||||
|
|
||||||
if ($current_section == "Variables")
|
|
||||||
{
|
|
||||||
$variables["keys"][$kv_key] = $kv_key;
|
|
||||||
$variables["values"][$kv_key] = $kv_value;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// after some thinking, keeping the original names was a good idea
|
|
||||||
$parsed[$current_section][$kv_key] = $kv_value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ($section_type == "lists")
|
|
||||||
{
|
|
||||||
$list = explode($delimiter, $line);
|
|
||||||
if ($current_section == "Events") // saving the whole thing would take up too much space
|
|
||||||
{
|
|
||||||
if (mb_strpos($line, " ") === 0 || mb_strpos($line, "_") === 0) continue; // skip storyboard details lines
|
|
||||||
|
|
||||||
list($event_type, $source_files) = self::gather_source_files($list, $variables);
|
|
||||||
|
|
||||||
if ($event_type === false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
else if ($event_type == "Background")
|
|
||||||
{
|
|
||||||
$parsed["background"] = $source_files[0] ?? "";
|
|
||||||
}
|
|
||||||
else if ($event_type == "Video")
|
|
||||||
{
|
|
||||||
$parsed["video"] = $source_files[0] ?? "";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// init empty array
|
|
||||||
if (!isset($parsed["storyboard"])) $parsed["storyboard"] = array();
|
|
||||||
|
|
||||||
// add the elements to the storyboard
|
|
||||||
foreach ($source_files as $source_file)
|
|
||||||
{
|
|
||||||
$parsed["storyboard"][] = $source_file;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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
|
// init empty array
|
||||||
if (!isset($parsed[$current_section])) $parsed[$current_section] = array();
|
if (!isset($parsed[$current_section])) $parsed[$current_section] = array();
|
||||||
|
|
||||||
// just dump the non-events...
|
$delimiter_position = mb_strpos($line, $delimiter);
|
||||||
//
|
|
||||||
// at the point of writing this
|
// old maps had random lines and lines with different delimiters (why?)
|
||||||
// comment, this section will
|
if ($delimiter_position !== false)
|
||||||
// never get used...
|
{
|
||||||
$parsed[$current_section][] = $line;
|
$kv_key = mb_substr($line, 0, $delimiter_position);
|
||||||
|
$kv_value = mb_substr($line, $delimiter_position + strlen($delimiter));
|
||||||
|
|
||||||
|
if ($current_section == "Variables")
|
||||||
|
{
|
||||||
|
$variables["keys"][$kv_key] = $kv_key;
|
||||||
|
$variables["values"][$kv_key] = $kv_value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// after some thinking, keeping the original names was a good idea
|
||||||
|
$parsed[$current_section][$kv_key] = $kv_value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ($section_type == "lists")
|
||||||
|
{
|
||||||
|
$list = explode($delimiter, $line);
|
||||||
|
if ($current_section == "Events") // saving the whole thing would take up too much space
|
||||||
|
{
|
||||||
|
if (mb_strpos($line, " ") === 0 || mb_strpos($line, "_") === 0) continue; // skip storyboard details lines
|
||||||
|
|
||||||
|
list($event_type, $source_files) = self::gather_source_files($list, $variables);
|
||||||
|
|
||||||
|
else if ($event_type == "Background")
|
||||||
|
{
|
||||||
|
$parsed["background"] = $source_files[0] ?? "";
|
||||||
|
}
|
||||||
|
else if ($event_type == "Video")
|
||||||
|
{
|
||||||
|
$parsed["video"] = $source_files[0] ?? "";
|
||||||
|
}
|
||||||
|
else if ($event_type !== false)
|
||||||
|
{
|
||||||
|
// init empty array
|
||||||
|
if (!isset($parsed["storyboard"])) $parsed["storyboard"] = array();
|
||||||
|
|
||||||
|
// add the elements to the storyboard
|
||||||
|
foreach ($source_files as $source_file)
|
||||||
|
{
|
||||||
|
$parsed["storyboard"][] = $source_file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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
|
||||||
|
if (!isset($parsed[$current_section])) $parsed[$current_section] = array();
|
||||||
|
|
||||||
|
// just dump the non-events...
|
||||||
|
//
|
||||||
|
// at the point of writing this
|
||||||
|
// comment, this section will
|
||||||
|
// never get used...
|
||||||
|
$parsed[$current_section][] = $line;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,4 +26,58 @@ class utils
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// does nothing if the directory already exists
|
||||||
|
public static function make_directory(string $directory) : void
|
||||||
|
{
|
||||||
|
if (!file_exists($directory))
|
||||||
|
{
|
||||||
|
mkdir($directory, 0777, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function load_json(string $path) : array
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$raw = file_get_contents($path);
|
||||||
|
}
|
||||||
|
catch (Exception $e)
|
||||||
|
{
|
||||||
|
$raw = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return json_decode($raw, true) ?? array();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function to_unix_slashes(string $path) : string
|
||||||
|
{
|
||||||
|
return str_replace("\\", "/", $path);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function remove_trailing_slashes(string $path) : string
|
||||||
|
{
|
||||||
|
return rtrim($path, "/");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function to_unix_slashes_without_trail(string $path) : string
|
||||||
|
{
|
||||||
|
return self::remove_trailing_slashes(self::to_unix_slashes($path));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function delete_if_exists(string $file) : void
|
||||||
|
{
|
||||||
|
if (file_exists($file))
|
||||||
|
{
|
||||||
|
unlink($file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function array_delete_if_exists(array $files_list) : void
|
||||||
|
{
|
||||||
|
foreach ($files_list as $file)
|
||||||
|
{
|
||||||
|
self::delete_if_exists($file);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,12 +1,4 @@
|
|||||||
<?php
|
<?php
|
||||||
// todo: cleanup repacker
|
|
||||||
// todo: cleanup cache
|
|
||||||
// todo: cleanup db
|
|
||||||
// todo: cleanup settings (full reset)
|
|
||||||
// todo: whitelist / blacklist
|
|
||||||
// todo: dupe checker
|
|
||||||
// todo: stardiff deleter
|
|
||||||
// todo: mode deleter
|
|
||||||
|
|
||||||
// git does not like empty folders
|
// git does not like empty folders
|
||||||
if (!file_exists("session")) mkdir("session");
|
if (!file_exists("session")) mkdir("session");
|
||||||
@@ -33,7 +25,7 @@ $display = "start";
|
|||||||
|
|
||||||
if (isset($_GET["settings"]) || empty($settings->get_osu_path()))
|
if (isset($_GET["settings"]) || empty($settings->get_osu_path()))
|
||||||
{
|
{
|
||||||
// $display = "start";
|
$display = "start";
|
||||||
}
|
}
|
||||||
else if (isset($_GET["cleanup"]))
|
else if (isset($_GET["cleanup"]))
|
||||||
{
|
{
|
||||||
@@ -150,13 +142,13 @@ if ($display == "main")
|
|||||||
[ "./?settings", "Settings", "Go back to the setup/settings screen.", "Settings" ],
|
[ "./?settings", "Settings", "Go back to the setup/settings screen.", "Settings" ],
|
||||||
[ "./?scan", "Scan", "Only scan for changes.", "Scan" ],
|
[ "./?scan", "Scan", "Only scan for changes.", "Scan" ],
|
||||||
[ "./?rescan", "Force rescan", "Fully rescan the library. <i>(cached)</i>", "Rescan", "Slow" ],
|
[ "./?rescan", "Force rescan", "Fully rescan the library. <i>(cached)</i>", "Rescan", "Slow" ],
|
||||||
[ "./?blacken", "Remove backgrounds", "Replace the background files with 1x1 black images." ],
|
[ "./?blacken", "Remove backgrounds", "Replace the background files with 1x1 black images. So that osu! stays CAAAALLLLLLMMMMMMMM! And so that you can play without using the \"Background Dim\" setting." ],
|
||||||
[ "./?novid", "Remove videos", "" ],
|
[ "./?novid", "Remove videos", "" ],
|
||||||
[ "./?nosb", "Remove storyboards", "" ],
|
[ "./?nosb", "Remove storyboards", "" ],
|
||||||
[ "./?noskin", "Remove beatmap skins", "Does not remove hitsounds & storyboard elements.", null, "Slow" ],
|
[ "./?noskin", "Remove beatmap skins", "Does not remove hitsounds & storyboard elements.", null, "Slow" ],
|
||||||
[ "./?nohit", "Remove custom hitsounds", "Does not remove storyboard elements.", null, "Slow" ],
|
[ "./?nohit", "Remove custom hitsounds", "Does not remove storyboard elements.", null, "Slow" ],
|
||||||
[ "./?purify", "Remove junk files", "Remove everything that isn't referenced in .osu or .osb files.", null, "Very slow" ],
|
[ "./?purify", "Remove junk files", "Remove everything that isn't referenced in .osu or .osb files.", null, "Very slow" ],
|
||||||
[ "./?nuke", "NUKE", "Remove everything that isn't .osu or a referenced audio/background file. Note: old/bad maps might lose vital elements!", "NUKE" ],
|
[ "./?nuke", "NUKE", "Remove everything that isn't .osu or a referenced audio/background file.<br /><br /><b>Note:</b> old/bad maps might lose vital elements!", "NUKE" ],
|
||||||
[ "./?warn=repack&forward=" . urlencode("./?repack&all"), "Repack all", "Repack all maps to .osz files. Note: you should not share exported maps; always use official osu! links.", "Repack ALL", "EXTREMELY slow" ],
|
[ "./?warn=repack&forward=" . urlencode("./?repack&all"), "Repack all", "Repack all maps to .osz files. Note: you should not share exported maps; always use official osu! links.", "Repack ALL", "EXTREMELY slow" ],
|
||||||
[ "./?cleanup", "Clean up", "Reset your settings, delete unused files, or clear cache. This does not touch your osu! folder. Useful after exporting many maps individually.", "Choose what to clean up" ],
|
[ "./?cleanup", "Clean up", "Reset your settings, delete unused files, or clear cache. This does not touch your osu! folder. Useful after exporting many maps individually.", "Choose what to clean up" ],
|
||||||
[ "./splitter.php?page=1", "TBD", null, "Explore" ],
|
[ "./splitter.php?page=1", "TBD", null, "Explore" ],
|
||||||
@@ -172,7 +164,7 @@ if ($display == "main")
|
|||||||
}
|
}
|
||||||
|
|
||||||
$mapset_count = count($lib->get_library());
|
$mapset_count = count($lib->get_library());
|
||||||
$osu_root = $lib->get_root();
|
$osu_root = $lib->get_osu_root();
|
||||||
$parse_time = round($parse_time, 3);
|
$parse_time = round($parse_time, 3);
|
||||||
$scan_time = round($lib->get_scan_time(), 3);
|
$scan_time = round($lib->get_scan_time(), 3);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
<div id="options" class="options">{{ MAIN_OPTIONS }}</div>
|
||||||
|
<div id="loader"></div>
|
||||||
|
<script>{{ MAIN_OPTIONS_SCRIPT }}</script>
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
<!-- https://github.com/Thayol/OsuOptimizerPHP -->
|
<!-- https://github.com/Thayol/osu-optimizer-php -->
|
||||||
<body id="body">
|
<body id="body">
|
||||||
{{ CONTENT }}
|
{{ CONTENT }}
|
||||||
</body>
|
</body>
|
||||||
+2
-2
@@ -1,7 +1,7 @@
|
|||||||
<div class="main-container">
|
<div class="main-container">
|
||||||
<h1>osu! optimizer (PHP)</h1>
|
<h1>osu! optimizer (PHP)</h1>
|
||||||
<h3>Version 0.1 by Thayol</h3>
|
<h3>Version {{ VERSION }} by Thayol</h3>
|
||||||
<p><a href="https://github.com/Thayol/OsuOptimizerPHP">[ GitHub ]</a></p>
|
<p><a href="https://github.com/Thayol/osu-optimizer-php" target="_blank">[ GitHub ]</a></p>
|
||||||
<div class="main-item">
|
<div class="main-item">
|
||||||
<h2>Stats</h2>
|
<h2>Stats</h2>
|
||||||
<h3>
|
<h3>
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
0.1a
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
<h2>MISSING DATABASE</h2>
|
||||||
|
<p>It seems like your database is empty but there is an osu! folder in your settings. </p>
|
||||||
|
<p>Do you wish to continue with a scan?</p>
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<div class="warn">
|
||||||
|
{{ WARN_CONTENT }}
|
||||||
|
<div id="options">
|
||||||
|
<p style="text-align:center;"><a href="{{ WARN_FORWARD_LINK }}" onclick="displayLoading()">[ Yes ]</a> <a href="{{ WARN_BACKWARD_LINK }}">[ No ]</a></p>
|
||||||
|
</div>
|
||||||
|
<div id="loader"></div>
|
||||||
|
</div>
|
||||||
|
<script>{{ MAIN_OPTIONS_SCRIPT }}</script>
|
||||||
Reference in New Issue
Block a user