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 client; 8 9 import core.thread; 10 import std.conv : to; 11 import std.stdio : writefln, writeln; 12 import std.string : format; 13 import std.random : uniform; 14 15 import derelict.enet.enet; 16 17 import connection; 18 import packets; 19 20 immutable randomNames = [ 21 "Bob", "Steve", "Alanakai", "Tyler", "Carmine", "Randy", "Tim", 22 "Robbie", "Xavier", "Jerrell", "Clinton", "Bob", "Berry", "Maximo", 23 "Emmett", "Napoleon", "Jeffery", "Ali", "Hubert", "Jordan", "Rickey", "Jamey", 24 "Bret", "Gene", "Cornell", "Garret", "Randal", "Luther", "Raymundo", "Brady", 25 "Reid", "Asha", "Tari", "Isela", "Qiana", "Nada", "Nicole", "Waneta", "Mammie", 26 "Deedra", "Shizuko", "Tammy", "Rachelle", "Tu", "Yon", "Torie", "Lauryn", 27 "Nikia", "Alaina", "Kelsey", "Velva", "Luna", "Nicola", "Darla", "Kelle", 28 "Valarie", "Bernardina", "Isidra", ]; 29 30 class Client : Connection 31 { 32 bool isRunning; 33 34 ENetAddress serverAddress; 35 ENetPeer* server; 36 37 UserId myId; 38 string myName; 39 40 string[UserId] userNames; 41 42 string userName(UserId userId) 43 { 44 return userId in userNames ? userNames[userId] : format("? %s", userId); 45 } 46 47 void start(string address = "127.0.0.1", ushort port = 1234) 48 { 49 registerPacket!LoginPacket; 50 registerPacket!SessionInfoPacket(&handleSessionInfoPacket); 51 registerPacket!UserLoggedInPacket(&handleUserLoggedInPacket); 52 registerPacket!UserLoggedOutPacket(&handleUserLoggedOutPacket); 53 registerPacket!MessagePacket(&handleMessagePacket); 54 55 enet_address_set_host(&serverAddress, cast(char*)address); 56 serverAddress.port = port; 57 58 host = enet_host_create(null /* create a client host */, 59 1 /* only allow 1 outgoing connection */, 60 2, 61 57600 / 8 /* 56K modem with 56 Kbps downstream bandwidth */, 62 14400 / 8 /* 56K modem with 14 Kbps upstream bandwidth */); 63 64 if (host is null) 65 { 66 writeln("Client: An error occured while trying to create an ENet server host"); 67 return; 68 } 69 70 server = enet_host_connect(host, &serverAddress, 2, 42); 71 enet_peer_timeout(server, 0, 0, 5000); 72 73 if (server is null) 74 { 75 writeln("Client: An error occured while trying to create an ENet server peer"); 76 return; 77 } 78 79 side = "Client"; 80 81 writeln("Client: Started"); 82 isRunning = true; 83 } 84 85 override void stop() 86 { 87 super.stop(); 88 writefln("Client: Stopped"); 89 } 90 91 void send(ubyte[] data, ubyte channel = 0) 92 { 93 ENetPacket* packet = enet_packet_create(data.ptr, data.length, 94 ENET_PACKET_FLAG_RELIABLE); 95 enet_peer_send(server, channel, packet); 96 } 97 98 override void onConnect(ref ENetEvent event) 99 { 100 writefln("Client: Connection to 127.0.0.1:1234 established"); 101 102 // generate random name 103 myName = randomNames[uniform(0, randomNames.length)]; 104 send(createPacket(LoginPacket(myName))); 105 } 106 107 void handleSessionInfoPacket(ubyte[] packetData, UserId peer) 108 { 109 SessionInfoPacket loginInfo = unpackPacket!SessionInfoPacket(packetData); 110 111 userNames = loginInfo.userNames; 112 myId = loginInfo.yourId; 113 114 writefln("Client %s: my id is %s", myName[0], myId); 115 116 // Send 3 hello message packets. 117 foreach(i; 0..3) 118 { 119 string str = format("hello from %s %s", myName, i); 120 ubyte[] packet = createPacket(MessagePacket(0, str)); 121 send(packet); 122 } 123 124 //send(createPacket(MessagePacket(0, "/stop"))); 125 flush(); 126 } 127 128 void handleUserLoggedInPacket(ubyte[] packetData, UserId peer) 129 { 130 UserLoggedInPacket newUser = unpackPacket!UserLoggedInPacket(packetData); 131 userNames[newUser.userId] = newUser.userName; 132 writefln("Client %s: %s has connected", myName[0], newUser.userName); 133 } 134 135 void handleUserLoggedOutPacket(ubyte[] packetData, UserId peer) 136 { 137 UserLoggedOutPacket packet = unpackPacket!UserLoggedOutPacket(packetData); 138 writefln("Client %s: %s has disconnected", myName[0], userName(packet.userId)); 139 userNames.remove(packet.userId); 140 } 141 142 void handleMessagePacket(ubyte[] packetData, UserId peer) 143 { 144 MessagePacket msg = unpackPacket!MessagePacket(packetData); 145 if (msg.userId == 0) 146 writefln("Client %s: %s", myName[0], msg.msg); 147 else 148 writefln("Client %s: %s> %s", myName[0], userName(msg.userId), msg.msg); 149 } 150 151 override void onDisconnect(ref ENetEvent event) 152 { 153 writefln("Client: disconnected with data %s", event.data); 154 155 // Reset server's information 156 event.peer.data = null; 157 158 isRunning = false; 159 } 160 }