1 /**
2 Copyright: Copyright (c) 2014 Andrey Penechko.
3 License: a$(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0).
4 Authors: Andrey Penechko.
5 */
6 
7 module baseserver;
8 
9 import std.stdio;
10 import std.range;
11 
12 import derelict.enet.enet;
13 
14 import connection;
15 import clientstorage;
16 
17 abstract class BaseServer(Client) : Connection
18 {
19 	ClientStorage!Client clientStorage;
20 	
21 	void start(ConnectionSettings settings, uint host, ushort port)
22 	{
23 		ENetAddress address;
24 		address.host = host;
25 		address.port = port;
26 		settings.address = &address;
27 
28 		super.start(settings);
29 	}
30 
31 	/// Disconnects all clients.
32 	void disconnectAll()
33 	{
34 		foreach(user; clientStorage.clients.byValue)
35 		{
36 			enet_peer_disconnect(user.peer, 0);
37 		}
38 	}
39 
40 	/// Sends packet to specified clients.
41 	void sendTo(R)(R clients, ubyte[] data, ubyte channel = 0)
42 		if ((isInputRange!R && is(ElementType!R : ClientId)) ||
43 			is(R : ClientId))
44 	{
45 		ENetPacket* packet = enet_packet_create(data.ptr, data.length,
46 				ENET_PACKET_FLAG_RELIABLE);
47 		sendTo(clients, packet, channel);
48 	}
49 
50 	/// ditto
51 	void sendTo(R, P)(R clients, auto ref const(P) packet, ubyte channel = 0)
52 		if ((isInputRange!R && is(ElementType!R : ClientId)) ||
53 			is(R : ClientId) &&
54 			is(P == struct))
55 	{
56 		sendTo(clients, createPacket(packet), channel);
57 	}
58 
59 	/// ditto
60 	void sendTo(R)(R clients, ENetPacket* packet, ubyte channel = 0)
61 		if ((isInputRange!R && is(ElementType!R : ClientId)) ||
62 			is(R : ClientId))
63 	{
64 		static if (isInputRange!R)
65 		{
66 			foreach(clientId; clients)
67 			{
68 				if (auto client = clientStorage[clientId])
69 					enet_peer_send(client.peer, channel, packet);
70 			}
71 		}
72 		else
73 		{
74 			if (auto client = clientStorage[clients])
75 					enet_peer_send(client.peer, channel, packet);
76 		}
77 	}
78 
79 	/// Sends packet to all clients.
80 	void sendToAll(P)(auto ref P packet, ubyte channel = 0)
81 		if (is(P == struct))
82 	{
83 		sendToAll(createPacket(packet), channel);
84 	}
85 
86 	/// ditto
87 	void sendToAll(ubyte[] data, ubyte channel = 0)
88 	{
89 		ENetPacket* packet = enet_packet_create(data.ptr, data.length,
90 					ENET_PACKET_FLAG_RELIABLE);
91 		sendToAll(packet, channel);
92 	}
93 
94 	/// ditto
95 	void sendToAll(ENetPacket* packet, ubyte channel = 0)
96 	{
97 		enet_host_broadcast(host, channel, packet);
98 	}
99 
100 	/// Sends packet to all clients except one.
101 	void sendToAllExcept(P)(ClientId exceptClient, auto ref const(P) packet, ubyte channel = 0)
102 		if (is(P == struct))
103 	{
104 		sendToAllExcept(exceptClient, createPacket(packet), channel);
105 	}
106 
107 	/// ditto
108 	void sendToAllExcept(ClientId exceptClient, ubyte[] data, ubyte channel = 0)
109 	{
110 		ENetPacket* packet = enet_packet_create(data.ptr, data.length,
111 					ENET_PACKET_FLAG_RELIABLE);
112 		sendToAllExcept(exceptClient, packet, channel);
113 	}
114 
115 	/// ditto
116 	void sendToAllExcept(ClientId exceptClient, ENetPacket* packet, ubyte channel = 0)
117 	{
118 		foreach(clientId, client; clientStorage.clients)
119 		{
120 			if (clientId != exceptClient && client)
121 				enet_peer_send(client.peer, channel, packet);
122 		}
123 	}
124 }