diff --git a/hGameTest/project.xml b/hGameTest/project.xml index e52a3878..19b2ff25 100644 --- a/hGameTest/project.xml +++ b/hGameTest/project.xml @@ -17,7 +17,7 @@ - + diff --git a/hGameTest/src/engine/ConVar.hx b/hGameTest/src/engine/ConVar.hx index c5987b62..8eaaa370 100644 --- a/hGameTest/src/engine/ConVar.hx +++ b/hGameTest/src/engine/ConVar.hx @@ -67,6 +67,10 @@ class ConVar{ } public static inline function setCVar(_name:String, _value:Dynamic):Void { + if(CVarMap == null){ + Console.devMsg("CVarMap is null"); + return; + } var cv = getCVar(_name); if(cv != null){ switch(cv.type){ diff --git a/hGameTest/src/engine/ConVars_Engine.hx b/hGameTest/src/engine/ConVars_Engine.hx index 8b86f665..8ff62f79 100644 --- a/hGameTest/src/engine/ConVars_Engine.hx +++ b/hGameTest/src/engine/ConVars_Engine.hx @@ -6,14 +6,14 @@ import engine.typedefs.console.CVar; import engine.typedefs.console.CCmd; import engine.enums.console.CVarType; import engine.enums.console.CVarFlag; -import engine.macros.CCmdDecorator; +import engine.macros.ConVarDecorators; import game.ui.console.Console; @:keep // @:build(engine.macros.CCmdDecorator.build()) // No longer needed because we added the build macro to the project.xml class ConVars_Engine { - @:ConCmd("list") + @:concmd("list") public static function listCommands(args:Array) { var CVarMap:Map = ConVar.getCVarMap(); var keys:Array = ConVar.getCVarNames(); @@ -27,7 +27,7 @@ class ConVars_Engine { } } - @:ConCmd("test") + @:concmd("test") public static function testCommand() { // Command implementation trace("Test Output"); diff --git a/hGameTest/src/engine/enums/console/CVarFlag.hx b/hGameTest/src/engine/enums/console/CVarFlag.hx index 56ee8e16..11426847 100644 --- a/hGameTest/src/engine/enums/console/CVarFlag.hx +++ b/hGameTest/src/engine/enums/console/CVarFlag.hx @@ -1,6 +1,7 @@ package engine.enums.console; enum CVarFlag{ + FCVAR_NONE; FCVAR_ARCHIVE; FCVAR_CHEAT; FVCAR_REPLICATED; diff --git a/hGameTest/src/engine/macros/CCmdDecorator.hx b/hGameTest/src/engine/macros/CCmdDecorator.hx deleted file mode 100644 index 129f9878..00000000 --- a/hGameTest/src/engine/macros/CCmdDecorator.hx +++ /dev/null @@ -1,46 +0,0 @@ -package engine.macros; - -import haxe.macro.Expr; -import haxe.macro.Context; - -class CCmdDecorator { - public static macro function build():Array { - var fields = Context.getBuildFields(); - var pos = Context.currentPos(); - - for (field in fields) { - var meta = field.meta != null ? Lambda.find(field.meta, function(m) return m.name == ":ConCMD") : null; - if (meta != null) { - trace(meta); - switch field.kind { - case FFun(f): - var name = meta.params.length > 0 - ? switch(meta.params[0].expr) { - case EConst(CString(s)): s; - case _: field.name; - } - : field.name; - - // Create a static initializer field - var initField = { - name: "__init__" + name, - access: [AStatic, APrivate], - kind: FVar(null, macro { - engine.ConVar.registerCCmd($v{name}, function(args:Array) { - ${f.expr}; - }); - }), - pos: pos, - doc: null, - meta: [] - }; - - // Add the initializer field - fields.push(initField); - case _: - } - } - } - return fields; - } -} \ No newline at end of file diff --git a/hGameTest/src/engine/macros/ConVarDecorators.hx b/hGameTest/src/engine/macros/ConVarDecorators.hx new file mode 100644 index 00000000..131a5160 --- /dev/null +++ b/hGameTest/src/engine/macros/ConVarDecorators.hx @@ -0,0 +1,136 @@ +package engine.macros; + +import haxe.macro.Expr; +import haxe.macro.Context; +import haxe.macro.Expr.Field; + +private typedef CVarMetadata = { + name: Expr, + type: String, + value: Expr, + flags: Expr, + help: Expr, + ?callback: Expr +} + +class ConVarDecorators { + static function extractCVarMetadata(params:Array):CVarMetadata { + var metadata:CVarMetadata = null; + + switch (params[0].expr) { + case EObjectDecl(fields): + metadata = { + name: macro "", + type: "CString", + value: macro 0, + flags: macro "FCVAR_NONE", + help: macro "", + callback: macro null + }; + + for (field in fields) { + switch (field.field) { + case "name": metadata.name = field.expr; + case "type": metadata.type = switch(field.expr.expr) { + case EConst(CString(s)): s; + case _: "CString"; + } + case "value": metadata.value = field.expr; + case "flags": metadata.flags = field.expr; + case "help": metadata.help = field.expr; + case "callback": metadata.callback = field.expr; + case _: + } + } + case _: + } + return metadata; + } + + public static macro function build():Array { + var fields = Context.getBuildFields(); + var pos = Context.currentPos(); + + for (field in fields) { + var cmdMeta = field.meta != null ? Lambda.find(field.meta, function(m) return m.name == ":concmd") : null; + var cvarMeta = field.meta != null ? Lambda.find(field.meta, function(m) return m.name == ":convar") : null; + + if (cmdMeta != null) { + switch field.kind { + case FFun(f): + var name = cmdMeta.params.length > 0 ? switch (cmdMeta.params[0].expr) { + case EConst(CString(s)): s; + case _: field.name; + } : field.name; + + var fnExpr = macro function(args:Array) ${f.expr}; + + var initExpr = macro { + var cmd = engine.ConVar.registerCCmd($v{name}, $fnExpr); + cmd; // Return the command reference + }; + + // Generate a safe initialization field name + var initName = "__init__" + name; + + fields.push({ + name: initName, + access: [AStatic], + kind: FVar(null, initExpr), + pos: pos, + doc: null, + meta: [{ + name: ":keep", + params: [], + pos: pos + }] + }); + case _: + } + } else if (cvarMeta != null && cvarMeta.params.length > 0) { + switch (field.kind) { + case FVar(t, e): + var meta = extractCVarMetadata(cvarMeta.params); + if (meta == null) continue; + + // Extract name from metadata expression + var cvarName = switch(meta.name.expr) { + case EConst(CString(s)): s; + case _: field.name; + }; + + var initExpr = macro { + var cvar = $i{field.name} = engine.ConVar.registerCVar( + ${meta.name}, + ${Context.parse('engine.enums.console.CVarType.' + meta.type, pos)}, + ${meta.value}, + ${Context.parse('engine.enums.console.CVarFlag.' + switch(meta.flags.expr) { + case EConst(CString(s)): s; + case _: "FCVAR_NONE"; + }, pos)}, + ${meta.help}, + ${meta.callback ?? macro null} + ); + trace($v{"Registered CVar: "} + $e{meta.name}); + cvar; // Return the CVar reference + }; + + fields.push({ + name: "__init__" + cvarName, + access: [AStatic], + kind: FVar(null, initExpr), + pos: pos, + doc: null, + meta: [{ + name: ":keep", + params: [], + pos: pos + }] + }); + case _: + } + } + } + return fields; + } +} diff --git a/hGameTest/src/game/Input.hx b/hGameTest/src/game/Input.hx index 1e1cdf6c..079431ca 100644 --- a/hGameTest/src/game/Input.hx +++ b/hGameTest/src/game/Input.hx @@ -18,7 +18,19 @@ class Input{ public static var keys:Map = []; public static var keysLast:Map = []; public static var bindMap:Map = ["~" => "toggleconsole", "\\" => "toggleconsole", "1" => "echo kak", "2" => "+attack"]; - public static var cv_debugKeys = ConVar.registerCVar("cl_debuginput", CInt, 0, null, "print debug messages related to input to console", null, false, true, 0, 0, false); + @:convar({ + name: "cl_debuginput", + type: CVarType.CInt, + value: 0, + flags: CVarFlag.None, + help: "print debug messages related to input to console", + callback: function() { + trace("Debug input changed"); + } + }) + public static var cv_debugKeys:CVar; + + // public static var cv_debugKeys = ConVar.registerCVar("cl_debuginput", CInt, 0, null, "print debug messages related to input to console", null, false, true, 0, 0, false); public static var keyNameMap:Map = [ Kb.HOME => "HOME", Kb.END => "END", Kb.INSERT => "INSERT", Kb.DELETE => "DELETE", Kb.PAGE_UP => "PGUP", Kb.PAGE_DOWN => "PGDN", Kb.ESCAPE => "ESC", Kb.F1 => "F1", Kb.F2 => "F2", Kb.F3 => "F3", Kb.F4 => "F4", Kb.F5 => "F5", diff --git a/hGameTest/src/game/video/Mode.hx b/hGameTest/src/game/video/Mode.hx index 54afc3ed..42a64551 100644 --- a/hGameTest/src/game/video/Mode.hx +++ b/hGameTest/src/game/video/Mode.hx @@ -15,7 +15,7 @@ class Mode public static function setVideoMode(width:Int, height:Int, fs:Int = null){ getWindow().resize(width,height); } - @:ConCmd("mat_setvideomode") + @:concmd("mat_setvideomode") public static function cCmdMatSetVideoMode(args:Array){ Mode.setVideoMode(Std.parseInt(args[0]), Std.parseInt(args[1]), Std.parseInt(args[2])); }