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