Advertisement
Guest User

Untitled

a guest
Jun 18th, 2018
64
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.87 KB | None | 0 0
  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <math.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <condition_variable>
  6. #include <iostream>
  7. #include <mutex>
  8. #include <queue>
  9. #include <string>
  10. #include <thread>
  11. #include <vector>
  12. #include "uWS/uWS.h"
  13.  
  14. #define PI 3.14159265
  15.  
  16. std::mutex mutex;
  17. std::mutex stateMutex;
  18.  
  19. struct UserMetaData {
  20. int port;
  21. char id;
  22. };
  23.  
  24. class Queue {
  25. struct State {
  26. int id;
  27. double positionX;
  28. double positionY;
  29. };
  30.  
  31. struct Element {
  32. char messageType;
  33. int id;
  34. int number;
  35. std::string message;
  36. };
  37.  
  38. std::vector<State> stateHistory;
  39. std::queue<Element> queue;
  40. State players[4];
  41. std::vector<uWS::WebSocket<uWS::SERVER>*> websockets;
  42. std::vector<char> freePlayerId = {'0', '1', '2', '3'};
  43. std::vector<int> ports = {3001, 3002, 3003, 3004, 3005, 3006,
  44. 3007, 3008, 3009, 3010, 3011, 3012};
  45.  
  46. public:
  47. Queue(){};
  48. ~Queue(){};
  49.  
  50. void addConnection(uWS::WebSocket<uWS::SERVER>* ws) {
  51. websockets.push_back(ws);
  52. }
  53.  
  54. Element pop() {
  55. Element element;
  56. std::unique_lock<std::mutex> lock(mutex);
  57. element = queue.front();
  58. queue.pop();
  59. lock.unlock();
  60. return element;
  61. }
  62.  
  63. void push(Element element) {
  64. std::lock_guard<std::mutex> lock(mutex);
  65. queue.push(element);
  66. }
  67.  
  68. void updateState(int playerId, int x, int y) {
  69. std::lock_guard<std::mutex> lock(stateMutex);
  70. players[playerId].positionX = x;
  71. players[playerId].positionY = y;
  72. }
  73.  
  74. State getState(int playerId) { return players[playerId]; }
  75.  
  76. void broadcast() {
  77. // as long as there are messages in the queue sends data to all connected
  78. // clients (ws). Queue is synchonised and thread safe.
  79.  
  80. Element tmp;
  81. UserMetaData* userMetaData;
  82. while (1) {
  83. if (!queue.empty()) {
  84. tmp = pop();
  85. for (uWS::WebSocket<uWS::SERVER>* ws : websockets) {
  86. userMetaData = (UserMetaData*)ws->getUserData();
  87. if (userMetaData->id != tmp.id) {
  88. std::string str = tmp.message;
  89. const char* astr = str.c_str();
  90. ws->send(astr, tmp.message.length(), uWS::OpCode::TEXT);
  91. }
  92. // printf("\n\n%s\n\n",tmp.message.c_str());
  93. }
  94. }
  95. }
  96. }
  97.  
  98. void removeWebsocket(uWS::WebSocket<uWS::SERVER>* ws) {
  99. websockets.erase(std::remove(websockets.begin(), websockets.end(), ws),
  100. websockets.end());
  101. }
  102.  
  103. void saveToQueue(char* message, int playerId, int length) {
  104. Element element;
  105. char outMessage[30];
  106. outMessage[0] = message[0];
  107. outMessage[1] = playerId;
  108. memcpy(&outMessage[2], message + 1, length);
  109. element.message = outMessage;
  110. element.id = playerId;
  111. push(element);
  112. }
  113.  
  114. char getFreeId() {
  115. char id = 0;
  116. if (!freePlayerId.empty()) {
  117. id = freePlayerId.back();
  118. freePlayerId.pop_back();
  119. }
  120. return id;
  121. }
  122. int getFreePort() {
  123. int port = 0;
  124. if (!ports.empty()) {
  125. port = ports.back();
  126. ports.pop_back();
  127. }
  128. return port;
  129. }
  130.  
  131. void addNewPort(int port) { ports.push_back(port); }
  132. void addFreeId(char id) { freePlayerId.push_back(id); }
  133. };
  134.  
  135. void clientMain(int port, Queue& queue, UserMetaData* userMetaData) {
  136. uWS::Hub h;
  137. h.onConnection([port, &queue, userMetaData](uWS::WebSocket<uWS::SERVER>* ws,
  138. uWS::HttpRequest req) {
  139. std::cout << "server thread: connected on port " << port << '\n';
  140. //
  141. queue.addConnection(ws);
  142. ws->setUserData(userMetaData);
  143. });
  144. h.onMessage([&queue](uWS::WebSocket<uWS::SERVER>* ws, char* message,
  145. size_t length, uWS::OpCode opCode) {
  146. message[length] = 0;
  147. UserMetaData* userMetaData = (UserMetaData*)ws->getUserData();
  148. char playerId = userMetaData->id;
  149. // this swich is a cringy do something about it
  150. // the messega we are storing in Element is in format
  151. // "messegatype,plyerID,resofthemessage" in restofthemessage delimiter is
  152. // ','
  153. // the message we are reciving from from in in format
  154. // "messageType,restofthemessage", delimiter is ','
  155. switch (message[0]) {
  156. case 'p':
  157. // position message, x, y on map
  158. double x, y;
  159. sscanf(&(message[2]), "%lf,%lf", &x, &y);
  160. queue.updateState(playerId, x, y);
  161. // handle messege
  162. break;
  163. case 'm':
  164. // move message
  165. double dir, val;
  166. sscanf(&(message[2]), "%lf,%lf", &dir, &val);
  167. // handle messege
  168. break;
  169. case 't':
  170. // move head of the tank
  171. double angle;
  172. sscanf(&(message[2]), "%lf", &angle);
  173. // handle messege
  174. break;
  175. case 's':
  176. // shot
  177. double shotX, shotY, shotDir, b, a, tmpX, tmpY, wynik;
  178. sscanf(&(message[2]), "%lf,%lf,%lf", &shotX, &shotY, &shotDir);
  179. // printf("messege s shotX:%lf, shotY:%lf, shotDir:%lf
  180. // \n", shotX, shotY,
  181. // shotDir);
  182. a = tan(shotDir * PI / 180.0);
  183. b = shotY - a * shotX;
  184. for (int i = 0; i < 4; i++) {
  185. // TODO: shotDir 2 IFs - y Left or Right side
  186. // TODO: STOP on first target.
  187. // TODO: sizeof(dlaSpajkiego) +1
  188. tmpX = queue.getState(i).positionX;
  189. tmpY = queue.getState(i).positionY;
  190. // printf("%lf,%lf\n", tmpX,tmpY);
  191. wynik = a * tmpX + b;
  192.  
  193. if (wynik > tmpY - 100 && wynik < tmpY + 100 && playerId - '0' != i) {
  194. char* dlaSpajkiego = new char[40];
  195. sprintf(dlaSpajkiego, "b%d,%lf,%lf", i, tmpX, tmpY);
  196. queue.saveToQueue(dlaSpajkiego, i, 30);
  197. delete[] dlaSpajkiego;
  198. }
  199. }
  200. break;
  201. }
  202. queue.saveToQueue(message, playerId, length);
  203. });
  204. h.onDisconnection([&queue](uWS::WebSocket<uWS::SERVER>* ws, int code,
  205. char* message, size_t length) {
  206. UserMetaData* userMetaData = (UserMetaData*)ws->getUserData();
  207. char playerId = userMetaData->id;
  208. int port = userMetaData->port;
  209. queue.addNewPort(port);
  210. queue.addFreeId(playerId);
  211. queue.removeWebsocket(ws);
  212. });
  213. h.listen(port);
  214. h.run();
  215. }
  216.  
  217. int main() {
  218. // main thread waits on port 3000 for clients, when client connects new thread
  219. // starts running and handles the client on new port
  220. std::vector<std::string> welcomeMessage = {
  221. std::string("hullDir:315,turretDir:315,x:3190,y:2540"),
  222. std::string("hullDir:45,turretDir:45,x:400,y:2540"),
  223. std::string("hullDir:135,turretDir:135,x:400,y:430"),
  224. std::string("hullDir:225,turretDir:225,x:3190,y:430")};
  225. Queue queue = Queue();
  226. // all threads in program
  227. std::vector<std::thread> threadVector;
  228. // start the broadcast thread that sends messages to all client in game
  229. threadVector.push_back(std::thread(&Queue::broadcast, &queue));
  230. uWS::Hub h;
  231.  
  232. // the port we are initially wait on clients.
  233. int port = 3000;
  234. std::cout << "waiting on port: " << port << '\n';
  235. h.onConnection([&queue, &welcomeMessage, &threadVector](
  236. uWS::WebSocket<uWS::SERVER>* ws, uWS::HttpRequest req) {
  237. UserMetaData* userData = new UserMetaData;
  238. // get one of the free id player and remove it from list
  239. // if (freePlayerId.empty)
  240. // handle if there is already 4 players;
  241. // else
  242. userData->id = queue.getFreeId();
  243. if (userData->id == 0)
  244. std::cout << "za duzo graczy do somthing about it";
  245.  
  246. userData->port = queue.getFreePort();
  247. if (userData->id == 0)
  248. std::cout << "nie ma wolnych portow";
  249.  
  250. // instead of this shamefull code with char* and magic number create a
  251. // std::string and just before ws->send() transrofm it to char*;
  252. // the form of the message is "port,userid,welcomeMessage"
  253. std::string tmpWelcomeMessage = welcomeMessage.back();
  254. welcomeMessage.pop_back();
  255. int messageSize = tmpWelcomeMessage.length();
  256. char* message = new char[messageSize + 2 + 6 + 1];
  257. sprintf(message, "%d,", userData->port);
  258. message[5] = userData->id;
  259. message[6] = ',';
  260. std::strcpy(message + 7, tmpWelcomeMessage.c_str());
  261. message[messageSize + 9] = 0;
  262. // get welcome message
  263. ws->send(message, messageSize + 9, uWS::OpCode::TEXT);
  264. threadVector.push_back(
  265. std::thread(&clientMain, userData->port, std::ref(queue), userData));
  266. delete[] message;
  267. });
  268.  
  269. h.onMessage([port, &queue](uWS::WebSocket<uWS::SERVER>* ws, char* message,
  270. size_t length, uWS::OpCode opCode) {});
  271.  
  272. h.onDisconnection([port, &queue](uWS::WebSocket<uWS::SERVER>* ws, int code,
  273. char* message, size_t length) {
  274. std::cout << "server: ws disconnected on " << port << '\n';
  275. });
  276.  
  277. h.listen(port);
  278. h.run();
  279.  
  280. return 0;
  281. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement