diff --git a/Project.xml b/Project.xml index f014c797..3e9cce07 100644 --- a/Project.xml +++ b/Project.xml @@ -128,6 +128,9 @@ + + + @@ -139,6 +142,9 @@ + + + diff --git a/source/funkin/game/Character.hx b/source/funkin/game/Character.hx index be8435a4..f67e7bab 100644 --- a/source/funkin/game/Character.hx +++ b/source/funkin/game/Character.hx @@ -27,6 +27,7 @@ using StringTools; @:allow(funkin.desktop.editors.CharacterEditor) @:allow(funkin.game.StrumLine) @:allow(funkin.game.PlayState) +@:build(funkin.macros.SoftcodedClassMacro.build()) class Character extends FunkinSprite implements IBeatReceiver implements IOffsetCompatible { private var __stunnedTime:Float = 0; diff --git a/source/funkin/macros/ScriptsMacro.hx b/source/funkin/macros/ScriptsMacro.hx index 8bed21d1..16dbaf85 100644 --- a/source/funkin/macros/ScriptsMacro.hx +++ b/source/funkin/macros/ScriptsMacro.hx @@ -17,23 +17,5 @@ class ScriptsMacro { // FOR ABSTRACTS Compiler.addGlobalMetadata('haxe.xml', '@:build(hscript.UsingHandler.build())'); } - - public static function build():Array { - var fields:Array = Context.getBuildFields(); - - for(f in fields) { - switch(f.kind) { - case FFun(func): - if (f.access == null) f.access = []; - if (f.access.contains(AInline)) - f.access.remove(AInline); - f.access.push(ADynamic); - default: - // do nothing u piece of shit - } - } - - return fields; - } } #end \ No newline at end of file diff --git a/source/funkin/macros/SoftcodedClassMacro.hx b/source/funkin/macros/SoftcodedClassMacro.hx new file mode 100644 index 00000000..5c8fba21 --- /dev/null +++ b/source/funkin/macros/SoftcodedClassMacro.hx @@ -0,0 +1,118 @@ +package funkin.macros; + +class SoftcodedClassMacro { + #if macro + public static function init() { + trace("cock and balls"); + // Compiler.addGlobalMetadata('funkin.game', '@:build(funkin.macros.SoftcodedClassMacro.build())'); + } + + public static function build():Array { + var fields = Context.getBuildFields(); + var cl = Context.getLocalClass(); + + var funcs:Array = []; + if (cl != null) { + var c = cl.get(); + if (c.isAbstract) return fields; + + for(m in c.meta.get()) { + switch(m.name) { + case ":final", ":noSoftcodedExtend": + return fields; + default: + // cool + } + } + + for(f in fields) { + var valid = true; + if (f.access != null) for(e in f.access) { + switch (e) { + case AStatic | ADynamic | AInline | AMacro | AFinal | AExtern | AAbstract: + valid = false; + break; + default: + // nothing + } + } + + if (!valid) continue; + + switch(f.kind) { + case FFun(fun): + var funcExpr = macro { + ${{ + pos: Context.currentPos(), + expr: ECall({ + pos: Context.currentPos(), + expr: EField({ + pos: Context.currentPos(), + expr: EConst(CIdent("super")) + }, f.name) + }, fun.args != null ? [for(a in fun.args) { + pos: Context.currentPos(), + expr: EConst(CIdent(a.name)) + }] : []) + }}; + }; + + var accessors = []; + if (f.access != null) for(f in f.access) accessors.push(f); + accessors.remove(AOverride); + + if (f.name != "new") { + var func:Function = { + expr: funcExpr, + args: fun.args + }; + funcs.push({ + pos: Context.currentPos(), + name: '__super__${f.name}', + kind: FFun(func), + access: accessors + }); + } + + accessors.push(AOverride); + + var overrideFuncExpr = macro { + var fieldName = ${{ + pos: Context.currentPos(), + expr: EConst(CString(f.name, DoubleQuotes)) + }}; + if (__scriptClass != null && __scriptClass.hasField(fieldName) && Reflect.isFunction(__scriptClass.get(fieldName))) { + __scriptClass.call(fieldName, ${{ + pos: Context.currentPos(), + expr: EArrayDecl([for(a in fun.args) { + pos: Context.currentPos(), + expr: EConst(CIdent(a.name)) + }]) + }}); + } else ${funcExpr} + }; + + var overrideFunc:Function = { + expr: overrideFuncExpr, + args: fun.args + }; + funcs.push({ + pos: Context.currentPos(), + name: '${f.name}', + kind: FFun(overrideFunc), + access: accessors + }); + + + + var printer = new Printer(); + trace(printer.printField(funcs[funcs.length - 1])); + default: + + } + } + } + return fields; + } + #end +} \ No newline at end of file diff --git a/source/funkin/scripting/HScript.hx b/source/funkin/scripting/HScript.hx index 96dfa607..c30dc966 100644 --- a/source/funkin/scripting/HScript.hx +++ b/source/funkin/scripting/HScript.hx @@ -1,5 +1,8 @@ package funkin.scripting; +import funkin.scripting.Script.ScriptClass; +import hscript.Expr.ClassDecl; +import hscript.Expr.ModuleDecl; import hscript.Expr.Error; import hscript.Parser; import openfl.Assets; @@ -9,16 +12,23 @@ class HScript extends Script { public var interp:Interp; public var parser:Parser; public var expr:Expr; + public var decls:Array = null; + public var code:String; + + public static function initParser() { + var parser = new Parser(); + parser.allowJSON = parser.allowMetadata = parser.allowTypes = true; + parser.preprocesorValues = Script.getDefaultPreprocessors(); + return parser; + } public override function onCreate(path:String) { super.onCreate(path); interp = new Interp(); - var code:String = Assets.getText(path); - parser = new Parser(); - parser.allowJSON = parser.allowMetadata = parser.allowTypes = true; - parser.preprocesorValues = Script.getDefaultPreprocessors(); + code = Assets.getText(path); + parser = initParser(); interp.errorHandler = _errorHandler; interp.staticVariables = Script.staticVariables; interp.allowStaticVariables = interp.allowPublicVariables = true; @@ -117,6 +127,27 @@ class HScript extends Script { this.interp.publicVariables = map; } + public override function getClass(name:String) { + if (decls == null) { + decls = parser.parseModule(code, fileName); + } + for(d in decls) { + switch(d) { + case DPackage(path): + // ignore + case DImport(path, everything): + // ignore + case DClass(c): + if (c.name == name) { + + } + case DTypedef(c): + // ignore + } + } + return null; + } + public override function onDestroy() { @:privateAccess { // INTERP @@ -182,4 +213,40 @@ class HScript extends Script { interp = null; } } +} + +class HScriptClass extends ScriptClass { + var decl:ClassDecl; + var name:String; + + var interp:Interp; + + public function new(decl:ClassDecl, sInterp:Interp) { + super(); + this.name = decl.name; + + + + interp = new Interp(); + interp.errorHandler = sInterp.errorHandler; + interp.staticVariables = sInterp.staticVariables; + interp.allowStaticVariables = interp.allowPublicVariables = false; + // interp.execute({ e : EBlock(decl.fields), pmin : 0, pmax : 0, origin : fileName, line : 0 }); + + var parser = HScript.initParser(); + + for(f in decl.fields) { + switch(f.kind) { + case KVar(v): + interp.variables[f.name] = interp.execute(v.expr); + case KFunction(fun): + @:privateAccess + interp.variables[f.name] = interp.execute(parser.mk(EFunction(fun.args, fun.expr, f.name, fun.ret, false, false))); + } + } + } + + public override function get(field:String) { + return interp.variables[field]; + } } \ No newline at end of file diff --git a/source/funkin/scripting/Script.hx b/source/funkin/scripting/Script.hx index 5ced36be..22698725 100644 --- a/source/funkin/scripting/Script.hx +++ b/source/funkin/scripting/Script.hx @@ -266,8 +266,22 @@ class Script extends FlxBasic implements IFlxDestroyable { public function onDestroy() {}; + public function getClass(name:String):ScriptClass { + return null; + } + public override function destroy() { super.destroy(); onDestroy(); } } + +class ScriptClass { + public function new() {} + + public function get(field:String):Dynamic {return null;} + + public function set(field:String, v:Dynamic) {} + + public function call(field:String, ?args:Array) {return null;} +} \ No newline at end of file