From 5541dd6832ae3881a1c6c72e131baf2d02341d5e Mon Sep 17 00:00:00 2001 From: ItsLJcool <54383469+ItsLJcool@users.noreply.github.com> Date: Wed, 3 Sep 2025 21:55:40 -0700 Subject: [PATCH 01/16] well boys I fixed it. you can now have Zipped Mods!!!!! --- .../funkin/backend/assets/ZipFolderLibrary.hx | 1 - source/funkin/backend/utils/CoolUtil.hx | 15 ++ source/funkin/backend/utils/SysZip.hx | 180 +++++++----------- 3 files changed, 87 insertions(+), 109 deletions(-) diff --git a/source/funkin/backend/assets/ZipFolderLibrary.hx b/source/funkin/backend/assets/ZipFolderLibrary.hx index 68ef537a5..f10f80f6e 100644 --- a/source/funkin/backend/assets/ZipFolderLibrary.hx +++ b/source/funkin/backend/assets/ZipFolderLibrary.hx @@ -31,7 +31,6 @@ class ZipFolderLibrary extends AssetLibrary implements IModsAssetLibrary { this.modName = (modName == null) ? libName : modName; zip = SysZip.openFromFile(basePath); - zip.read(); for(entry in zip.entries) { lowerCaseAssets[entry.fileName.toLowerCase()] = assets[entry.fileName.toLowerCase()] = assets[entry.fileName] = entry; nameMap.set(entry.fileName.toLowerCase(), entry.fileName); diff --git a/source/funkin/backend/utils/CoolUtil.hx b/source/funkin/backend/utils/CoolUtil.hx index d06b416c3..18e6c7dcd 100644 --- a/source/funkin/backend/utils/CoolUtil.hx +++ b/source/funkin/backend/utils/CoolUtil.hx @@ -1435,6 +1435,21 @@ final class CoolUtil return toProperty.setValue(fromProperty.getValue()); } + + private static var lastTimeStamp:Float = -1; + public static function debugTimeStamp() { + if (lastTimeStamp != -1) { + var endTimeStamp = haxe.Timer.stamp(); + Logs.traceColored([ + Logs.logText("[Haxe Time Stamp] ", YELLOW), + Logs.logText(customText), + Logs.logText(' | Time stamp took ${(endTimeStamp - lastTimeStamp)} milliseconds.'), + ], INFO); + lastTimeStamp = -1; + return; + } + lastTimeStamp = haxe.Timer.stamp(); + } } class PropertyInfo { diff --git a/source/funkin/backend/utils/SysZip.hx b/source/funkin/backend/utils/SysZip.hx index b1c013fbd..db4cbaa6a 100644 --- a/source/funkin/backend/utils/SysZip.hx +++ b/source/funkin/backend/utils/SysZip.hx @@ -2,157 +2,121 @@ package funkin.backend.utils; #if sys import haxe.io.Input; -import haxe.zip.Entry; -import haxe.zip.InflateImpl; import haxe.zip.Reader; import sys.io.File; import sys.io.FileInput; +import haxe.io.Bytes; + /** * Class that extends Reader allowing you to load ZIP entries without blowing your RAM up!! - * Half of the code is taken from haxe libraries btw + * ~~Half of the code is taken from haxe libraries btw~~ Reworked by ItsLJcool to actually work for zip files. */ class SysZip extends Reader { - var input:Input; var fileInput:FileInput; + var filePath:String; public var entries:List; /** * Opens a zip from a specified path. - * @param path Path to the zip file. + * @param path Path to the zip file. (With the extension) */ - public static function openFromFile(path:String) { - - return new SysZip(File.read(path, true)); - } + public static function openFromFile(path:String) { return new SysZip(path); } // keeping for compatibility. /** - * Creates a new SysZip from a specified file input. - * @param input File input. + * Creates a new SysZip from a specified path. + * @param path Path to the zip file. (With the extension) */ - public function new(input:FileInput) { - super(input); - fileInput = input; - } + public function new(path:String) { + this.filePath = path; + fileInput = File.read(path, true); + super(fileInput); - /** - * Reads all the data present in a specified entry. - * NOTE: If the entry is compressed, the data won't be decompressed. For decompression, use `unzipEntry`. - * @param e Entry - */ - public function readEntryData(e:SysZipEntry) { - var bytes:haxe.io.Bytes = null; - var buf = null; - var tmp = null; - - fileInput.seek(e.seekPos, SeekBegin); - if (e.crc32 == null) { - if (e.compressed) { - #if neko - // enter progressive mode : we use a different input which has - // a temporary buffer, this is necessary since we have to uncompress - // progressively, and after that we might have pending read data - // that needs to be processed - var bufSize = 65536; - if (buf == null) { - buf = new haxe.io.BufferInput(i, haxe.io.Bytes.alloc(bufSize)); - tmp = haxe.io.Bytes.alloc(bufSize); - i = buf; - } - var out = new haxe.io.BytesBuffer(); - var z = new neko.zip.Uncompress(-15); - z.setFlushMode(neko.zip.Flush.SYNC); - while (true) { - if (buf.available == 0) - buf.refill(); - var p = bufSize - buf.available; - if (p != buf.pos) { - // because of lack of "srcLen" in zip api, we need to always be stuck to the buffer end - buf.buf.blit(p, buf.buf, buf.pos, buf.available); - buf.pos = p; - } - var r = z.execute(buf.buf, buf.pos, tmp, 0); - out.addBytes(tmp, 0, r.write); - buf.pos += r.read; - buf.available -= r.read; - if (r.done) - break; - } - bytes = out.getBytes(); - #else - var bufSize = 65536; - if (tmp == null) - tmp = haxe.io.Bytes.alloc(bufSize); - var out = new haxe.io.BytesBuffer(); - var z = new InflateImpl(i, false, false); - while (true) { - var n = z.readBytes(tmp, 0, bufSize); - out.addBytes(tmp, 0, n); - if (n < bufSize) - break; - } - bytes = out.getBytes(); - #end - } else - bytes = i.read(e.dataSize); - e.crc32 = i.readInt32(); - if (e.crc32 == 0x08074b50) - e.crc32 = i.readInt32(); - e.dataSize = i.readInt32(); - e.fileSize = i.readInt32(); - // set data to uncompressed - e.dataSize = e.fileSize; - e.compressed = false; - } else - bytes = i.read(e.dataSize); - return bytes; + updateEntries(); } /** * Unzips and returns all of the data present in an entry. * @param f Entry to read from. */ - public function unzipEntry(f:SysZipEntry) { - var data = readEntryData(f); + public function unzipEntry(f:SysZipEntry):Bytes { + fileInput.seek(f.seekPos, SeekBegin); + var data = fileInput.read(f.compressedSize); + + if (!f.compressed) return data; - if (!f.compressed) - return data; var c = new haxe.zip.Uncompress(-15); - var s = haxe.io.Bytes.alloc(f.fileSize); + var s = Bytes.alloc(f.fileSize); var r = c.execute(data, 0, s, 0); c.close(); - if (!r.done || r.read != data.length || r.write != f.fileSize) - throw "Invalid compressed data for " + f.fileName; - data = s; - return data; + + if (!r.done || r.read != data.length || r.write != f.fileSize) throw "Invalid compressed data for " + f.fileName; + return s; } - public override function read():List { - if (entries != null) - return entries; + public function updateEntries() { entries = new List(); + + // --- locate End of Central Directory (EOCD) --- + var fileSize:Int = sys.FileSystem.stat(this.filePath).size; // probably need a better way to check the size of the file. + var scanSize:Int = (65535 < fileSize) ? 65535 : fileSize; + + fileInput.seek(fileSize - scanSize, SeekBegin); // It seems this usually ends up being 0 anyways, but for cases where it might not be?? I'd just make sure. but Someone do some digging I don't know if this required. + + var buf = fileInput.read(scanSize); + var b = new haxe.io.BytesInput(buf); + b.position = (buf.length - 22) + 16; // offset to start of central directory + + // --- read central directory --- + fileInput.seek(b.readInt32(), SeekBegin); while (true) { - var e = readEntryHeader(); - if (e == null) - break; + if (fileInput.readInt32() != 0x02014b50) break; // central dir file header signature + + fileInput.seek(6, SeekCur); // version/flags + var compMethod = fileInput.readUInt16(); + fileInput.seek(8, SeekCur); // time/date + CRC32 (4, 4) + var compSize = fileInput.readInt32(); + var uncompSize = fileInput.readInt32(); + var nameLen = fileInput.readUInt16(); + var extraLen = fileInput.readUInt16(); + var commentLen = fileInput.readUInt16(); + fileInput.seek(8, SeekCur); // skip disk number/start attrs + var localHeaderOffset = fileInput.readInt32(); + + var name = fileInput.read(nameLen).toString(); + + // skip central directory extra/comment + fileInput.seek(extraLen + commentLen, SeekCur); + + // --- compute correct seekPos using local header --- + var curPos = fileInput.tell(); + fileInput.seek(localHeaderOffset + 26, SeekBegin); + var localNameLen = fileInput.readUInt16(); + var localExtraLen = fileInput.readUInt16(); + fileInput.seek(curPos, SeekBegin); - var zipEntry:SysZipEntry = cast e; - zipEntry.seekPos = fileInput.tell(); + var zipEntry:SysZipEntry = { + fileName: name, + fileSize: uncompSize, + seekPos: (localHeaderOffset + 30 + localNameLen + localExtraLen), + compressedSize: compSize, + compressed: (compMethod == 8), + }; entries.add(zipEntry); - fileInput.seek(e.dataSize, SeekCur); } - return entries; } public function dispose() { - if (input != null) - input.close(); + if (fileInput != null) fileInput.close(); } } typedef SysZipEntry = { - > Entry, + var fileName:String; + var fileSize:Int; var seekPos:Int; + var compressedSize:Int; + var compressed:Bool; } #end \ No newline at end of file From e0491162f2491fe1737c23d2571cc1dcec11c367 Mon Sep 17 00:00:00 2001 From: ItsLJcool <54383469+ItsLJcool@users.noreply.github.com> Date: Wed, 3 Sep 2025 21:59:24 -0700 Subject: [PATCH 02/16] comment update --- source/funkin/backend/utils/SysZip.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/backend/utils/SysZip.hx b/source/funkin/backend/utils/SysZip.hx index db4cbaa6a..6a6f0faf2 100644 --- a/source/funkin/backend/utils/SysZip.hx +++ b/source/funkin/backend/utils/SysZip.hx @@ -33,7 +33,7 @@ class SysZip extends Reader { fileInput = File.read(path, true); super(fileInput); - updateEntries(); + updateEntries(); // automatic but if you feel like you don't want it to be automatic, you can remove this. } /** From d776fed4bbf673a1ede001e6dd42abb2cae5add9 Mon Sep 17 00:00:00 2001 From: ItsLJcool <54383469+ItsLJcool@users.noreply.github.com> Date: Wed, 3 Sep 2025 22:08:49 -0700 Subject: [PATCH 03/16] quick fixes + optimizations --- source/funkin/backend/utils/CoolUtil.hx | 4 ++-- source/funkin/backend/utils/SysZip.hx | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/source/funkin/backend/utils/CoolUtil.hx b/source/funkin/backend/utils/CoolUtil.hx index 18e6c7dcd..764e4203c 100644 --- a/source/funkin/backend/utils/CoolUtil.hx +++ b/source/funkin/backend/utils/CoolUtil.hx @@ -1437,8 +1437,8 @@ final class CoolUtil } private static var lastTimeStamp:Float = -1; - public static function debugTimeStamp() { - if (lastTimeStamp != -1) { + public static function debugTimeStamp(?customText:String = "Quick Debug") { + if (lastTimeStamp < 0) { var endTimeStamp = haxe.Timer.stamp(); Logs.traceColored([ Logs.logText("[Haxe Time Stamp] ", YELLOW), diff --git a/source/funkin/backend/utils/SysZip.hx b/source/funkin/backend/utils/SysZip.hx index 6a6f0faf2..25eee0fbe 100644 --- a/source/funkin/backend/utils/SysZip.hx +++ b/source/funkin/backend/utils/SysZip.hx @@ -12,7 +12,7 @@ import haxe.io.Bytes; * Class that extends Reader allowing you to load ZIP entries without blowing your RAM up!! * ~~Half of the code is taken from haxe libraries btw~~ Reworked by ItsLJcool to actually work for zip files. */ -class SysZip extends Reader { +class SysZip { var fileInput:FileInput; var filePath:String; @@ -31,7 +31,6 @@ class SysZip extends Reader { public function new(path:String) { this.filePath = path; fileInput = File.read(path, true); - super(fileInput); updateEntries(); // automatic but if you feel like you don't want it to be automatic, you can remove this. } From 11a8b21df2170f4a24182af4629ed9c5bda9be2c Mon Sep 17 00:00:00 2001 From: ItsLJcool <54383469+ItsLJcool@users.noreply.github.com> Date: Wed, 3 Sep 2025 23:37:43 -0700 Subject: [PATCH 04/16] fixed stream audio bug???? --- source/funkin/backend/assets/ZipFolderLibrary.hx | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/source/funkin/backend/assets/ZipFolderLibrary.hx b/source/funkin/backend/assets/ZipFolderLibrary.hx index f10f80f6e..b0adc1253 100644 --- a/source/funkin/backend/assets/ZipFolderLibrary.hx +++ b/source/funkin/backend/assets/ZipFolderLibrary.hx @@ -15,7 +15,7 @@ class ZipFolderLibrary extends AssetLibrary implements IModsAssetLibrary { public var basePath:String; public var modName:String; public var libName:String; - public var useImageCache:Bool = false; + // public var useImageCache:Bool = false; public var prefix = 'assets/'; public var zip:SysZip; @@ -67,15 +67,13 @@ class ZipFolderLibrary extends AssetLibrary implements IModsAssetLibrary { return getAssetPath(); } - - public inline function unzip(f:SysZipEntry) return f == null ? null : zip.unzipEntry(f); public function __parseAsset(asset:String):Bool { if (!asset.startsWith(prefix)) return false; _parsedAsset = asset.substr(prefix.length); - if(ModsFolder.useLibFile) { + if (ModsFolder.useLibFile) { var file = new haxe.io.Path(_parsedAsset); if(file.file.startsWith("LIB_")) { var library = file.file.substr(4); @@ -103,8 +101,8 @@ class ZipFolderLibrary extends AssetLibrary implements IModsAssetLibrary { } private function getAssetPath() { - trace('[ZIP]$basePath/$_parsedAsset'); - return '[ZIP]$basePath/$_parsedAsset'; + // trace('$basePath/$_parsedAsset'); + return '$basePath/$_parsedAsset'; } // TODO: rewrite this to 1 function, like ModsFolderLibrary From 99f1156a210377de1a143cfae6de6b2a0d3ccf05 Mon Sep 17 00:00:00 2001 From: ItsLJcool <54383469+ItsLJcool@users.noreply.github.com> Date: Thu, 4 Sep 2025 00:01:26 -0700 Subject: [PATCH 05/16] found the issue ffs --- source/funkin/backend/assets/ZipFolderLibrary.hx | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/source/funkin/backend/assets/ZipFolderLibrary.hx b/source/funkin/backend/assets/ZipFolderLibrary.hx index b0adc1253..39591c49e 100644 --- a/source/funkin/backend/assets/ZipFolderLibrary.hx +++ b/source/funkin/backend/assets/ZipFolderLibrary.hx @@ -67,8 +67,10 @@ class ZipFolderLibrary extends AssetLibrary implements IModsAssetLibrary { return getAssetPath(); } - public inline function unzip(f:SysZipEntry) + public inline function unzip(f:SysZipEntry) { + trace("unzipping " + f.fileName); return f == null ? null : zip.unzipEntry(f); + } public function __parseAsset(asset:String):Bool { if (!asset.startsWith(prefix)) return false; @@ -86,6 +88,7 @@ class ZipFolderLibrary extends AssetLibrary implements IModsAssetLibrary { _parsedAsset = _parsedAsset.toLowerCase(); if(nameMap.exists(_parsedAsset)) _parsedAsset = nameMap.get(_parsedAsset); + if (_parsedAsset.endsWith(".mp4")) trace(_parsedAsset); return true; } @@ -101,8 +104,9 @@ class ZipFolderLibrary extends AssetLibrary implements IModsAssetLibrary { } private function getAssetPath() { - // trace('$basePath/$_parsedAsset'); - return '$basePath/$_parsedAsset'; + var hot_take = (Path.extension(_parsedAsset) == "mp4") ? '[ZIP]$basePath/$_parsedAsset' : '$basePath/$_parsedAsset'; // cuz of how stupid hxvlc is implemented. (and VideoCutscene ig) + trace(hot_take); + return hot_take; } // TODO: rewrite this to 1 function, like ModsFolderLibrary From 77b1c31ce17cb11cb6f34192e15e7e587a99c3d8 Mon Sep 17 00:00:00 2001 From: ItsLJcool <54383469+ItsLJcool@users.noreply.github.com> Date: Thu, 4 Sep 2025 00:02:23 -0700 Subject: [PATCH 06/16] removing traces oops --- source/funkin/backend/assets/ZipFolderLibrary.hx | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/source/funkin/backend/assets/ZipFolderLibrary.hx b/source/funkin/backend/assets/ZipFolderLibrary.hx index 39591c49e..3e2bb0c94 100644 --- a/source/funkin/backend/assets/ZipFolderLibrary.hx +++ b/source/funkin/backend/assets/ZipFolderLibrary.hx @@ -67,10 +67,8 @@ class ZipFolderLibrary extends AssetLibrary implements IModsAssetLibrary { return getAssetPath(); } - public inline function unzip(f:SysZipEntry) { - trace("unzipping " + f.fileName); + public inline function unzip(f:SysZipEntry) return f == null ? null : zip.unzipEntry(f); - } public function __parseAsset(asset:String):Bool { if (!asset.startsWith(prefix)) return false; @@ -86,9 +84,7 @@ class ZipFolderLibrary extends AssetLibrary implements IModsAssetLibrary { } _parsedAsset = _parsedAsset.toLowerCase(); - if(nameMap.exists(_parsedAsset)) - _parsedAsset = nameMap.get(_parsedAsset); - if (_parsedAsset.endsWith(".mp4")) trace(_parsedAsset); + if (nameMap.exists(_parsedAsset)) _parsedAsset = nameMap.get(_parsedAsset); return true; } @@ -105,7 +101,6 @@ class ZipFolderLibrary extends AssetLibrary implements IModsAssetLibrary { private function getAssetPath() { var hot_take = (Path.extension(_parsedAsset) == "mp4") ? '[ZIP]$basePath/$_parsedAsset' : '$basePath/$_parsedAsset'; // cuz of how stupid hxvlc is implemented. (and VideoCutscene ig) - trace(hot_take); return hot_take; } From e0156691b4acd2ae8ef95529466e965a904bd348 Mon Sep 17 00:00:00 2001 From: ItsLJcool <54383469+ItsLJcool@users.noreply.github.com> Date: Thu, 4 Sep 2025 00:32:24 -0700 Subject: [PATCH 07/16] fixed videos from not being able to play. Inspired from VideoCutscene's fix for ZIP videos, and also removed that fix in favor for just fixing the issue entirely --- source/funkin/backend/assets/ZipFolderLibrary.hx | 12 ++++++++++-- source/funkin/game/cutscenes/VideoCutscene.hx | 7 ------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/source/funkin/backend/assets/ZipFolderLibrary.hx b/source/funkin/backend/assets/ZipFolderLibrary.hx index 3e2bb0c94..89e455a26 100644 --- a/source/funkin/backend/assets/ZipFolderLibrary.hx +++ b/source/funkin/backend/assets/ZipFolderLibrary.hx @@ -1,11 +1,14 @@ package funkin.backend.assets; +import funkin.backend.system.Flags; + import haxe.io.Path; import lime.graphics.Image; import lime.media.AudioBuffer; import lime.text.Font; import lime.utils.Bytes; import openfl.utils.AssetLibrary; +import sys.io.File; #if MOD_SUPPORT import funkin.backend.utils.SysZip.SysZipEntry; @@ -100,8 +103,13 @@ class ZipFolderLibrary extends AssetLibrary implements IModsAssetLibrary { } private function getAssetPath() { - var hot_take = (Path.extension(_parsedAsset) == "mp4") ? '[ZIP]$basePath/$_parsedAsset' : '$basePath/$_parsedAsset'; // cuz of how stupid hxvlc is implemented. (and VideoCutscene ig) - return hot_take; + // Now we have supports for videos in ZIP!! + if (Path.extension(_parsedAsset) == Flags.VIDEO_EXT) { + var newPath = './.temp/zip_video-${_parsedAsset.split("/").pop()}'; + File.saveBytes(newPath, unzip(assets[_parsedAsset])); + return newPath; + } + return '$basePath/$_parsedAsset'; } // TODO: rewrite this to 1 function, like ModsFolderLibrary diff --git a/source/funkin/game/cutscenes/VideoCutscene.hx b/source/funkin/game/cutscenes/VideoCutscene.hx index f3e3e2745..d7a16c18b 100644 --- a/source/funkin/game/cutscenes/VideoCutscene.hx +++ b/source/funkin/game/cutscenes/VideoCutscene.hx @@ -101,13 +101,6 @@ class VideoCutscene extends Cutscene { FlxTween.tween(loadingBackdrop, {alpha: 1}, 0.5, {ease: FlxEase.sineInOut}); Main.execAsync(function() { - if (localPath.startsWith("[ZIP]")) { - // ZIP PATH: EXPORT - // TODO: this but better and more ram friendly - localPath = './.temp/video-${curVideo++}.mp4'; - File.saveBytes(localPath, Assets.getBytes(path)); - } - if (video.load(localPath)) new FlxTimer().start(0.001, function(_) { mutex.acquire(); onReady(); mutex.release(); }); else { mutex.acquire(); close(); mutex.release(); } }); From c9eb19b1e6298e97bb5a770c30bc0c9c14961776 Mon Sep 17 00:00:00 2001 From: ItsLJcool <54383469+ItsLJcool@users.noreply.github.com> Date: Thu, 4 Sep 2025 08:46:41 -0700 Subject: [PATCH 08/16] oop just in case no special characters that kill themself on other shit --- source/funkin/backend/assets/ZipFolderLibrary.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/backend/assets/ZipFolderLibrary.hx b/source/funkin/backend/assets/ZipFolderLibrary.hx index 89e455a26..b7b4320c3 100644 --- a/source/funkin/backend/assets/ZipFolderLibrary.hx +++ b/source/funkin/backend/assets/ZipFolderLibrary.hx @@ -105,7 +105,7 @@ class ZipFolderLibrary extends AssetLibrary implements IModsAssetLibrary { private function getAssetPath() { // Now we have supports for videos in ZIP!! if (Path.extension(_parsedAsset) == Flags.VIDEO_EXT) { - var newPath = './.temp/zip_video-${_parsedAsset.split("/").pop()}'; + var newPath = './.temp/video-${_parsedAsset.split("/").pop()}'; File.saveBytes(newPath, unzip(assets[_parsedAsset])); return newPath; } From cdbcbed8d63003e7b8d4249a3533a03ffe52eba0 Mon Sep 17 00:00:00 2001 From: ItsLJcool <54383469+ItsLJcool@users.noreply.github.com> Date: Thu, 4 Sep 2025 10:00:32 -0700 Subject: [PATCH 09/16] Implemented preloading every video (caching) when loading a ZipFolderLibrary. Since videos have to be decompressed and be saved as a file anyways this reduces the time to do that, and what not. --- .../funkin/backend/assets/ZipFolderLibrary.hx | 49 +++++++++++++------ source/funkin/backend/utils/CoolUtil.hx | 2 +- source/funkin/game/cutscenes/VideoCutscene.hx | 5 +- 3 files changed, 40 insertions(+), 16 deletions(-) diff --git a/source/funkin/backend/assets/ZipFolderLibrary.hx b/source/funkin/backend/assets/ZipFolderLibrary.hx index b7b4320c3..3d3f6cd78 100644 --- a/source/funkin/backend/assets/ZipFolderLibrary.hx +++ b/source/funkin/backend/assets/ZipFolderLibrary.hx @@ -26,7 +26,8 @@ class ZipFolderLibrary extends AssetLibrary implements IModsAssetLibrary { public var lowerCaseAssets:Map = []; public var nameMap:Map = []; - public function new(basePath:String, libName:String, ?modName:String) { + public function new(basePath:String, libName:String, ?modName:String, ?preloadVideos:Bool = true) { + CoolUtil.debugTimeStamp(); this.libName = libName; this.basePath = basePath; @@ -35,19 +36,46 @@ class ZipFolderLibrary extends AssetLibrary implements IModsAssetLibrary { zip = SysZip.openFromFile(basePath); for(entry in zip.entries) { - lowerCaseAssets[entry.fileName.toLowerCase()] = assets[entry.fileName.toLowerCase()] = assets[entry.fileName] = entry; - nameMap.set(entry.fileName.toLowerCase(), entry.fileName); + var name = entry.fileName.toLowerCase(); + lowerCaseAssets[name] = assets[name] = assets[entry.fileName] = entry; + nameMap.set(name, entry.fileName); } super(); + precacheVideos(); + CoolUtil.debugTimeStamp("ZipFolderLibrary"); + } + + public function precacheVideos() { + videoCacheRemap = []; + for (entry in zip.entries) { + var name = entry.fileName.toLowerCase(); + if (_videoExtensions.contains(Path.extension(name))) getPath(prefix+name); + } + var count = 0; + for (_ in videoCacheRemap.keys()) count++; + trace('Precached $count video${count == 1 ? "" : "s"}'); + } + + // Now we have supports for videos in ZIP!! + public var _videoExtensions:Array = [Flags.VIDEO_EXT]; + public var videoCacheRemap:Map = []; + public function getVideoRemap(originalPath:String):String { + if (!_videoExtensions.contains(Path.extension(_parsedAsset))) return originalPath; + if (videoCacheRemap.exists(originalPath)) return videoCacheRemap.get(originalPath); + + // We adding the length of the string to counteract folder in folder naming duplicates. + var newPath = './.temp/${assets[_parsedAsset].fileName.length}-zipvideo-${_parsedAsset.split("/").pop()}'; + File.saveBytes(newPath, unzip(assets[_parsedAsset])); + videoCacheRemap.set(originalPath, newPath); + return newPath; } function toString():String { - return '(ZipFolderLibrary: $libName/$modName)'; + return '(ZipFolderLibrary: $libName/$modName | ${zip.entries.length} entries | Detected Video Extensions: ${_videoExtensions.join(", ")})'; } public var _parsedAsset:String; - public override function getAudioBuffer(id:String):AudioBuffer { __parseAsset(id); return AudioBuffer.fromBytes(unzip(assets[_parsedAsset])); @@ -70,8 +98,7 @@ class ZipFolderLibrary extends AssetLibrary implements IModsAssetLibrary { return getAssetPath(); } - public inline function unzip(f:SysZipEntry) - return f == null ? null : zip.unzipEntry(f); + public inline function unzip(f:SysZipEntry) return (f == null) ? null : zip.unzipEntry(f); public function __parseAsset(asset:String):Bool { if (!asset.startsWith(prefix)) return false; @@ -103,13 +130,7 @@ class ZipFolderLibrary extends AssetLibrary implements IModsAssetLibrary { } private function getAssetPath() { - // Now we have supports for videos in ZIP!! - if (Path.extension(_parsedAsset) == Flags.VIDEO_EXT) { - var newPath = './.temp/video-${_parsedAsset.split("/").pop()}'; - File.saveBytes(newPath, unzip(assets[_parsedAsset])); - return newPath; - } - return '$basePath/$_parsedAsset'; + return getVideoRemap('$basePath/$_parsedAsset'); } // TODO: rewrite this to 1 function, like ModsFolderLibrary diff --git a/source/funkin/backend/utils/CoolUtil.hx b/source/funkin/backend/utils/CoolUtil.hx index 764e4203c..0bdcd5836 100644 --- a/source/funkin/backend/utils/CoolUtil.hx +++ b/source/funkin/backend/utils/CoolUtil.hx @@ -1438,7 +1438,7 @@ final class CoolUtil private static var lastTimeStamp:Float = -1; public static function debugTimeStamp(?customText:String = "Quick Debug") { - if (lastTimeStamp < 0) { + if (lastTimeStamp > 0) { var endTimeStamp = haxe.Timer.stamp(); Logs.traceColored([ Logs.logText("[Haxe Time Stamp] ", YELLOW), diff --git a/source/funkin/game/cutscenes/VideoCutscene.hx b/source/funkin/game/cutscenes/VideoCutscene.hx index d7a16c18b..283f8e499 100644 --- a/source/funkin/game/cutscenes/VideoCutscene.hx +++ b/source/funkin/game/cutscenes/VideoCutscene.hx @@ -101,7 +101,9 @@ class VideoCutscene extends Cutscene { FlxTween.tween(loadingBackdrop, {alpha: 1}, 0.5, {ease: FlxEase.sineInOut}); Main.execAsync(function() { - if (video.load(localPath)) new FlxTimer().start(0.001, function(_) { mutex.acquire(); onReady(); mutex.release(); }); + if (video.load(localPath)) new FlxTimer().start(0.001, function(_) { + mutex.acquire(); onReady(); mutex.release(); + }); else { mutex.acquire(); close(); mutex.release(); } }); @@ -173,6 +175,7 @@ class VideoCutscene extends Cutscene { } public inline function onReady() { + trace("VideoCutscene: Ready"); FlxTween.cancelTweensOf(loadingBackdrop); FlxTween.tween(loadingBackdrop, {alpha: 0}, 0.7, {ease: FlxEase.sineInOut, onComplete: function(_) { loadingBackdrop.destroy(); From 04e3d9b56258e059ea59494474216866f78d927f Mon Sep 17 00:00:00 2001 From: ItsLJcool <54383469+ItsLJcool@users.noreply.github.com> Date: Thu, 4 Sep 2025 10:51:40 -0700 Subject: [PATCH 10/16] [UNTESTED] Allowed Zip Extensions for allowing any extension in the list to be passed as a `.zip` --- source/funkin/backend/assets/ModsFolder.hx | 23 +++++++++------------- source/funkin/backend/system/Flags.hx | 3 +++ source/funkin/backend/system/MainState.hx | 8 ++------ 3 files changed, 14 insertions(+), 20 deletions(-) diff --git a/source/funkin/backend/assets/ModsFolder.hx b/source/funkin/backend/assets/ModsFolder.hx index b59b605cb..77190c9f6 100644 --- a/source/funkin/backend/assets/ModsFolder.hx +++ b/source/funkin/backend/assets/ModsFolder.hx @@ -83,10 +83,11 @@ class ModsFolder { */ public static function loadModLib(path:String, force:Bool = false, ?modName:String) { #if MOD_SUPPORT - if (FileSystem.exists('$path.zip')) - return loadLibraryFromZip('$path'.toLowerCase(), '$path.zip', force, modName); - else - return loadLibraryFromFolder('$path'.toLowerCase(), '$path', force, modName); + for (ext in Flags.ALLOWED_ZIP_EXTENSIONS) { + if (!FileSystem.exists('$path.$ext')) continue; + return loadLibraryFromZip('$path'.toLowerCase(), '$path.$ext', force, modName); + } + return loadLibraryFromFolder('$path'.toLowerCase(), '$path', force, modName); #else return null; @@ -103,19 +104,13 @@ class ModsFolder { final modsList:Array = FileSystem.readDirectory(modsPath); - if (modsList == null || modsList.length <= 0) - return mods; + if (modsList == null || modsList.length <= 0) return mods; for (modFolder in modsList) { - if (FileSystem.isDirectory(modsPath + modFolder)) { - mods.push(modFolder); - } else { + if (FileSystem.isDirectory(modsPath + modFolder)) mods.push(modFolder); + else { var ext = Path.extension(modFolder).toLowerCase(); - switch(ext) { - case 'zip': - // is a zip mod!! - mods.push(Path.withoutExtension(modFolder)); - } + if (Flags.ALLOWED_ZIP_EXTENSIONS.contains(ext)) mods.push(Path.withoutExtension(modFolder)); } } #end diff --git a/source/funkin/backend/system/Flags.hx b/source/funkin/backend/system/Flags.hx index f57eb7aef..fc4d688e1 100644 --- a/source/funkin/backend/system/Flags.hx +++ b/source/funkin/backend/system/Flags.hx @@ -18,6 +18,9 @@ class Flags { // -- Codename's Addon Config -- @:bypass public static var addonFlags:Map = []; + // -- Codename's ZipFolderLibrary Config -- + public static var ALLOWED_ZIP_EXTENSIONS:Array = ["zip"]; + // -- Codename's Mod Config -- public static var MOD_NAME:String = ""; public static var MOD_DESCRIPTION:String = ""; diff --git a/source/funkin/backend/system/MainState.hx b/source/funkin/backend/system/MainState.hx index 982152d5d..109293e96 100644 --- a/source/funkin/backend/system/MainState.hx +++ b/source/funkin/backend/system/MainState.hx @@ -72,12 +72,8 @@ class MainState extends FlxState { for (addon in FileSystem.readDirectory(path)) { if (!FileSystem.isDirectory(path + addon)) { - switch(Path.extension(addon).toLowerCase()) { - case 'zip': - addon = Path.withoutExtension(addon); - default: - continue; - } + if (Flags.ALLOWED_ZIP_EXTENSIONS.contains(Path.extension(addon).toLowerCase())) addon = Path.withoutExtension(addon); + else continue; } var data:AddonInfo = { From 1cb8bbdf1bfa0db8cac9e00851a574ff70cf208a Mon Sep 17 00:00:00 2001 From: ItsLJcool <54383469+ItsLJcool@users.noreply.github.com> Date: Thu, 4 Sep 2025 14:27:23 -0700 Subject: [PATCH 11/16] After some more testing loading Zip Addons works as well. --- source/funkin/backend/system/Flags.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/backend/system/Flags.hx b/source/funkin/backend/system/Flags.hx index fc4d688e1..b6e94e31d 100644 --- a/source/funkin/backend/system/Flags.hx +++ b/source/funkin/backend/system/Flags.hx @@ -19,7 +19,7 @@ class Flags { @:bypass public static var addonFlags:Map = []; // -- Codename's ZipFolderLibrary Config -- - public static var ALLOWED_ZIP_EXTENSIONS:Array = ["zip"]; + public static var ALLOWED_ZIP_EXTENSIONS:Array = ["zip"]; // So we can have .cnemod extensions :troll: // -- Codename's Mod Config -- public static var MOD_NAME:String = ""; From ab998613c51979a60d3ed4493363c40be8d50403 Mon Sep 17 00:00:00 2001 From: ItsLJcool <54383469+ItsLJcool@users.noreply.github.com> Date: Thu, 4 Sep 2025 21:14:52 -0700 Subject: [PATCH 12/16] Added the long awaited .cnemod file type!!!!! (it's just a folder with .cnemod with a .zip inside LMAO) --- source/funkin/backend/assets/ModsFolder.hx | 11 +++-------- source/funkin/backend/system/Flags.hx | 2 +- source/funkin/backend/system/MainState.hx | 14 ++++++++++---- source/funkin/menus/ModSwitchMenu.hx | 2 +- 4 files changed, 15 insertions(+), 14 deletions(-) diff --git a/source/funkin/backend/assets/ModsFolder.hx b/source/funkin/backend/assets/ModsFolder.hx index 77190c9f6..328c4836b 100644 --- a/source/funkin/backend/assets/ModsFolder.hx +++ b/source/funkin/backend/assets/ModsFolder.hx @@ -97,10 +97,8 @@ class ModsFolder { public static function getModsList():Array { var mods:Array = []; #if MOD_SUPPORT - if (!FileSystem.exists(modsPath)) { - // Mods directory does not exist yet, create it - FileSystem.createDirectory(modsPath); - } + // Mods directory does not exist yet, create it + if (!FileSystem.exists(modsPath)) FileSystem.createDirectory(modsPath); final modsList:Array = FileSystem.readDirectory(modsPath); @@ -108,10 +106,7 @@ class ModsFolder { for (modFolder in modsList) { if (FileSystem.isDirectory(modsPath + modFolder)) mods.push(modFolder); - else { - var ext = Path.extension(modFolder).toLowerCase(); - if (Flags.ALLOWED_ZIP_EXTENSIONS.contains(ext)) mods.push(Path.withoutExtension(modFolder)); - } + else if (Flags.ALLOWED_ZIP_EXTENSIONS.contains(Path.extension(modFolder))) mods.push(Path.withoutExtension(modFolder)); } #end return mods; diff --git a/source/funkin/backend/system/Flags.hx b/source/funkin/backend/system/Flags.hx index b6e94e31d..fc4d688e1 100644 --- a/source/funkin/backend/system/Flags.hx +++ b/source/funkin/backend/system/Flags.hx @@ -19,7 +19,7 @@ class Flags { @:bypass public static var addonFlags:Map = []; // -- Codename's ZipFolderLibrary Config -- - public static var ALLOWED_ZIP_EXTENSIONS:Array = ["zip"]; // So we can have .cnemod extensions :troll: + public static var ALLOWED_ZIP_EXTENSIONS:Array = ["zip"]; // -- Codename's Mod Config -- public static var MOD_NAME:String = ""; diff --git a/source/funkin/backend/system/MainState.hx b/source/funkin/backend/system/MainState.hx index 109293e96..821858ac0 100644 --- a/source/funkin/backend/system/MainState.hx +++ b/source/funkin/backend/system/MainState.hx @@ -57,11 +57,12 @@ class MainState extends FlxState { var _highPriorityAddons:Array = []; var _noPriorityAddons:Array = []; + var quick_modsPath = ModsFolder.modsPath + ModsFolder.currentModFolder; var addonPaths = [ ModsFolder.addonsPath, ( ModsFolder.currentModFolder != null ? - ModsFolder.modsPath + ModsFolder.currentModFolder + "/addons/" : + quick_modsPath + "/addons/" : null ) ]; @@ -97,8 +98,13 @@ class MainState extends FlxState { for (addon in _lowPriorityAddons) loadLib(addon.path, ltrim(addon.name, "[LOW]")); - if (ModsFolder.currentModFolder != null) - loadLib(ModsFolder.modsPath + ModsFolder.currentModFolder, ModsFolder.currentModFolder); + var isZipMod = (Path.extension(ModsFolder.currentModFolder) == "cnemod" || Flags.ALLOWED_ZIP_EXTENSIONS.contains(Path.extension(ModsFolder.currentModFolder))); + if (ModsFolder.currentModFolder != null) { + if (FileSystem.isDirectory(quick_modsPath) && Path.extension(ModsFolder.currentModFolder) == "cnemod") + loadLib(quick_modsPath + "/mod", ModsFolder.currentModFolder); + else + loadLib(quick_modsPath, ModsFolder.currentModFolder); + } for (addon in _noPriorityAddons) loadLib(addon.path, addon.name); @@ -137,7 +143,7 @@ class MainState extends FlxState { for (e in Paths.assetsTree.libraries) if ((lib = cast AssetsLibraryList.getCleanLibrary(e)) is ModsFolderLibrary && lib.modName == ModsFolder.currentModFolder) { - if (lib.exists(Paths.ini("config/modpack"), lime.utils.AssetType.TEXT)) break; + if (lib.exists(Paths.ini("config/modpack"), lime.utils.AssetType.TEXT) || isZipMod) break; // because it's a zip file, you can't edit a zip file without decompiling it FlxG.switchState(new ModConfigWarning(lib, startState)); return; diff --git a/source/funkin/menus/ModSwitchMenu.hx b/source/funkin/menus/ModSwitchMenu.hx index 977f74fc6..3414af7f0 100644 --- a/source/funkin/menus/ModSwitchMenu.hx +++ b/source/funkin/menus/ModSwitchMenu.hx @@ -34,7 +34,7 @@ class ModSwitchMenu extends MusicBeatSubstate { alphabets = new FlxTypedGroup(); for(mod in mods) { - var a = new Alphabet(0, 0, mod == null ? TU.translate("mods.disableMods") : mod, "bold"); + var a = new Alphabet(0, 0, mod == null ? TU.translate("mods.disableMods") : Path.withoutExtension(mod), "bold"); if(mod == ModsFolder.currentModFolder) a.color = FlxColor.LIME; a.isMenuItem = true; From 1eb048061c29ebd30d93f1c8a5bf4870bd022a49 Mon Sep 17 00:00:00 2001 From: ItsLJcool <54383469+ItsLJcool@users.noreply.github.com> Date: Fri, 5 Sep 2025 16:49:48 -0700 Subject: [PATCH 13/16] Chalking up the Streamed Audio Bug to a mod issue, and also added capabilites to detect if a library is considered compressed --- source/funkin/backend/assets/AssetsLibraryList.hx | 12 +++++++++--- source/funkin/backend/assets/ZipFolderLibrary.hx | 3 ++- source/funkin/backend/system/MainState.hx | 3 +-- source/funkin/backend/system/macros/Macros.hx | 1 + source/openfl/utils/Assets.hx | 5 +++-- 5 files changed, 16 insertions(+), 8 deletions(-) diff --git a/source/funkin/backend/assets/AssetsLibraryList.hx b/source/funkin/backend/assets/AssetsLibraryList.hx index ea3cffdc4..0dd532c80 100644 --- a/source/funkin/backend/assets/AssetsLibraryList.hx +++ b/source/funkin/backend/assets/AssetsLibraryList.hx @@ -7,7 +7,15 @@ import funkin.backend.assets.IModsAssetLibrary; import lime.utils.AssetLibrary; class AssetsLibraryList extends AssetLibrary { + public var libraries:Array = []; + + // is true if any library in `libraries` contains some kind of compressed library. + public var hasCompressedLibrary(get, never):Bool; + function get_hasCompressedLibrary():Bool { + for (l in libraries) if (getCleanLibrary(l).isCompressed) return true; + return false; + } @:allow(funkin.backend.system.Main) @:allow(funkin.backend.system.MainState) @@ -141,9 +149,7 @@ class AssetsLibraryList extends AssetLibrary { public override inline function getAsset(id:String, type:String):Dynamic return getSpecificAsset(id, type, BOTH); - public override function isLocal(id:String, type:String) { - return true; - } + public override function isLocal(id:String, type:String) return true; public function new(?base:AssetLibrary) { super(); diff --git a/source/funkin/backend/assets/ZipFolderLibrary.hx b/source/funkin/backend/assets/ZipFolderLibrary.hx index 3d3f6cd78..de519742f 100644 --- a/source/funkin/backend/assets/ZipFolderLibrary.hx +++ b/source/funkin/backend/assets/ZipFolderLibrary.hx @@ -20,7 +20,7 @@ class ZipFolderLibrary extends AssetLibrary implements IModsAssetLibrary { public var libName:String; // public var useImageCache:Bool = false; public var prefix = 'assets/'; - + public var zip:SysZip; public var assets:Map = []; public var lowerCaseAssets:Map = []; @@ -42,6 +42,7 @@ class ZipFolderLibrary extends AssetLibrary implements IModsAssetLibrary { } super(); + isCompressed = true; precacheVideos(); CoolUtil.debugTimeStamp("ZipFolderLibrary"); } diff --git a/source/funkin/backend/system/MainState.hx b/source/funkin/backend/system/MainState.hx index 821858ac0..71c2db716 100644 --- a/source/funkin/backend/system/MainState.hx +++ b/source/funkin/backend/system/MainState.hx @@ -98,7 +98,6 @@ class MainState extends FlxState { for (addon in _lowPriorityAddons) loadLib(addon.path, ltrim(addon.name, "[LOW]")); - var isZipMod = (Path.extension(ModsFolder.currentModFolder) == "cnemod" || Flags.ALLOWED_ZIP_EXTENSIONS.contains(Path.extension(ModsFolder.currentModFolder))); if (ModsFolder.currentModFolder != null) { if (FileSystem.isDirectory(quick_modsPath) && Path.extension(ModsFolder.currentModFolder) == "cnemod") loadLib(quick_modsPath + "/mod", ModsFolder.currentModFolder); @@ -143,7 +142,7 @@ class MainState extends FlxState { for (e in Paths.assetsTree.libraries) if ((lib = cast AssetsLibraryList.getCleanLibrary(e)) is ModsFolderLibrary && lib.modName == ModsFolder.currentModFolder) { - if (lib.exists(Paths.ini("config/modpack"), lime.utils.AssetType.TEXT) || isZipMod) break; // because it's a zip file, you can't edit a zip file without decompiling it + if (lib.exists(Paths.ini("config/modpack"), lime.utils.AssetType.TEXT) || Paths.assetsTree.hasCompressedLibrary) break; // because it's a zip file, you can't edit a zip file without decompiling it FlxG.switchState(new ModConfigWarning(lib, startState)); return; diff --git a/source/funkin/backend/system/macros/Macros.hx b/source/funkin/backend/system/macros/Macros.hx index f3bf4adb2..983fa9355 100644 --- a/source/funkin/backend/system/macros/Macros.hx +++ b/source/funkin/backend/system/macros/Macros.hx @@ -64,6 +64,7 @@ class Macros { final fields:Array = Context.getBuildFields(), pos:Position = Context.currentPos(); fields.push({name: 'tag', access: [APublic], pos: pos, kind: FVar(macro :funkin.backend.assets.AssetSource)}); + fields.push({name: 'isCompressed', access: [APublic], pos: pos, kind: FVar(macro :Bool, macro false)}); return fields; } diff --git a/source/openfl/utils/Assets.hx b/source/openfl/utils/Assets.hx index c14b9f2c9..07a6c90f5 100644 --- a/source/openfl/utils/Assets.hx +++ b/source/openfl/utils/Assets.hx @@ -249,9 +249,10 @@ class Assets } #if (lime_vorbis && lime > "7.9.0" && !macro) if (Options.streamedMusic) { - var path = getPath(id); + var bytes = getBytes(id); + if (bytes == null) return null; // TODO: What if it is a WAV or non-Vorbis file? - var vorbisFile = VorbisFile.fromFile(path); + var vorbisFile = VorbisFile.fromBytes(bytes); if (vorbisFile != null) return Sound.fromAudioBuffer(AudioBuffer.fromVorbisFile(vorbisFile)); } #end From ba1976f09301e19b5e06617fdab2cad6311ebbf8 Mon Sep 17 00:00:00 2001 From: ItsLJcool <54383469+ItsLJcool@users.noreply.github.com> Date: Fri, 5 Sep 2025 18:09:03 -0700 Subject: [PATCH 14/16] Added warning to those who try to use the editor with compressed libraries --- source/funkin/editors/EditorTreeMenu.hx | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/source/funkin/editors/EditorTreeMenu.hx b/source/funkin/editors/EditorTreeMenu.hx index 1a7a0e372..e9bb7ab37 100644 --- a/source/funkin/editors/EditorTreeMenu.hx +++ b/source/funkin/editors/EditorTreeMenu.hx @@ -20,6 +20,8 @@ class EditorTreeMenu extends funkin.options.TreeMenu { bg.antialiasing = true; setBackgroundRotation(-5); super.createPost(); + + if (Paths.assetsTree.hasCompressedLibrary) warnCompressLibrary(); } public inline function setBackgroundRotation(rotation:Float) { @@ -58,6 +60,21 @@ class EditorTreeMenu extends funkin.options.TreeMenu { bg.colorTransform.greenMultiplier = FlxMath.lerp(1, color.greenFloat, 0.25); bg.colorTransform.blueMultiplier = FlxMath.lerp(1, color.blueFloat, 0.25); } + + private function warnCompressLibrary() { + var warningMessage = "It seems you have libraries loaded that are compressed, and can not have files written to them.\n + This is just a friendly reminder that if you're loading a Mod and wish to edit files, you need to uncompress it to be able to use any editors!\n\nCompressed Libraries: "; + var compressedList = Paths.assetsTree.libraries.filter(l -> funkin.backend.assets.AssetsLibraryList.getCleanLibrary(l).isCompressed); + var modNameList = [for (l in compressedList) { + l = funkin.backend.assets.AssetsLibraryList.getCleanLibrary(l); + if (l is funkin.backend.assets.IModsAssetLibrary) cast(l, funkin.backend.assets.IModsAssetLibrary).modName; + }]; + warningMessage += modNameList.join(", "); + var zipLibraryWarning = new funkin.editors.ui.UIWarningSubstate("Compressed Library Detected!", warningMessage, [{label: "Ok", color: 0x969533, onClick: (state) -> {} }], false); + + openSubState(zipLibraryWarning); + } + } class EditorTreeMenuScreen extends funkin.options.TreeMenuScreen { From ed7fb9b70533da5e4ea90f466420f750ed9ce027 Mon Sep 17 00:00:00 2001 From: ItsLJcool <54383469+ItsLJcool@users.noreply.github.com> Date: Tue, 9 Sep 2025 00:52:01 -0700 Subject: [PATCH 15/16] ok instead of making it a .cnemod, the zip name will be `cnemod.zip` or what not. --- source/funkin/backend/system/Main.hx | 1 + source/funkin/backend/system/MainState.hx | 34 +++++++++++++++++------ 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/source/funkin/backend/system/Main.hx b/source/funkin/backend/system/Main.hx index da44cf1d4..cf7bf7a59 100644 --- a/source/funkin/backend/system/Main.hx +++ b/source/funkin/backend/system/Main.hx @@ -167,6 +167,7 @@ class Main extends Sprite if (FileSystem.exists("mods/autoload.txt")) modToLoad = File.getContent("mods/autoload.txt").trim(); + trace('modToLoad: ${modToLoad}'); ModsFolder.switchMod(modToLoad.getDefault(Options.lastLoadedMod)); #end diff --git a/source/funkin/backend/system/MainState.hx b/source/funkin/backend/system/MainState.hx index 71c2db716..d133d0101 100644 --- a/source/funkin/backend/system/MainState.hx +++ b/source/funkin/backend/system/MainState.hx @@ -58,12 +58,28 @@ class MainState extends FlxState { var _noPriorityAddons:Array = []; var quick_modsPath = ModsFolder.modsPath + ModsFolder.currentModFolder; + + var isCneMod = false; + for (ext in Flags.ALLOWED_ZIP_EXTENSIONS) { + if (!FileSystem.exists(quick_modsPath+"/cnemod."+ext)) continue; + isCneMod = true; + break; + } + + // handing if the loading mod, before it's properly loaded, is a compressed mod + // we just need to use `Paths.assetsTree.hasCompressedLibrary` to complete valid checks for actual loaded compressed mods + var isZipMod = false; + for (ext in Flags.ALLOWED_ZIP_EXTENSIONS) { + if (!FileSystem.exists(quick_modsPath+"."+ext)) continue; + isZipMod = true; + break; + } + + // Now here is a conundrum, if it's a compressed mod you can't really uncompress it yet, since it's not loaded as a library, so we need to skip it. var addonPaths = [ ModsFolder.addonsPath, - ( - ModsFolder.currentModFolder != null ? - quick_modsPath + "/addons/" : - null + ( (ModsFolder.currentModFolder != null && !isZipMod) ? + quick_modsPath + "/addons/" : null ) ]; @@ -97,10 +113,10 @@ class MainState extends FlxState { #if MOD_SUPPORT for (addon in _lowPriorityAddons) loadLib(addon.path, ltrim(addon.name, "[LOW]")); - + if (ModsFolder.currentModFolder != null) { - if (FileSystem.isDirectory(quick_modsPath) && Path.extension(ModsFolder.currentModFolder) == "cnemod") - loadLib(quick_modsPath + "/mod", ModsFolder.currentModFolder); + if (isCneMod) + loadLib(quick_modsPath + "/cnemod", ModsFolder.currentModFolder); else loadLib(quick_modsPath, ModsFolder.currentModFolder); } @@ -137,12 +153,12 @@ class MainState extends FlxState { var startState:Class = Flags.DISABLE_WARNING_SCREEN ? TitleState : funkin.menus.WarningState; - if (Options.devMode && Options.allowConfigWarning) { + if (Options.devMode && Options.allowConfigWarning && !Paths.assetsTree.hasCompressedLibrary) { // because it's a zip file, you can't edit a zip file without decompiling it var lib:ModsFolderLibrary; for (e in Paths.assetsTree.libraries) if ((lib = cast AssetsLibraryList.getCleanLibrary(e)) is ModsFolderLibrary && lib.modName == ModsFolder.currentModFolder) { - if (lib.exists(Paths.ini("config/modpack"), lime.utils.AssetType.TEXT) || Paths.assetsTree.hasCompressedLibrary) break; // because it's a zip file, you can't edit a zip file without decompiling it + if (lib.exists(Paths.ini("config/modpack"), lime.utils.AssetType.TEXT)) break; FlxG.switchState(new ModConfigWarning(lib, startState)); return; From d1c93779993d777444e4a8e900e29a3f2024e02c Mon Sep 17 00:00:00 2001 From: ItsLJcool <54383469+ItsLJcool@users.noreply.github.com> Date: Wed, 10 Sep 2025 17:35:37 -0700 Subject: [PATCH 16/16] removing unnessesary traces oops --- source/funkin/backend/system/Main.hx | 1 - 1 file changed, 1 deletion(-) diff --git a/source/funkin/backend/system/Main.hx b/source/funkin/backend/system/Main.hx index cf7bf7a59..da44cf1d4 100644 --- a/source/funkin/backend/system/Main.hx +++ b/source/funkin/backend/system/Main.hx @@ -167,7 +167,6 @@ class Main extends Sprite if (FileSystem.exists("mods/autoload.txt")) modToLoad = File.getContent("mods/autoload.txt").trim(); - trace('modToLoad: ${modToLoad}'); ModsFolder.switchMod(modToLoad.getDefault(Options.lastLoadedMod)); #end