1 /** 2 Copyright: Copyright (c) 2014-2016 Andrey Penechko. 3 License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0). 4 Authors: Andrey Penechko. 5 */ 6 7 module netlib.baseclient; 8 9 import core.thread; 10 import std.conv : to; 11 import std.string : toStringz; 12 import std.experimental.logger; 13 14 import derelict.enet.enet; 15 16 import netlib.connection; 17 18 abstract class BaseClient : Connection 19 { 20 ENetAddress serverAddress; 21 ENetPeer* server; 22 bool isConnecting; 23 24 void connect(string address, ushort port) 25 { 26 enet_address_set_host(&serverAddress, address.toStringz); 27 serverAddress.port = port; 28 29 server = enet_host_connect(host, &serverAddress, 2, 42); 30 //enet_peer_timeout(server, 0, 0, 5000); 31 32 if (server is null) 33 { 34 error("An error occured while trying to create an ENet server peer"); 35 return; 36 } 37 38 isConnecting = true; 39 } 40 41 bool isConnected() @property 42 { 43 return host.connectedPeers > 0; 44 } 45 46 void disconnect() 47 { 48 if (isConnecting) 49 enet_peer_disconnect_now(server, 0); 50 else 51 enet_peer_disconnect(server, 0); 52 isConnecting = false; 53 } 54 55 void send(ubyte[] data, ubyte channel = 0) 56 { 57 if (!isRunning) return; 58 ENetPacket* packet = enet_packet_create(data.ptr, data.length, 59 ENET_PACKET_FLAG_RELIABLE); 60 enet_peer_send(server, channel, packet); 61 } 62 63 void send(P)(auto ref const(P) packet, ubyte channel = 0) 64 if (is(P == struct)) 65 { 66 if (packetId!P >= packetArray.length) 67 { 68 infof("Dropping packet %s: %s", P.stringof, packetId!P); 69 return; 70 } 71 72 send(createPacket(packet), channel); 73 } 74 75 // Set id mapping for packets 76 void setPacketMap(string[] packetNames) 77 { 78 import std.algorithm : countUntil, remove, SwapStrategy; 79 80 PacketInfo*[] newPacketArray; 81 newPacketArray.reserve(packetNames.length); 82 83 static bool pred(PacketInfo* packetInfo, string packetName) 84 { 85 return packetInfo.name == packetName; 86 } 87 88 foreach(i, packetName; packetNames) 89 { 90 ptrdiff_t index = countUntil!pred(packetArray, packetName); 91 size_t newId = newPacketArray.length; 92 93 if (index > -1) 94 { 95 newPacketArray ~= packetArray[index]; 96 remove!(SwapStrategy.unstable)(packetArray, index); 97 } 98 else 99 { 100 newPacketArray ~= new PacketInfo(packetName); 101 } 102 newPacketArray[$-1].id = newId; 103 } 104 105 packetArray = newPacketArray; 106 } 107 108 override void update() 109 { 110 ENetEvent event; 111 while (enet_host_service(host, &event, 0) > 0) 112 { 113 final switch (event.type) 114 { 115 case ENET_EVENT_TYPE_NONE: 116 break; 117 case ENET_EVENT_TYPE_CONNECT: 118 isConnecting = false; 119 onConnect(event); 120 break; 121 case ENET_EVENT_TYPE_RECEIVE: 122 onPacketReceived(event); 123 break; 124 case ENET_EVENT_TYPE_DISCONNECT: 125 onDisconnect(event); 126 isConnecting = false; 127 break; 128 } 129 } 130 } 131 }