package kha.netsync; import haxe.macro.Context; import haxe.macro.Expr.Field; class ControllerBuilder { public static var nextId: Int = 0; macro static public function build(): Array { var fields = Context.getBuildFields(); #if (!kha_server && (kha_html5 || kha_kore)) { var funcindex = 0; for (field in fields) { var input = false; for (meta in field.meta) { if (meta.name == "input") { input = true; break; } } if (!input) continue; switch (field.kind) { case FFun(f): var size = 4; for (arg in f.args) { switch (arg.type) { case TPath(p): switch (p.name) { case "Int": size += 4; case "String": size += 1; case "Float": size += 8; case "Bool": size += 1; case "KeyCode": size += 1; } default: } } var expr = macro @:mergeBlock { var bytes = haxe.io.Bytes.alloc($v{size}); bytes.setInt32(0, $v{funcindex}); }; var index: Int = 4; for (arg in f.args) { switch (arg.type) { case TPath(p): switch (p.name) { case "Int": var argname = arg.name; expr = macro @:mergeBlock { $expr; bytes.setInt32($v{index}, $i{argname}); }; index += 4; case "String": var argname = arg.name; expr = macro @:mergeBlock { $expr; bytes.set($v{index}, $i{argname}.charCodeAt(0)); }; index += 1; case "Float": var argname = arg.name; expr = macro @:mergeBlock { $expr; bytes.setDouble($v{index}, $i{argname}); }; index += 8; case "Bool": var argname = arg.name; expr = macro @:mergeBlock { $expr; bytes.set($v{index}, $i{argname} ?1:0); }; index += 1; case "KeyCode": var argname = arg.name; expr = macro @:mergeBlock { $expr; bytes.set($v{index}, $i{argname}); }; index += 1; } default: } } var original = f.expr; expr = macro { if (kha.netsync.Session.the() != null) { $expr; kha.netsync.Session.the().sendControllerUpdate(_id(), bytes); } $original; }; f.expr = expr; default: } ++funcindex; } } #end // macros failing everywhere but in JavaScript? #if (kha_server || kha_html5 || kha_kore) var receive = macro @:mergeBlock { var funcindex = bytes.getInt32(0); }; { var funcindex = 0; for (field in fields) { var input = false; for (meta in field.meta) { if (meta.name == "input") { input = true; break; } } if (!input) continue; switch (field.kind) { case FFun(f): var expr = macro {}; var index: Int = 4; var varindex: Int = 0; for (arg in f.args) { switch (arg.type) { case TPath(p): switch (p.name) { case "Int": var argname = arg.name; var varname = "input" + varindex; expr = macro @:mergeBlock { $expr; var $varname:Int = bytes.getInt32($v{index}); }; index += 4; case "String": var argname = arg.name; var varname = "input" + varindex; expr = macro @:mergeBlock { $expr; var $varname:String = String.fromCharCode(bytes.get($v{index})); }; index += 1; case "Float": var argname = arg.name; var varname = "input" + varindex; expr = macro @:mergeBlock { $expr; var $varname:Float = bytes.getDouble($v{index}); }; index += 8; case "Bool": var argname = arg.name; var varname = "input" + varindex; expr = macro @:mergeBlock { $expr; var $varname:Bool = bytes.get($v{index}) != 0; }; index += 1; case "KeyCode": var argname = arg.name; var varname = "input" + varindex; expr = macro @:mergeBlock { $expr; var $varname:kha.input.KeyCode = cast bytes.get($v{index}); }; index += 1; } default: } ++varindex; } switch (varindex) { case 1: var funcname = field.name; receive = macro @:mergeBlock { $receive; if (funcindex == $v{funcindex}) { $expr; $i{funcname}(input0); return; } }; case 2: var funcname = field.name; receive = macro @:mergeBlock { $receive; if (funcindex == $v{funcindex}) { $expr; $i{funcname}(input0, input1); return; } }; case 3: var funcname = field.name; receive = macro @:mergeBlock { $receive; if (funcindex == $v{funcindex}) { $expr; $i{funcname}(input0, input1, input2); return; } }; case 4: var funcname = field.name; receive = macro @:mergeBlock { $receive; if (funcindex == $v{funcindex}) { $expr; $i{funcname}(input0, input1, input2, input3); return; } }; case 5: var funcname = field.name; receive = macro @:mergeBlock { $receive; if (funcindex == $v{funcindex}) { $expr; $i{funcname}(input0, input1, input2, input3, input4); return; } }; } default: } ++funcindex; } } fields.push({ name: "_receive", doc: null, meta: [], access: [APublic, AOverride], kind: FFun({ ret: null, params: null, expr: receive, args: [ { value: null, type: Context.toComplexType(Context.getType("haxe.io.Bytes")), opt: null, name: "bytes" } ] }), pos: Context.currentPos() }); #else fields.push({ name: "_receive", doc: null, meta: [], access: [APublic, AOverride], kind: FFun({ ret: null, params: null, expr: macro {}, args: [ { value: null, type: Context.toComplexType(Context.getType("haxe.io.Bytes")), opt: null, name: "bytes" } ] }), pos: Context.currentPos() }); #end return fields; } }