288 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
			
		
		
	
	
			288 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
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<Field> {
 | 
						|
		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;
 | 
						|
	}
 | 
						|
}
 |