1 /*
2  * Copyright (c) 2017-2018 sel-project
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to deal
6  * in the Software without restriction, including without limitation the rights
7  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  * copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in all
12  * copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20  * SOFTWARE.
21  *
22  */
23 /**
24  * Copyright: Copyright (c) 2017-2018 sel-project
25  * License: MIT
26  * Authors: Kripth
27  * Source: $(HTTP github.com/sel-project/sel-hncom/sel/hncom/handler.d, sel/hncom/handler.d)
28  */
29 module sel.hncom.handler;
30 
31 import std.string : capitalize;
32 import std.traits : hasUDA;
33 import std.typetuple : TypeTuple;
34 
35 import sel.hncom.about;
36 
37 static import sel.hncom.util;
38 static import sel.hncom.status;
39 static import sel.hncom.player;
40 
41 interface HncomHandler(alias type) if(is(type == clientbound )|| is(type == serverbound)) {
42 	
43 	mixin((){
44 		string ret;
45 		foreach(section ; TypeTuple!("util", "status", "player")) {
46 			foreach(member ; __traits(allMembers, mixin("sel.hncom." ~ section))) {
47 				static if(member != "Packets" && hasUDA!(__traits(getMember, mixin("sel.hncom." ~ section), member), type)) {
48 					ret ~= "protected void handle" ~ capitalize(section) ~ member ~ "(sel.hncom." ~ section ~ "." ~ member ~ " packet);";
49 				}
50 			}
51 		}
52 		return ret;
53 	}());
54 
55 	public final void handleHncom(ubyte[] buffer) {
56 		assert(buffer.length);
57 		switch(buffer[0]) {
58 			foreach(section ; TypeTuple!("util", "status", "player")) {
59 				foreach(member ; __traits(allMembers, mixin("sel.hncom." ~ section))) {
60 					static if(hasUDA!(__traits(getMember, mixin("sel.hncom." ~ section), member), type)) {
61 						mixin("alias T = sel.hncom." ~ section ~ "." ~ member ~ ";");
62 						case T.ID: return mixin("this.handle" ~ capitalize(section) ~ member)(T.fromBuffer(buffer[1..$]));
63 					}
64 				}
65 			}
66 			default: break;
67 		}
68 	}
69 
70 	protected final void handlePlayerPackets(sel.hncom.player.Packets packets) {
71 		foreach(packet ; packets.packets) {
72 			this.handlePlayerPacketsImpl(packets.hubId, packet.id, packet.payload);
73 		}
74 	}
75 
76 	private final void handlePlayerPacketsImpl(uint hubId, ubyte id, ubyte[] payload) {
77 		switch(id) {
78 			foreach(member ; __traits(allMembers, sel.hncom.player)) {
79 				static if(member != "Packets" && hasUDA!(__traits(getMember, sel.hncom.player, member), type)) {
80 					mixin("alias T = sel.hncom.player." ~ member ~ ";");
81 					case T.ID: return mixin("this.handlePlayer" ~ member)(T.fromBuffer(hubId, payload));
82 				}
83 			}
84 			default: return;
85 		}
86 	}
87 
88 }
89 
90 unittest {
91 
92 	abstract class TestClientbound : HncomHandler!clientbound {}
93 
94 	abstract class TestServerbound : HncomHandler!serverbound {}
95 
96 }