replace single scripts with scriptpacks (#185)

* replace single scripts with scriptpack

* this might break a ton of mods i think

* oops

* stuff

---------

Co-authored-by: Frakist <90983918+Frakist@users.noreply.github.com>
This commit is contained in:
Frakits
2023-07-18 04:25:37 -07:00
committed by GitHub
co-authored by Frakist
parent 8054d5c5ba
commit 2114be6fc6
6 changed files with 139 additions and 152 deletions
+47 -39
View File
@@ -9,6 +9,7 @@ import flixel.FlxState;
import flixel.FlxSubState;
import funkin.backend.scripting.events.*;
import funkin.backend.scripting.Script;
import funkin.backend.scripting.ScriptPack;
import funkin.backend.system.interfaces.IBeatReceiver;
import funkin.backend.system.Conductor;
import funkin.options.PlayerSettings;
@@ -89,7 +90,7 @@ class MusicBeatState extends FlxState implements IBeatReceiver
/**
* Current injected script attached to the state. To add one, create a file at path "data/states/stateName" (ex: data/states/FreeplayState)
*/
public var stateScript:Script;
public var scripts:ScriptPack;
public var scriptsAllowed:Bool = true;
@@ -111,26 +112,44 @@ class MusicBeatState extends FlxState implements IBeatReceiver
this.scriptName = scriptName;
}
public function addScript(file:String)
scripts.add(Script.create(Paths.script(file, null, true)));
function loadScript() {
if (scriptsAllowed) {
if (stateScript == null || stateScript is DummyScript) {
if (scripts == null) {
var className = Type.getClassName(Type.getClass(this));
var scriptName = this.scriptName != null ? this.scriptName : className.substr(className.lastIndexOf(".")+1);
stateScript = Script.create(Paths.script('data/states/${scriptName}'));
stateScript.setParent(this);
stateScript.load();
} else
stateScript.reload();
var scriptPaths = [];
(scripts = new ScriptPack(scriptName)).setParent(this);
scriptPaths = Paths.getScriptPaths('assets/data/states/$scriptName');
for (i in Paths.getScriptPaths('assets/data/states', '/$scriptName.'))
scriptPaths.push(i);
if (scriptPaths.length > 0) for (i in scriptPaths) addScript(i);
if (Type.getClass(this) != PlayState) scripts.load();
}
else
scripts.reload();
}
}
public function call(name:String, ?args:Array<Dynamic>, ?defaultVal:Dynamic):Dynamic {
// calls the function on the assigned script
if (scripts == null) return defaultVal;
return scripts.call(name, args);
}
public function event<T:CancellableEvent>(name:String, event:T):T {
if (scripts == null) return event;
scripts.event(name, event);
return event;
}
public override function tryUpdate(elapsed:Float):Void
{
if (persistentUpdate || subState == null) {
call("preUpdate", [elapsed]);
scripts.call("preUpdate", [elapsed]);
update(elapsed);
call("postUpdate", [elapsed]);
scripts.call("postUpdate", [elapsed]);
}
if (_requestSubStateReset)
@@ -145,42 +164,31 @@ class MusicBeatState extends FlxState implements IBeatReceiver
}
override function create()
{
loadScript();
if (Type.getClass(this) != PlayState) loadScript();
Framerate.offset.y = 0;
super.create();
call("create");
scripts.call("create");
}
public override function createPost() {
super.createPost();
persistentUpdate = true;
call("postCreate");
scripts.call("postCreate");
if (!skipTransIn)
openSubState(new MusicBeatTransition(null));
skipTransIn = false;
skipTransOut = false;
}
public function call(name:String, ?args:Array<Dynamic>, ?defaultVal:Dynamic):Dynamic {
// calls the function on the assigned script
if (stateScript == null) return defaultVal;
return stateScript.call(name, args);
}
public function event<T:CancellableEvent>(name:String, event:T):T {
if (stateScript == null) return event;
stateScript.call(name, [event]);
return event;
}
override function update(elapsed:Float)
{
// TODO: DEBUG MODE!!
if (FlxG.keys.justPressed.F5) {
loadScript();
if (stateScript != null && !(stateScript is DummyScript))
if (scripts != null)
Logs.trace('State script successfully reloaded', WARNING, GREEN);
}
call("update", [elapsed]);
scripts.call("update", [elapsed]);
super.update(elapsed);
}
@@ -188,19 +196,19 @@ class MusicBeatState extends FlxState implements IBeatReceiver
@:dox(hide) public function stepHit(curStep:Int):Void
{
for(e in members) if (e != null && e is IBeatReceiver) cast(e, IBeatReceiver).stepHit(curStep);
call("stepHit", [curStep]);
scripts.call("stepHit", [curStep]);
}
@:dox(hide) public function beatHit(curBeat:Int):Void
{
for(e in members) if (e != null && e is IBeatReceiver) cast(e, IBeatReceiver).beatHit(curBeat);
call("beatHit", [curBeat]);
scripts.call("beatHit", [curBeat]);
}
@:dox(hide) public function measureHit(curMeasure:Int):Void
{
for(e in members) if (e != null && e is IBeatReceiver) cast(e, IBeatReceiver).measureHit(curMeasure);
call("measureHit", [curMeasure]);
scripts.call("measureHit", [curMeasure]);
}
/**
@@ -221,34 +229,34 @@ class MusicBeatState extends FlxState implements IBeatReceiver
* SCRIPTING STUFF
*/
public override function openSubState(subState:FlxSubState) {
var e = event("onOpenSubState", EventManager.get(StateEvent).recycle(subState));
var e = scripts.event("onOpenSubState", EventManager.get(StateEvent).recycle(subState));
if (!e.cancelled)
super.openSubState(subState);
}
public override function onResize(w:Int, h:Int) {
super.onResize(w, h);
event("onResize", EventManager.get(ResizeEvent).recycle(w, h, null, null));
scripts.event("onResize", EventManager.get(ResizeEvent).recycle(w, h, null, null));
}
public override function destroy() {
super.destroy();
graphicCache.destroy();
call("onDestroy");
if (stateScript != null)
stateScript.destroy();
scripts.call("onDestroy");
scripts.call("destroy");
scripts = FlxDestroyUtil.destroy(scripts);
}
public override function draw() {
graphicCache.draw();
var e = event("draw", EventManager.get(DrawEvent).recycle());
var e = scripts.event("draw", EventManager.get(DrawEvent).recycle());
if (!e.cancelled)
super.draw();
event("postDraw", e);
scripts.event("postDraw", e);
}
public override function switchTo(nextState:FlxState) {
var e = event("onStateSwitch", EventManager.get(StateEvent).recycle(nextState));
var e = scripts.event("onStateSwitch", EventManager.get(StateEvent).recycle(nextState));
if (e.cancelled)
return false;
@@ -263,12 +271,12 @@ class MusicBeatState extends FlxState implements IBeatReceiver
public override function onFocus() {
super.onFocus();
call("onFocus");
scripts.call("onFocus");
}
public override function onFocusLost() {
super.onFocusLost();
call("onFocusLost");
scripts.call("onFocusLost");
}
public override function resetSubState() {
+44 -39
View File
@@ -3,6 +3,7 @@ package funkin.backend;
import flixel.FlxState;
import funkin.backend.scripting.events.*;
import funkin.backend.scripting.Script;
import funkin.backend.scripting.ScriptPack;
import funkin.backend.scripting.DummyScript;
import funkin.backend.system.interfaces.IBeatReceiver;
import funkin.backend.system.Conductor.BPMChangeEvent;
@@ -63,7 +64,7 @@ class MusicBeatSubstate extends FlxSubState implements IBeatReceiver
/**
* Current injected script attached to the state. To add one, create a file at path "data/states/stateName" (ex: "data/states/PauseMenuSubstate.hx")
*/
public var stateScript:Script;
public var scripts:ScriptPack;
public var scriptsAllowed:Bool = true;
@@ -97,27 +98,43 @@ class MusicBeatSubstate extends FlxSubState implements IBeatReceiver
this.scriptsAllowed = #if SOFTCODED_STATES scriptsAllowed #else false #end;
this.scriptName = scriptName;
}
public function addScript(file:String)
scripts.add(Script.create(Paths.script(file, null, true)));
function loadScript() {
if (scriptsAllowed) {
if (stateScript == null || stateScript is DummyScript) {
if (scripts == null) {
(scripts = new ScriptPack(scriptName)).setParent(this);
var className = Type.getClassName(Type.getClass(this));
var scriptName = this.scriptName != null ? this.scriptName : className.substr(className.lastIndexOf(".")+1);
stateScript = Script.create(Paths.script('data/states/${scriptName}'));
stateScript.setParent(this);
stateScript.load();
} else
stateScript.reload();
var scriptPaths = [];
scriptPaths = Paths.getScriptPaths('assets/data/states/$scriptName');
for (i in Paths.getScriptPaths('assets/data/states', '/$scriptName.'))
scriptPaths.push(i);
if (scriptPaths.length > 0) for (i in scriptPaths) addScript(i);
scripts.load();
}
else
scripts.reload();
}
}
public function call(name:String, ?args:Array<Dynamic>, ?defaultVal:Dynamic):Dynamic {
// calls the function on the assigned script
if (scripts == null) return defaultVal;
return scripts.call(name, args);
}
public function event<T:CancellableEvent>(name:String, event:T):T {
if (scripts == null) return event;
scripts.call(name, [event]);
return event;
}
public override function tryUpdate(elapsed:Float):Void
{
if (persistentUpdate || subState == null) {
call("preUpdate", [elapsed]);
scripts.call("preUpdate", [elapsed]);
update(elapsed);
call("postUpdate", [elapsed]);
scripts.call("postUpdate", [elapsed]);
}
if (_requestSubStateReset)
@@ -132,10 +149,10 @@ class MusicBeatSubstate extends FlxSubState implements IBeatReceiver
}
override function close() {
var event = event("onClose", new CancellableEvent());
var event = scripts.event("onClose", new CancellableEvent());
if (!event.cancelled) {
super.close();
call("onClosePost");
scripts.call("onClosePost");
}
}
@@ -143,23 +160,12 @@ class MusicBeatSubstate extends FlxSubState implements IBeatReceiver
{
loadScript();
super.create();
call("create");
scripts.call("create");
}
public override function createPost() {
super.createPost();
call("postCreate");
}
public function call(name:String, ?args:Array<Dynamic>, ?defaultVal:Dynamic):Dynamic {
// calls the function on the assigned script
if (stateScript == null) return defaultVal;
return stateScript.call(name, args);
}
public function event<T:CancellableEvent>(name:String, event:T):T {
if (stateScript == null) return event;
stateScript.call(name, [event]);
return event;
scripts.call("postCreate");
}
override function update(elapsed:Float)
@@ -167,29 +173,28 @@ class MusicBeatSubstate extends FlxSubState implements IBeatReceiver
// TODO: DEBUG MODE!!
if (FlxG.keys.justPressed.F5) {
loadScript();
if (stateScript != null && !(stateScript is DummyScript))
Logs.trace('State script successfully reloaded', WARNING, GREEN);
Logs.trace('State script successfully reloaded', WARNING, GREEN);
}
call("update", [elapsed]);
scripts.call("update", [elapsed]);
super.update(elapsed);
}
@:dox(hide) public function stepHit(curStep:Int):Void
{
for(e in members) if (e is IBeatReceiver) cast(e, IBeatReceiver).stepHit(curStep);
call("stepHit", [curStep]);
scripts.call("stepHit", [curStep]);
}
@:dox(hide) public function beatHit(curBeat:Int):Void
{
for(e in members) if (e is IBeatReceiver) cast(e, IBeatReceiver).beatHit(curBeat);
call("beatHit", [curBeat]);
scripts.call("beatHit", [curBeat]);
}
@:dox(hide) public function measureHit(curMeasure:Int):Void
{
for(e in members) if (e is IBeatReceiver) cast(e, IBeatReceiver).measureHit(curMeasure);
call("measureHit", [curMeasure]);
scripts.call("measureHit", [curMeasure]);
}
/**
@@ -210,25 +215,25 @@ class MusicBeatSubstate extends FlxSubState implements IBeatReceiver
* SCRIPTING STUFF
*/
public override function openSubState(subState:FlxSubState) {
var e = event("onOpenSubState", EventManager.get(StateEvent).recycle(subState));
var e = scripts.event("onOpenSubState", EventManager.get(StateEvent).recycle(subState));
if (!e.cancelled)
super.openSubState(subState);
}
public override function onResize(w:Int, h:Int) {
super.onResize(w, h);
event("onResize", EventManager.get(ResizeEvent).recycle(w, h, null, null));
scripts.event("onResize", EventManager.get(ResizeEvent).recycle(w, h, null, null));
}
public override function destroy() {
super.destroy();
call("onDestroy");
if(stateScript != null)
stateScript.destroy();
scripts.call("onDestroy");
scripts.call("destroy");
scripts = FlxDestroyUtil.destroy(scripts);
}
public override function switchTo(nextState:FlxState) {
var e = event("onStateSwitch", EventManager.get(StateEvent).recycle(nextState));
var e = scripts.event("onStateSwitch", EventManager.get(StateEvent).recycle(nextState));
if (e.cancelled)
return false;
return super.switchTo(nextState);
@@ -236,12 +241,12 @@ class MusicBeatSubstate extends FlxSubState implements IBeatReceiver
public override function onFocus() {
super.onFocus();
call("onFocus");
scripts.call("onFocus");
}
public override function onFocusLost() {
super.onFocusLost();
call("onFocusLost");
scripts.call("onFocusLost");
}
public var parent:FlxState;
+17 -2
View File
@@ -97,10 +97,25 @@ class Paths
}
return getPath('images/$key.png', library);
}
static public function getScriptPaths(key:String, excep:String = ""):Array<String> {
var scriptsPaths:Array<String> = [];
var reallib = assetsTree.libraries.copy();
reallib.pop();
if (!key.endsWith("/")) key += "/";
for (e in reallib) {
if (!OpenFlAssets.exists(e.getPath(key).startsWith(".") ? "." + e.getPath(key) : e.getPath(key))) continue;
for (i in sys.FileSystem.readDirectory(e.getPath(key)))
if (Script.scriptExtensions.contains(Path.extension(i))) {
var path = '${e.getPath(key)}$i';
if (path.startsWith(".")) path = "." + path;
if (path.contains(excep) || excep == "") scriptsPaths.push(path.replace("//", "/"));
}
}
return scriptsPaths;
}
inline static public function script(key:String, ?library:String, isAssetsPath:Bool = false) {
var scriptPath = isAssetsPath ? key : getPath(key, library);
if (!OpenFlAssets.exists(scriptPath)) {
if (!Script.scriptExtensions.contains(Path.extension(scriptPath))) {
var p:String;
for(ex in Script.scriptExtensions) {
p = '$scriptPath.$ex';
+27 -41
View File
@@ -9,7 +9,7 @@ import funkin.backend.assets.ModsFolder;
* Class for THE Global Script, aka script that runs in the background at all times.
*/
class GlobalScript {
public static var script:Script;
public static var scripts:ScriptPack;
public static function init() {
#if MOD_SUPPORT
@@ -20,92 +20,78 @@ class GlobalScript {
Conductor.onStepHit.add(stepHit);
FlxG.signals.focusGained.add(function() {
call("focusGained");
scripts.call("focusGained");
});
FlxG.signals.focusLost.add(function() {
call("focusLost");
scripts.call("focusLost");
});
FlxG.signals.gameResized.add(function(w:Int, h:Int) {
call("gameResized", [w, h]);
scripts.call("gameResized", [w, h]);
});
FlxG.signals.postDraw.add(function() {
call("postDraw");
scripts.call("postDraw");
});
FlxG.signals.postGameReset.add(function() {
call("postGameReset");
scripts.call("postGameReset");
});
FlxG.signals.postGameStart.add(function() {
call("postGameStart");
scripts.call("postGameStart");
});
FlxG.signals.postStateSwitch.add(function() {
call("postStateSwitch");
scripts.call("postStateSwitch");
});
FlxG.signals.postUpdate.add(function() {
call("postUpdate", [FlxG.elapsed]);
scripts.call("postUpdate", [FlxG.elapsed]);
if (FlxG.keys.justPressed.F5) {
if (script != null && !(script is DummyScript)) {
if (scripts != null) {
Logs.trace('Reloading global script...', WARNING, YELLOW);
script.reload();
scripts.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");
scripts.call("preDraw");
});
FlxG.signals.preGameReset.add(function() {
call("preGameReset");
scripts.call("preGameReset");
});
FlxG.signals.preGameStart.add(function() {
call("preGameStart");
scripts.call("preGameStart");
});
FlxG.signals.preStateCreate.add(function(state:FlxState) {
call("preStateCreate", [state]);
scripts.call("preStateCreate", [state]);
});
FlxG.signals.preStateSwitch.add(function() {
call("preStateSwitch", []);
scripts.call("preStateSwitch", []);
});
FlxG.signals.preUpdate.add(function() {
call("preUpdate", [FlxG.elapsed]);
call("update", [FlxG.elapsed]);
scripts.call("preUpdate", [FlxG.elapsed]);
scripts.call("update", [FlxG.elapsed]);
});
onModSwitch(#if MOD_SUPPORT ModsFolder.currentModFolder #else null #end);
}
public static function event<T:CancellableEvent>(name:String, event:T):T {
if (script == null) return event;
script.call(name, [event]);
return event;
}
public static function call(name:String, ?args:Array<Dynamic>) {
if (script == null) return;
script.call(name, args);
}
public static function onModSwitch(newMod:String) {
call("onDestroy");
if (script != null) {
script.destroy();
script = null;
}
script = Script.create(Paths.script('data/global'));
script.load();
if (scripts != null) scripts.call("onDestroy");
scripts = FlxDestroyUtil.destroy(scripts);
scripts = new ScriptPack("global");
var scriptPaths = Paths.getScriptPaths("assets/data", "/global.");
for (i in Paths.getScriptPaths("assets/data/global")) scriptPaths.push(i);
for (i in scriptPaths) scripts.add(Script.create(Paths.script(i, null, true)));
scripts.load();
}
public static function beatHit(curBeat:Int) {
call("beatHit", [curBeat]);
scripts.call("beatHit", [curBeat]);
}
public static function stepHit(curStep:Int) {
call("stepHit", [curStep]);
scripts.call("stepHit", [curStep]);
}
}
#end
+1 -1
View File
@@ -96,7 +96,7 @@ class DiscordUtil {
data.largeImageText = DiscordUtil.data.logoText;
#if GLOBAL_SCRIPT
var event = funkin.backend.scripting.GlobalScript.event("onDiscordPresenceUpdate", EventManager.get(DiscordPresenceUpdateEvent).recycle(data));
var event = funkin.backend.scripting.GlobalScript.scripts.event("onDiscordPresenceUpdate", EventManager.get(DiscordPresenceUpdateEvent).recycle(data));
if (event.cancelled) return;
#end
+3 -30
View File
@@ -80,11 +80,6 @@ class PlayState extends MusicBeatState
*/
public static var coopMode:Bool = false;
/**
* Script Pack of all the scripts being ran.
*/
public var scripts:ScriptPack;
/**
* Array of all the players in the stage.
*/
@@ -511,7 +506,7 @@ class PlayState extends MusicBeatState
if (FlxG.sound.music != null) FlxG.sound.music.stop();
PauseSubState.script = "";
(scripts = new ScriptPack("PlayState")).setParent(this);
loadScript();
camGame = camera;
FlxG.cameras.add(camHUD = new HudCamera(), false);
@@ -561,21 +556,20 @@ class PlayState extends MusicBeatState
// case "":
// ADD YOUR HARDCODED SCRIPTS HERE!
default:
for(content in [Paths.getFolderContent('songs/${SONG.meta.name.toLowerCase()}/scripts', true, fromMods ? MODS : BOTH), Paths.getFolderContent('data/charts/', true, fromMods ? MODS : BOTH)])
for(content in [Paths.getScriptPaths('assets/songs/${SONG.meta.name.toLowerCase()}/scripts'), Paths.getScriptPaths('assets/data/charts/')])
for(file in content) addScript(file);
var songEvents:Array<String> = [];
for (event in SONG.events)
if (!songEvents.contains(event.name)) songEvents.push(event.name);
for (file in Paths.getFolderContent('data/events/', true, fromMods ? MODS : BOTH)) {
for (file in Paths.getScriptPaths('assets/data/events/')) {
var fileName:String = Path.withoutExtension(Path.withoutDirectory(file));
if (EventsData.eventsList.contains(fileName) && songEvents.contains(fileName)) addScript(file);
}
}
}
add(comboGroup);
#end
@@ -647,7 +641,6 @@ class PlayState extends MusicBeatState
add(splashHandler);
scripts.load();
scripts.call("create");
#end
// CAMERA & HUD INITIALISATION
@@ -724,7 +717,6 @@ class PlayState extends MusicBeatState
#end
startingSong = true;
super.create();
for(s in introSprites)
@@ -743,8 +735,6 @@ class PlayState extends MusicBeatState
updateDiscordPresence();
__updateNote_event = EventManager.get(NoteUpdateEvent);
scripts.call("postCreate");
}
/**
@@ -897,11 +887,9 @@ class PlayState extends MusicBeatState
}
public override function destroy() {
scripts.call("destroy");
for(g in __cachedGraphics)
g.useCount--;
super.destroy();
scripts = FlxDestroyUtil.destroy(scripts);
@:privateAccess {
FlxG.sound.destroySound(inst);
FlxG.sound.destroySound(vocals);
@@ -1075,11 +1063,9 @@ class PlayState extends MusicBeatState
@:dox(hide)
override public function update(elapsed:Float)
{
scripts.call("update", [elapsed]);
if (inCutscene) {
super.update(elapsed);
scripts.call("postUpdate", [elapsed]);
return;
}
@@ -1197,13 +1183,6 @@ class PlayState extends MusicBeatState
scripts.call("postUpdate", [elapsed]);
}
override function draw() {
var e = scripts.event("draw", EventManager.get(DrawEvent).recycle());
if (!e.cancelled)
super.draw();
scripts.event("postDraw", e);
}
public function executeEvent(event:ChartEvent) {
if (event == null) return;
if (event.params == null) return;
@@ -1627,12 +1606,6 @@ class PlayState extends MusicBeatState
scripts.call("beatHit", [curBeat]);
}
public function addScript(file:String) {
var ext = Path.extension(file).toLowerCase();
if (Script.scriptExtensions.contains(ext))
scripts.add(Script.create(file));
}
// GETTERS & SETTERS
#if REGION
private inline function get_player():StrumLine