new assets system

This commit is contained in:
Yoshman29
2022-12-03 19:26:00 +01:00
parent efccfa37ac
commit 2255e251ac
10 changed files with 153 additions and 103 deletions
+1 -1
View File
@@ -1 +1 @@
1340
1354
+1 -1
View File
@@ -186,7 +186,7 @@ class FreeplayState extends MusicBeatState
curDifficulty = FlxMath.wrap(curDifficulty + change, 0, curSong.difficulties.length-1);
#if !switch
intendedScore = Highscore.getScore(songs[curSelected].songName, songs[curSelected].difficulties[curDifficulty]).score;
intendedScore = Highscore.getScore(curSong.songName, curSong.difficulties[curDifficulty]).score;
#end
+6 -2
View File
@@ -9,14 +9,18 @@ class ModdableAssetsFolder extends ModsFolderLibrary {
public var oldLibrary:AssetLibrary;
public override function exists(id:String, type:String) {
if (!id.startsWith("assets/"))
if (!id.startsWith("assets/") && !exists('assets/$id', type))
return oldLibrary.exists(id, type);
return super.exists(id, type);
}
public override function getAsset(id:String, type:String) {
if (!id.startsWith("assets/"))
if (!id.startsWith("assets/")) {
var possibleReplacement = getAsset('assets/$id', type);
if (possibleReplacement != null)
return possibleReplacement;
return oldLibrary.getAsset(id, type);
}
return super.getAsset(id, type);
}
+2
View File
@@ -23,6 +23,8 @@ import sys.FileSystem;
using StringTools;
interface ModsAssetLibrary {
public var prefix:String;
#if MOD_SUPPORT
public var _parsedAsset:String;
+26 -73
View File
@@ -30,9 +30,9 @@ class ModsFolder {
*/
public static var currentModFolder:String = null;
/**
* Array of all loaded mods' folder names.
* Map all loaded mods' folder libraries.
*/
public static var loadedMods:Array<String> = [];
public static var loadedMods:Map<String, lime.utils.AssetLibrary> = [];
/**
* Path to the `mods` folder.
*/
@@ -54,15 +54,11 @@ class ModsFolder {
#if MOD_SUPPORT
if (mod == null) return null; // may be loading base game
if (FileSystem.exists('${modsPath}$mod.zip')) {
var e = loadLibraryFromZip('mods/$mod'.toLowerCase(), '${modsPath}$mod.zip', force);
loadedMods.push(mod);
return e;
} else {
var e = loadLibraryFromFolder('mods/$mod'.toLowerCase(), '${modsPath}$mod', force);
loadedMods.push(mod);
return e;
}
if (FileSystem.exists('${modsPath}$mod.zip'))
return loadedMods[mod] = loadLibraryFromZip('mods/$mod'.toLowerCase(), '${modsPath}$mod.zip', force);
else
return loadedMods[mod] = loadLibraryFromFolder('mods/$mod'.toLowerCase(), '${modsPath}$mod', force);
#else
return null;
#end
@@ -73,16 +69,17 @@ class ModsFolder {
* @param libName
*/
public static function switchMod(mod:String) {
for(m in loadedMods)
unloadMod(m);
loadMod(ModsFolder.currentModFolder = mod);
unloadMod(ModsFolder.currentModFolder);
Paths.assetsTree.addLibrary(loadMod(ModsFolder.currentModFolder = mod));
Main.refreshAssets();
onModSwitch.dispatch(ModsFolder.currentModFolder);
FlxG.resetState();
}
public static function unloadMod(mod:String) {
if (mod == null) return;
Paths.assetsTree.removeLibrary(loadedMods[mod]);
Assets.unloadLibrary('mods/$mod'.toLowerCase());
}
@@ -103,64 +100,20 @@ class ModsFolder {
return AssetLibrary.fromManifest(assets);
}
public static function prepareModLibrary(libName:String, lib:ModsAssetLibrary, force:Bool = false) {
var openLib = prepareLibrary(libName, force);
lib.prefix = 'assets/';
@:privateAccess
openLib.__proxy = cast(lib, lime.utils.AssetLibrary);
Assets.registerLibrary(libName, openLib);
return openLib;
}
public static function loadLibraryFromFolder(libName:String, folder:String, force:Bool = false) {
return prepareModLibrary(libName, new ModsFolderLibrary(folder, libName), force);
}
public static function loadLibraryFromZip(libName:String, zipPath:String, force:Bool = false) {
var lib = prepareLibrary(libName, force);
@:privateAccess
lib.__proxy = new ZipFolderLibrary(zipPath, libName);
Assets.registerLibrary(libName, lib);
return lib;
}
public static function loadLibraryFromFolder(libName:String, folder:String, force:Bool = false, useOldWhenMissing:Bool = false) {
var oldLib = useOldWhenMissing ? Assets.getLibrary(libName) : null;
var lib = prepareLibrary(libName, force);
@:privateAccess
lib.__proxy = useOldWhenMissing ? new ModdableAssetsFolder(folder, libName, oldLib) : new ModsFolderLibrary(folder, libName);
Assets.registerLibrary(libName, lib);
return lib;
}
/**
* Gets all assets in folders and put them in the `assets` array.
* @param assets Array of assets
* @param rootPath Root path
* @param path Path inside of the rootPath (ex: `root path/path/path2/`)
* @param libraryName Name of the library (ex: `mods/my mod/`)
* @param prefix Prefix for the asset names (ex: `assets/mods/my mod/`)
* @param addRoot Whenever the root should be added to the paths. Defaults to false
*/
public static function getAssetFiles(assets:Array<Dynamic>, rootPath:String, path:String, libraryName:String, prefix:String = "", addRoot:Bool = false) {
#if sys
for(f in FileSystem.readDirectory('$rootPath$path')) {
if (FileSystem.isDirectory('$rootPath$path$f')) {
// fuck you git
if (f.toLowerCase() != ".git")
getAssetFiles(assets, rootPath, '$path$f/', libraryName);
} else {
var type = "BINARY";
var useExt:Bool = true;
switch(Path.extension(f).toLowerCase()) {
case "txt" | "xml" | "json" | "hx" | "hscript" | "hsc" | "lua" | "frag" | "vert":
type = "TEXT";
case "png":
type = "IMAGE";
case "ogg":
type = path.toLowerCase().startsWith("music") ? "MUSIC" : "SOUND";
case "ttf":
type = "FONT";
useExt = false;
}
var stat = FileSystem.stat('$rootPath$path$f');
assets.push({
type: type,
id: ('assets/$libraryName/$prefix$path${useExt ? f : Path.withoutExtension(f)}').toLowerCase(), // for case sensitive shit & correct linux support
path: (addRoot ? rootPath : '') + '$path$f',
size: stat.size,
edited: stat.mtime.getTime() / 1000
});
}
}
#end
return prepareModLibrary(libName, new ZipFolderLibrary(zipPath, libName), force);
}
}
+6 -13
View File
@@ -27,10 +27,12 @@ class ModsFolderLibrary extends AssetLibrary implements ModsAssetLibrary {
public var folderPath:String;
public var libName:String;
public var useImageCache:Bool = true;
public var prefix = 'assets/';
public function new(folderPath:String, libName:String) {
this.folderPath = folderPath;
this.libName = libName;
this.prefix = 'assets/$libName/';
super();
}
@@ -48,10 +50,8 @@ class ModsFolderLibrary extends AssetLibrary implements ModsAssetLibrary {
return LimeAssets.cache.audio.get('$libName:$id');
}
else {
if (!exists(id, "SOUND")) {
Log.error('ModsAssetLibrary: Audio Buffer at $id does not exist.');
if (!exists(id, "SOUND"))
return null;
}
var path = getAssetPath();
editedTimes[id] = FileSystem.stat(path).mtime.getTime();
var e = AudioBuffer.fromFile(path);
@@ -64,10 +64,8 @@ class ModsFolderLibrary extends AssetLibrary implements ModsAssetLibrary {
if (__isCacheValid(cachedBytes, id, true))
return cachedBytes.get(id);
else {
if (!exists(id, "BINARY")) {
Log.error('ModsAssetLibrary: Bytes at $id does not exist.');
if (!exists(id, "BINARY"))
return null;
}
var path = getAssetPath();
editedTimes[id] = FileSystem.stat(path).mtime.getTime();
var e = Bytes.fromFile(path);
@@ -80,10 +78,8 @@ class ModsFolderLibrary extends AssetLibrary implements ModsAssetLibrary {
if (__isCacheValid(LimeAssets.cache.font, id))
return LimeAssets.cache.font.get(id);
else {
if (!exists(id, "FONT")) {
Log.error('ModsAssetLibrary: Font at $id does not exist.');
if (!exists(id, "FONT"))
return null;
}
var path = getAssetPath();
editedTimes[id] = FileSystem.stat(path).mtime.getTime();
var e = Font.fromFile(path);
@@ -95,10 +91,8 @@ class ModsFolderLibrary extends AssetLibrary implements ModsAssetLibrary {
if (useImageCache && __isCacheValid(LimeAssets.cache.image, id))
return LimeAssets.cache.image.get('$libName:$id');
else {
if (!exists(id, "IMAGE")) {
Log.error('ModsAssetLibrary: Image at $id does not exist.');
if (!exists(id, "IMAGE"))
return null;
}
var path = getAssetPath();
editedTimes[id] = FileSystem.stat(path).mtime.getTime();
@@ -150,7 +144,6 @@ class ModsFolderLibrary extends AssetLibrary implements ModsAssetLibrary {
}
private function __parseAsset(asset:String):Bool {
var prefix = 'assets/$libName/';
if (!asset.startsWith(prefix)) return false;
_parsedAsset = asset.substr(prefix.length);
return true;
+2 -1
View File
@@ -29,6 +29,7 @@ class ZipFolderLibrary extends AssetLibrary implements ModsAssetLibrary {
public var zipPath:String;
public var libName:String;
public var useImageCache:Bool = false;
public var prefix = 'assets/';
#if MOD_SUPPORT
public var zip:Reader;
@@ -38,6 +39,7 @@ class ZipFolderLibrary extends AssetLibrary implements ModsAssetLibrary {
public function new(zipPath:String, libName:String) {
this.zipPath = zipPath;
this.libName = libName;
this.prefix = 'assets/$libName/';
#if MOD_SUPPORT
zip = new Reader(File.read(zipPath, true));
@@ -124,7 +126,6 @@ class ZipFolderLibrary extends AssetLibrary implements ModsAssetLibrary {
}
public function __parseAsset(asset:String):Bool {
var prefix = 'assets/$libName/';
if (!asset.startsWith(prefix)) return false;
_parsedAsset = asset.substr(prefix.length).toLowerCase();
return true;
+79
View File
@@ -0,0 +1,79 @@
package funkin.system;
import funkin.mods.ModsAssetLibrary;
import openfl.utils.Assets;
import lime.utils.AssetLibrary;
class AssetsLibraryList extends AssetLibrary {
public var libraries:Array<AssetLibrary> = [];
public var base:AssetLibrary;
public function removeLibrary(lib:AssetLibrary) {
if (lib == null) return lib;
libraries.remove(lib);
return lib;
}
public override function exists(id:String, type:String) {
if (!id.startsWith("assets/") && exists('assets/$id', type))
return true;
for(e in libraries)
if (e.exists(id, type))
return true;
return false;
}
public override function getPath(id:String) {
for(e in libraries) {
var path = e.getPath(id);
if (path != null)
return path;
}
return null;
}
public function getFiles(folder:String):Array<String> {
var content:Array<String> = [];
for(e in libraries) {
var l = e;
if (l is openfl.utils.AssetLibrary) {
@:privateAccess
l = cast(l, openfl.utils.AssetLibrary).__proxy;
}
// TODO: do base folder scanning
if (l is ModsAssetLibrary) {
var lib = cast(l, ModsAssetLibrary);
for(e in lib.getFiles(folder))
content.push(e);
}
}
return content;
}
public override function getAsset(id:String, type:String) {
if (!id.startsWith("assets/")) {
var ass = getAsset('assets/$id', type);
if (ass != null)
return ass;
}
for(e in libraries) {
var asset = e.getAsset(id, type);
if (asset != null)
return asset;
}
return null;
}
public function new(?base:AssetLibrary) {
super();
if (base == null)
base = Assets.getLibrary("default");
addLibrary(this.base = base);
}
public function addLibrary(lib:AssetLibrary) {
libraries.insert(0, lib);
return lib;
}
}
+17 -2
View File
@@ -1,5 +1,6 @@
package funkin.system;
import openfl.utils.AssetLibrary;
import openfl.utils.AssetCache;
import openfl.text.TextFormat;
import flixel.system.ui.FlxSoundTray;
@@ -111,6 +112,8 @@ class Main extends Sprite
public function loadGameSettings() {
Paths.assetsTree = new AssetsLibraryList();
Logs.init();
// TODO: Mod switching
@@ -127,7 +130,9 @@ class Main extends Sprite
if (Sys.args().contains("-livereload")) {
#if USE_SOURCE_ASSETS
trace("Used lime test windows. Switching into source assets.");
ModsFolder.loadLibraryFromFolder('default', './../../../../assets/', true, true);
Paths.assetsTree.addLibrary(ModsFolder.loadLibraryFromFolder('assets', './../../../../assets/', true));
#else
Assets.registerLibrary('assets', Paths.assetsTree.base);
#end
var buildNum:Int = Std.parseInt(File.getContent("./../../../../buildnumber.txt"));
@@ -135,11 +140,21 @@ class Main extends Sprite
File.saveContent("./../../../../buildnumber.txt", Std.string(buildNum));
} else {
#if USE_ADAPTED_ASSETS
ModsFolder.loadLibraryFromFolder('default', './assets/', true, true);
Paths.assetsTree.addLibrary(ModsFolder.loadLibraryFromFolder('assets', './assets/', true));
#else
Assets.registerLibrary('assets', Paths.assetsTree.base);
#end
}
#else
Assets.registerLibrary('assets', Paths.assetsTree.base);
#end
var lib = new AssetLibrary();
@:privateAccess
lib.__proxy = Paths.assetsTree;
Assets.registerLibrary('default', lib);
funkin.options.PlayerSettings.init();
FlxG.save.bind('Save');
Options.load();
+13 -10
View File
@@ -19,19 +19,14 @@ class Paths
*/
inline public static var SOUND_EXT = #if web "mp3" #else "ogg" #end;
public static var assetsTree:AssetsLibraryList;
public static function getPath(file:String, type:AssetType, library:Null<String>, skipModsVerification:Bool = false)
{
if (library != null && library.startsWith("mods/")) {
library = library.toLowerCase();
} else if (!skipModsVerification && ModsFolder.currentModFolder != null) {
var modPath = getPath(file, type, 'mods/${ModsFolder.currentModFolder}');
if (OpenFlAssets.exists(modPath)) return modPath;
}
if (library != null)
return getLibraryPath(file, library);
return getAssetsPath(file);
return skipModsVerification ? 'assets:${getAssetsPath(file)}' : getAssetsPath(file);
}
static public function video(key:String) {
@@ -188,13 +183,20 @@ class Paths
static public function getFolderContent(key:String, includeSource:Bool = true, addPath:Bool = false, scanSource:Bool = false):Array<String> {
// designed to work both on windows and web
if (!key.endsWith("/")) key += "/";
var content = assetsTree.getFiles('assets/$key');
if (addPath) {
for(k=>e in content)
content[k] = '$key$e';
}
return content;
/*
if (!key.endsWith("/")) key = key + "/";
if (ModsFolder.currentModFolder == null && !scanSource)
return getFolderContent(key, false, addPath, true);
var folderPath:String = scanSource ? getPreloadPath(key) : getLibraryPathForce(key, 'mods/${ModsFolder.currentModFolder}');
var folderPath:String = scanSource ? getAssetsPath(key) : getLibraryPathForce(key, 'mods/${ModsFolder.currentModFolder}');
var libThing = new LimeLibrarySymbol(folderPath);
var library = libThing.library;
@@ -239,5 +241,6 @@ class Paths
}
return content;
*/
}
}