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 }