1 /*
2  * Copyright (c) 2017 SEL
3  * 
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  * 
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12  * See the GNU Lesser General Public License for more details.
13  * 
14  */
15 module sel.hncom.handler;
16 
17 import std.string : capitalize;
18 import std.traits : hasUDA;
19 import std.typetuple : TypeTuple;
20 
21 import sel.hncom.about;
22 
23 static import sel.hncom.util;
24 static import sel.hncom.status;
25 static import sel.hncom.player;
26 
27 interface HncomHandler(alias type) if(is(type == clientbound )|| is(type == serverbound)) {
28 	
29 	mixin((){
30 		string ret;
31 		foreach(section ; TypeTuple!("util", "status", "player")) {
32 			foreach(member ; __traits(allMembers, mixin("sel.hncom." ~ section))) {
33 				static if(member != "Packets" && hasUDA!(__traits(getMember, mixin("sel.hncom." ~ section), member), type)) {
34 					ret ~= "protected void handle" ~ capitalize(section) ~ member ~ "(sel.hncom." ~ section ~ "." ~ member ~ " packet);";
35 				}
36 			}
37 		}
38 		return ret;
39 	}());
40 
41 	public final void handleHncom(ubyte[] buffer) {
42 		assert(buffer.length);
43 		switch(buffer[0]) {
44 			foreach(section ; TypeTuple!("util", "status", "player")) {
45 				foreach(member ; __traits(allMembers, mixin("sel.hncom." ~ section))) {
46 					static if(hasUDA!(__traits(getMember, mixin("sel.hncom." ~ section), member), type)) {
47 						mixin("alias T = sel.hncom." ~ section ~ "." ~ member ~ ";");
48 						case T.ID: return mixin("this.handle" ~ capitalize(section) ~ member)(T.fromBuffer(buffer[1..$]));
49 					}
50 				}
51 			}
52 			default: break;
53 		}
54 	}
55 
56 	protected final void handlePlayerPackets(sel.hncom.player.Packets packets) {
57 		foreach(packet ; packets.packets) {
58 			this.handlePlayerPacketsImpl(packets.hubId, packet.id, packet.payload);
59 		}
60 	}
61 
62 	private final void handlePlayerPacketsImpl(uint hubId, ubyte id, ubyte[] payload) {
63 		switch(id) {
64 			foreach(member ; __traits(allMembers, sel.hncom.player)) {
65 				static if(member != "Packets" && hasUDA!(__traits(getMember, sel.hncom.player, member), type)) {
66 					mixin("alias T = sel.hncom.player." ~ member ~ ";");
67 					case T.ID: return mixin("this.handlePlayer" ~ member)(T.fromBuffer(hubId, payload));
68 				}
69 			}
70 			default: return;
71 		}
72 	}
73 
74 }
75 
76 unittest {
77 
78 	abstract class TestClientbound : HncomHandler!clientbound {}
79 
80 	abstract class TestServerbound : HncomHandler!serverbound {}
81 
82 }