diff --git a/Project.xml b/Project.xml
index f6754d53..53928e72 100644
--- a/Project.xml
+++ b/Project.xml
@@ -126,6 +126,8 @@
+
+
diff --git a/buildnumber.txt b/buildnumber.txt
index 7b27b251..cd004727 100644
--- a/buildnumber.txt
+++ b/buildnumber.txt
@@ -1 +1 @@
-173
\ No newline at end of file
+182
\ No newline at end of file
diff --git a/source/LoadingState.hx b/source/LoadingState.hx
index 23bce2e6..91f2fb5e 100644
--- a/source/LoadingState.hx
+++ b/source/LoadingState.hx
@@ -151,7 +151,6 @@ class LoadingState extends MusicBeatState
static function getNextState(target:FlxState, stopMusic = false):FlxState
{
- Paths.setCurrentLevel("week" + PlayState.storyWeek);
#if NO_PRELOAD_ALL
var loaded = isSoundLoaded(getSongPath())
&& (!PlayState.SONG.needsVoices || isSoundLoaded(getVocalPath()))
diff --git a/source/Main.hx b/source/Main.hx
index 6809e703..f38e3776 100644
--- a/source/Main.hx
+++ b/source/Main.hx
@@ -16,10 +16,12 @@ import flixel.addons.transition.TransitionData;
import flixel.math.FlxPoint;
import flixel.math.FlxRect;
+#if sys
+import sys.io.File;
+#end
// TODO: REMOVE TEST
import funkin.mods.ModsFolder;
-@:build(funkin.macros.BuildCounterMacro.build())
class Main extends Sprite
{
var gameWidth:Int = 1280; // Width of the game in pixels (might be less / more in actual pixels depending on your zoom).
@@ -97,6 +99,19 @@ class Main extends Sprite
ModsFolder.init();
ModsFolder.loadMod("introMod");
ModsFolder.currentModFolder = "introMod";
+
+ #if sys
+ if (Sys.args().contains("-livereload")) {
+ trace("Used lime test windows. Switching into source assets.");
+ ModsFolder.loadLibraryFromFolder('sourceassets', './../../../../assets/');
+ @:privateAccess
+ Paths.__useSourceAssets = true;
+
+ var buildNum:Int = Std.parseInt(File.getContent("./../../../../buildnumber.txt"));
+ buildNum++;
+ File.saveContent("./../../../../buildnumber.txt", Std.string(buildNum));
+ }
+ #end
FlxG.fixedTimestep = false;
FlxG.autoPause = false;
diff --git a/source/Paths.hx b/source/Paths.hx
index 81cb1537..e493d820 100644
--- a/source/Paths.hx
+++ b/source/Paths.hx
@@ -15,18 +15,11 @@ class Paths
* Currently is set to `mp3` for web targets, and `ogg` for other targets.
*/
inline public static var SOUND_EXT = #if web "mp3" #else "ogg" #end;
-
- static var currentLevel:String;
-
- static public function setCurrentLevel(name:String)
- {
- currentLevel = name.toLowerCase();
- }
+ private static var __useSourceAssets = false;
static function getPath(file:String, type:AssetType, library:Null, skipModsVerification:Bool = false)
{
if (library != null && library.startsWith("mods/")) {
- file = file.toLowerCase();
library = library.toLowerCase();
} else if (!skipModsVerification && ModsFolder.currentModFolder != null) {
var modPath = getPath(file, type, 'mods/${ModsFolder.currentModFolder}');
@@ -36,17 +29,6 @@ class Paths
if (library != null)
return getLibraryPath(file, library);
- if (currentLevel != null)
- {
- var levelPath = getLibraryPathForce(file, currentLevel);
- if (OpenFlAssets.exists(levelPath, type))
- return levelPath;
-
- levelPath = getLibraryPathForce(file, "shared");
- if (OpenFlAssets.exists(levelPath, type))
- return levelPath;
- }
-
return getPreloadPath(file);
}
@@ -62,7 +44,7 @@ class Paths
inline static function getPreloadPath(file:String)
{
- return 'assets/$file';
+ return (__useSourceAssets) ? getLibraryPathForce(file, 'sourceassets') : 'assets/$file';
}
inline static public function file(file:String, type:AssetType = TEXT, ?library:String)
diff --git a/source/funkin/macros/BuildCounterMacro.hx b/source/funkin/macros/BuildCounterMacro.hx
index f0bb1c2e..a5178ae5 100644
--- a/source/funkin/macros/BuildCounterMacro.hx
+++ b/source/funkin/macros/BuildCounterMacro.hx
@@ -5,18 +5,13 @@ import haxe.macro.Context;
import sys.io.File;
class BuildCounterMacro {
- public static function build():Array {
+ // non functional
+ public static macro function getBuildNumber():haxe.macro.Expr.ExprOf {
+ #if !display
var buildNum:Int = Std.parseInt(File.getContent("buildnumber.txt"));
- buildNum++;
-
- var fields = Context.getBuildFields();
- fields.push({
- name: "buildNumber",
- access: [APublic, AStatic, AInline],
- kind: FieldType.FVar(macro:Int, macro $v{buildNum}),
- pos: Context.currentPos(),
- });
- File.saveContent("buildnumber.txt", Std.string(buildNum));
- return fields;
+ return macro $v{buildNum};
+ #else
+ return macro $v{0};
+ #end
}
}
\ No newline at end of file
diff --git a/source/funkin/menus/MainMenuState.hx b/source/funkin/menus/MainMenuState.hx
index 48aabd08..6c9b42e8 100644
--- a/source/funkin/menus/MainMenuState.hx
+++ b/source/funkin/menus/MainMenuState.hx
@@ -95,8 +95,8 @@ class MainMenuState extends MusicBeatState
FlxG.camera.follow(camFollow, null, 0.06);
- trace(Main.buildNumber);
- var versionShit:FlxText = new FlxText(5, FlxG.height - 2, 0, 'Codename Engine v${Application.current.meta.get('version')}\nPre-Alpha: Build ${Main.buildNumber}\n', 12);
+ trace(funkin.macros.BuildCounterMacro.getBuildNumber());
+ var versionShit:FlxText = new FlxText(5, FlxG.height - 2, 0, 'Codename Engine v${Application.current.meta.get('version')}\nPre-Alpha: Build ${funkin.macros.BuildCounterMacro.getBuildNumber()}\n', 12);
versionShit.scrollFactor.set();
versionShit.setFormat("VCR OSD Mono", 16, FlxColor.WHITE, LEFT, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK);
versionShit.y -= versionShit.height;
diff --git a/source/funkin/mods/ModsAssetLibrary.hx b/source/funkin/mods/ModsAssetLibrary.hx
index 48908898..4660f5c7 100644
--- a/source/funkin/mods/ModsAssetLibrary.hx
+++ b/source/funkin/mods/ModsAssetLibrary.hx
@@ -1,44 +1,137 @@
-
-// REDO THIS FOR FILE SUPPORT KINDA LIKE PSYCH BUT NOT MESSY
-
package funkin.mods;
+import lime.utils.Log;
import sys.FileStat;
import sys.FileSystem;
-import openfl.utils.AssetLibrary;
+import lime.utils.AssetLibrary;
import lime.utils.AssetManifest;
+import haxe.io.Path;
+import lime.app.Event;
+import lime.app.Future;
+import lime.app.Promise;
+import lime.media.AudioBuffer;
+import lime.graphics.Image;
+import lime.net.HTTPRequest;
+import lime.text.Font;
+import lime.utils.AssetType;
+import lime.utils.Bytes;
+
+using StringTools;
+
class ModsAssetLibrary extends AssetLibrary {
- private var editedTimes:Map = [];
- #if sys
- public override function __fromManifest(manifest:AssetManifest) {
- super.__fromManifest(manifest);
+ public var folderPath:String;
+ public var libName:String;
- var basePath = manifest.rootPath;
- if (basePath == null) basePath = "";
- if (basePath != "") basePath += "/";
-
- var stat:FileStat;
- for(asset in manifest.assets) {
- var id = asset.id;
- var assetPath = __cacheBreak(basePath + Reflect.field(asset, "path"));
- try {
- stat = FileSystem.stat(assetPath);
- if (stat != null) {
- editedTimes.set(id, stat.mtime.getTime());
- }
- } catch(e) {
- trace(e);
- }
- }
+ public function new(folderPath:String, libName:String) {
+ this.folderPath = folderPath;
+ this.libName = libName;
+ super();
}
- #end
+
+ #if sys
+ private var editedTimes:Map = [];
+ var _parsedAsset:String = null;
public function getEditedTime(asset:String):Null {
- #if sys
return editedTimes[asset];
- #else
- return null;
- #end
}
+
+ public override function getAudioBuffer(id:String):AudioBuffer {
+ if (__isCacheValid(cachedAudioBuffers, id))
+ return cachedAudioBuffers.get(id);
+ else {
+ if (!exists(id, "SOUND")) {
+ Log.error('ModsAssetLibrary: Audio Buffer at $id does not exist.');
+ return null;
+ }
+ var path = getAssetPath();
+ editedTimes[id] = FileSystem.stat(path).mtime.getTime();
+ var e = AudioBuffer.fromFile(path);
+ cachedAudioBuffers.set(id, e);
+ return e;
+ }
+ }
+
+ public override function getBytes(id:String):Bytes {
+ if (__isCacheValid(cachedBytes, id))
+ return cachedBytes.get(id);
+ else {
+ if (!exists(id, "BINARY")) {
+ Log.error('ModsAssetLibrary: Bytes at $id does not exist.');
+ return null;
+ }
+ var path = getAssetPath();
+ editedTimes[id] = FileSystem.stat(path).mtime.getTime();
+ var e = Bytes.fromFile(path);
+ cachedBytes.set(id, e);
+ return e;
+ }
+ }
+
+ public override function getFont(id:String):Font {
+ if (__isCacheValid(cachedFonts, id))
+ return cachedFonts.get(id);
+ else {
+ if (!exists(id, "FONT")) {
+ Log.error('ModsAssetLibrary: Font at $id does not exist.');
+ return null;
+ }
+ var path = getAssetPath();
+ editedTimes[id] = FileSystem.stat(path).mtime.getTime();
+ var e = Font.fromFile(path);
+ cachedFonts.set(id, e);
+ return e;
+ }
+ }
+
+ public override function getImage(id:String):Image {
+ if (__isCacheValid(cachedImages, id))
+ return cachedImages.get(id);
+ else {
+ if (!exists(id, "IMAGE")) {
+ Log.error('ModsAssetLibrary: Image at $id does not exist.');
+ return null;
+ }
+ var path = getAssetPath();
+ editedTimes[id] = FileSystem.stat(path).mtime.getTime();
+
+ var e = Image.fromFile(path);
+ cachedImages.set(id, e);
+ return e;
+ }
+ }
+
+ public override function getPath(id:String):String {
+ if (!__parseAsset(id)) return null;
+ return getAssetPath();
+ }
+
+ public override function exists(asset:String, type:String):Bool {
+ if(!__parseAsset(asset)) return false;
+
+ return FileSystem.exists(getAssetPath());
+ }
+
+ private function getAssetPath() {
+ return '$folderPath/$_parsedAsset';
+ }
+
+ private function __isCacheValid(cache:Map, asset:String) {
+ if (!editedTimes.exists(asset))
+ return false;
+
+
+ if (editedTimes[asset] == null) return true;
+ if (editedTimes[asset] < FileSystem.stat(getPath(asset)).mtime.getTime()) return false;
+ return true;
+ }
+
+ private function __parseAsset(asset:String):Bool {
+ var prefix = 'assets/$libName/';
+ if (!asset.startsWith(prefix)) return false;
+ _parsedAsset = asset.substr(prefix.length);
+ return true;
+ }
+ #end
}
\ No newline at end of file
diff --git a/source/funkin/mods/ModsFolder.hx b/source/funkin/mods/ModsFolder.hx
index 417f8178..63e21c15 100644
--- a/source/funkin/mods/ModsFolder.hx
+++ b/source/funkin/mods/ModsFolder.hx
@@ -3,6 +3,7 @@ package funkin.mods;
import openfl.utils.Assets;
import openfl.utils.AssetManifest;
import openfl.utils.AssetLibrary;
+import flixel.graphics.FlxGraphic;
import sys.FileSystem;
import flixel.FlxG;
import flixel.FlxState;
@@ -43,28 +44,33 @@ class ModsFolder {
* @param modName Name of the mod
* @param force Whenever the mod should be reloaded if it has already been loaded
*/
- public static function loadMod(mod:String, ?force:Bool = false) {
- var libName = 'mods/$mod'.toLowerCase();
+ public static function loadMod(mod:String, force:Bool = false) {
+ var e = loadLibraryFromFolder('mods/$mod'.toLowerCase(), '${modsPath}$mod', force);
+ loadedMods.push(mod);
+ return e;
+ }
+ public static function loadLibraryFromFolder(libName:String, folder:String, force:Bool = false) {
if (Assets.hasLibrary(libName)) {
if (force)
Assets.unloadLibrary(libName);
else
- checkForOutdatedAssets(cast Assets.getLibrary(libName));
+ return null;
}
var assets:AssetManifest = new AssetManifest();
- assets.name = libName;// for case sensitive shit & correct linux support
+ assets.name = libName;
assets.libraryType = 'funkin.mods.ModsAssetLibrary';
assets.version = 2;
assets.libraryArgs = [];
- assets.rootPath = '${modsPath}/$mod/';
+ assets.rootPath = folder;
assets.assets = [];
- getAssetFiles(assets.assets, '${modsPath}/$mod/', '', libName);
var lib = AssetLibrary.fromManifest(assets);
- openfl.utils.Assets.registerLibrary(libName, lib);
- loadedMods.push(mod);
+ @:privateAccess
+ lib.__proxy = new ModsAssetLibrary(assets.rootPath, assets.name);
+ Assets.registerLibrary(libName, lib);
+ return lib;
}
/**
@@ -137,7 +143,50 @@ class ModsFolder {
if (currentModFolder == null) return;
#if sys
- loadMod(currentModFolder, false); // hot reloading 🔥
+ var bmapsToRemove:Array = [];
+ @:privateAccess
+ for(bmap in FlxG.bitmap._cache) {
+ if (bmap.assetsKey != null) {
+ var e = new LibrarySymbol(bmap.assetsKey);
+ trace(bmap.assetsKey);
+ if (e.library is openfl.utils.AssetLibrary) {
+ @:privateAccess
+ e.library = cast(e.library, openfl.utils.AssetLibrary).__proxy;
+ }
+ if (e.library is ModsAssetLibrary) {
+ var lib = cast(e.library, ModsAssetLibrary);
+ if (!lib.__parseAsset(e.symbolName)) continue;
+ if (!lib.__isCacheValid(lib.cachedImages, lib._parsedAsset)) {
+ lib.cachedImages.remove(lib._parsedAsset);
+ bmapsToRemove.push(bmap);
+ }
+ }
+ }
+ }
+ for(e in bmapsToRemove)
+ FlxG.bitmap.remove(e);
+
#end
}
+}
+
+class LibrarySymbol
+{
+ public var library:lime.utils.AssetLibrary;
+ public var libraryName:String;
+ public var symbolName:String;
+
+ public inline function new(id:String)
+ {
+ var colonIndex = id.indexOf(":");
+ libraryName = id.substring(0, colonIndex);
+ symbolName = id.substring(colonIndex + 1);
+ library = lime.utils.Assets.getLibrary(libraryName);
+ }
+
+ public inline function isLocal(?type)
+ return library.isLocal(symbolName, type);
+
+ public inline function exists(?type)
+ return library.exists(symbolName, type);
}
\ No newline at end of file