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