global scripts

This commit is contained in:
Yoshman29
2022-11-03 15:59:30 +01:00
parent 686f6c7911
commit 3f857e3f5b
7 changed files with 222 additions and 15 deletions
+3
View File
@@ -160,4 +160,7 @@
<!-- Comment this out to disable mods folder !-->
<haxedef name="MOD_SUPPORT" unless="web"/>
<!-- Comment this out to disable global scripts !-->
<haxedef name="GLOBAL_SCRIPT" />
</project>
+1 -1
View File
@@ -1 +1 @@
1016
1032
+24 -5
View File
@@ -1,9 +1,11 @@
package funkin.mods;
import flixel.util.FlxSignal.FlxTypedSignal;
import openfl.utils.Assets;
import openfl.utils.AssetManifest;
import openfl.utils.AssetLibrary;
import flixel.graphics.FlxGraphic;
import flixel.util.FlxSignal.FlxTypedSignal;
#if MOD_SUPPORT
import sys.FileSystem;
@@ -16,13 +18,11 @@ import haxe.io.Path;
using StringTools;
class ModsFolder {
#if MOD_SUPPORT
/**
* Last time the folder was modified.
* INTERNAL - Only use when editing source mods!!
*/
public static var lastFolderEditTime:Date = null;
#end
@:dox(hide) public static var onModSwitch:FlxTypedSignal<String->Void> = new FlxTypedSignal<String->Void>();
/**
* Current mod folder. Will affect `Paths`.
*/
@@ -49,6 +49,8 @@ class ModsFolder {
* @param force Whenever the mod should be reloaded if it has already been loaded
*/
public static function loadMod(mod:String, force:Bool = false) {
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);
@@ -60,6 +62,23 @@ class ModsFolder {
}
}
/**
* Switches mod - unloads all the other mods, then load this one.
* @param libName
*/
public static function switchMod(mod:String) {
for(m in loadedMods)
unloadMod(m);
loadMod(ModsFolder.currentModFolder = mod);
onModSwitch.dispatch(ModsFolder.currentModFolder);
FlxG.resetState();
}
public static function unloadMod(mod:String) {
Assets.unloadLibrary('mods/$mod');
}
public static function prepareLibrary(libName:String, force:Bool = false) {
if (Assets.hasLibrary(libName)) {
if (force)
+100
View File
@@ -0,0 +1,100 @@
package funkin.scripting;
import flixel.FlxG;
import flixel.FlxState;
import funkin.mods.ModsFolder;
#if GLOBAL_SCRIPT
/**
* Class for THE Global Script, aka script that runs in the background at all times.
*/
class GlobalScript {
public static var script:Script;
public static function init() {
#if MOD_SUPPORT
ModsFolder.onModSwitch.add(onModSwitch);
#end
FlxG.signals.focusGained.add(function() {
call("focusGained");
});
FlxG.signals.focusLost.add(function() {
call("focusLost");
});
FlxG.signals.gameResized.add(function(w:Int, h:Int) {
call("gameResized", [w, h]);
});
FlxG.signals.postDraw.add(function() {
call("postDraw");
});
FlxG.signals.postGameReset.add(function() {
call("postGameReset");
});
FlxG.signals.postGameStart.add(function() {
});
FlxG.signals.postStateSwitch.add(function() {
call("postStateSwitch");
});
FlxG.signals.postUpdate.add(function() {
call("postUpdate", [FlxG.elapsed]);
call("updatePost", [FlxG.elapsed]);
if (FlxG.keys.justPressed.F5) {
if (script != null && !(script is DummyScript)) {
Logs.trace('Reloading global script...', WARNING, YELLOW);
script.reload();
Logs.trace('Global script successfully reloaded.', WARNING, GREEN);
} else {
Logs.trace('Loading global script...', WARNING, YELLOW);
onModSwitch(#if MOD_SUPPORT ModsFolder.currentModFolder #else null #end);
if (script is DummyScript)
Logs.trace('Global script not found. Are you sure "data/global.hx" exists?', ERROR, RED);
else
Logs.trace('Global script successfully loaded.', WARNING, GREEN);
}
}
});
FlxG.signals.preDraw.add(function() {
call("preDraw");
});
FlxG.signals.preGameReset.add(function() {
call("preGameReset");
});
FlxG.signals.preGameStart.add(function() {
call("preGameStart");
});
FlxG.signals.preStateCreate.add(function(state:FlxState) {
call("preStateCreate", [state]);
});
FlxG.signals.preStateSwitch.add(function() {
call("preStateSwitch", []);
});
FlxG.signals.preUpdate.add(function() {
call("preUpdate", [FlxG.elapsed]);
call("update", [FlxG.elapsed]);
});
onModSwitch(#if MOD_SUPPORT ModsFolder.currentModFolder #else null #end);
}
public static function call(name:String, ?args:Array<Dynamic>) {
if (script == null) return;
script.call(name, args);
}
public static function onModSwitch(newMod:String) {
trace(newMod);
if (script != null) {
script.destroy();
script = null;
}
script = Script.create(Paths.script('data/global'));
script.load();
}
public static function beatHit(curBeat:Int) {
call("beatHit", [curBeat]);
}
public static function stepHit(curStep:Int) {
call("stepHit", [curStep]);
}
}
#end
-4
View File
@@ -9,10 +9,6 @@ import funkin.windows.WindowsAPI.ConsoleColor;
class Logs {
private static var __showing:Bool = false;
public static function init() {
__showInConsole([
logText("Hello, World! ", CYAN),
logText("I am..."),
logText("COLORED!!", RED)]);
Log.trace = function(v : Dynamic, ?infos : Null<haxe.PosInfos>) {
__showInConsole(prepareColoredTrace([
+7 -5
View File
@@ -106,13 +106,15 @@ class Main extends Sprite
public function loadGameSettings() {
Logs.init();
// TODO: Mod switching
ModsFolder.init();
ModsFolder.loadMod("introMod");
ModsFolder.currentModFolder = "introMod";
Logs.init();
ModsFolder.switchMod("introMod");
#if GLOBAL_SCRIPT
funkin.scripting.GlobalScript.init();
#end
#if sys
if (Sys.args().contains("-livereload")) {
+87
View File
@@ -0,0 +1,87 @@
package scripting;
import flixel.FlxState;
/**
* A global script is a special kind of script that runs on everywhere on your mod: menus, game, etc...
*
* To create one, go to data and create a script named "global", then press F5 in game.
*
* All flixel signals are automatically binded, as shown below.
*/
interface GlobalScript {
/**
* Called whenever the game gains focus.
*/
public function focusGained():Void;
/**
* Called whenever the game loses focus.
*/
public function focusLost():Void;
/**
* Called whenever the game loses focus.
* @param width Width of the game
* @param height Height of the game
*/
public function gameResized(width:Int, height:Int):Void;
/**
* Called after the screen has been drawn.
*/
public function postDraw():Void;
/**
* Called after the game has been reset.
*/
public function postGameReset():Void;
/**
* Called after the game has been started.
*/
public function postGameStart():Void;
/**
* Called after the state has been switched.
*/
public function postStateSwitch():Void;
/**
* Called after the game has been updated.
*
* Aliases: `postUpdate`
*
* @param elapsed Time elapsed since last frame
*/
public function updatePost(elapsed:Float):Void;
/**
* Called before the game draws on screen.
*/
public function preDraw():Void;
/**
* Called before the game resets.
*/
public function preGameReset():Void;
/**
* Called before the game starts.
*/
public function preGameStart():Void;
/**
* Called before the state creates.
*/
public function preStateCreate(state:FlxState):Void;
/**
* Called before the state switches.
*/
public function preStateSwitch():Void;
/**
* Called before the game updates.
*
* Aliases: `preUpdate`
*/
public function update(elapsed:Float):Void;
}