main.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497
  1. /*
  2. Space Construct by Beanzilla
  3. Beanzilla@21:4/110 on fsxNet
  4. */
  5. // Verion 0.1-dev
  6. #define VERSION_MAJOR 0
  7. #define VERSION_MINOR 1
  8. #ifndef VERSION_TYPE
  9. #define VERSION_TYPE "dev"
  10. #endif
  11. #define PATH_MAX 256
  12. #define PATH_SEP "/"
  13. #include <MagiDoor.h>
  14. #include <sqlite3.h>
  15. #if defined(_MSC_VER) || defined(WIN32)
  16. #define snprintf _snprintf
  17. #define strcasecmp _stricmp
  18. #include <winsock2.h>
  19. #ifndef _MSC_VER
  20. #define _MSC_VER 1
  21. #endif
  22. #else
  23. #include <arpa/inet.h>
  24. #endif
  25. // Standard C
  26. #include <time.h>
  27. #include <stdio.h>
  28. #include <string.h>
  29. #include <stdlib.h>
  30. #include <stdarg.h>
  31. #include <ctype.h>
  32. #include <sys/types.h>
  33. #include <sys/stat.h>
  34. #include <unistd.h> // stat
  35. char * log_path = "logs";
  36. int inuse = 0; // Are any other copies of us running? (We are a single door!)
  37. int debug = 0; // Are we in debug mode?
  38. // User Structure (This includes guns, fuel, armor, shields, HP)
  39. typedef struct user_info {
  40. int uid; // Primary Key
  41. int experience; // Think about this as score
  42. // Was ship structure, now is part of user
  43. int guns; // Placed Guns, More means more damage (Deals from 1-2 damage per attack)
  44. int fuel; // How many "turns" do we have
  45. int metal; // Used to build more guns/armors/shields possibly fuel too (guns take 5, armor takes 3, shields take 7, maybe fuel takes 12)
  46. int armors; // Placed Armors (Each Armor takes 4 points of damage then breaks off)
  47. int shields; // Placed Shields (Each Shields takes 3 points of damage then is offline, regenerates 1 point per attack/turn must reach 50% of max to being protecting again)
  48. int hitpoints; // Total hitpoints till we die (Rules for taking damage, shields first then armor then hitpoints)
  49. int armorpoints; // Points we get from armors (Repairable but costs 1 metal per point, but can break if taking too much damage)
  50. int shieldpoints; // Points we get from shields (Self-Regenerates, and does not get destroyed)
  51. int shieldsup; // 0 means yes, anything else means shields are offline, deduct if not 0 for each attack.
  52. char nick[256]; // What they go by on score board, this allows duping since we really go by real
  53. char real[256]; // Their real name to match with drop file info, prevents someone from loging in as another
  54. } user_inf;
  55. void dolog(char *fmt, ...) {
  56. // Low end Logging
  57. char buffer[PATH_MAX];
  58. struct tm *time_now;
  59. time_t timen;
  60. FILE *logfptr;
  61. timen = time(NULL);
  62. time_now = localtime(&timen);
  63. if (log_path != NULL) {
  64. snprintf(buffer, PATH_MAX, "%s%s%04d%02d%02d.log", log_path, PATH_SEP,
  65. time_now->tm_year + 1900, time_now->tm_mon + 1, time_now->tm_mday);
  66. } else {
  67. snprintf(buffer, PATH_MAX, "%04d%02d%02d.log", time_now->tm_year + 1900,
  68. time_now->tm_mon + 1, time_now->tm_mday);
  69. }
  70. logfptr = fopen(buffer, "a");
  71. if (!logfptr) {
  72. return;
  73. }
  74. va_list ap;
  75. va_start(ap, fmt);
  76. vsnprintf(buffer, 512, fmt, ap);
  77. va_end(ap);
  78. fprintf(logfptr, "%02d:%02d:%02d %s\n", time_now->tm_hour, time_now->tm_min,
  79. time_now->tm_sec, buffer);
  80. fclose(logfptr);
  81. }
  82. void db_test() {
  83. sqlite3 *db;
  84. sqlite3_stmt *stmt;
  85. char sqlbuffer[256];
  86. char strbuffer[256];
  87. int rc = sqlite3_open("spaceconstruct.db3", &db);
  88. if(rc) { // Did we do a successful open?
  89. dolog("E: failed opening database %s", sqlite3_errmsg(db));
  90. sqlite3_close(db);
  91. md_exit(1);
  92. }
  93. sqlite3_busy_timeout(db, 5000);
  94. // DB open
  95. strcpy(sqlbuffer, "SELECT * FROM user;");
  96. sqlite3_prepare_v2(db, sqlbuffer, strlen(sqlbuffer), &stmt, NULL);
  97. while(sqlite3_step(stmt) == SQLITE_ROW) {
  98. /* Disabled to reduce logs to errors/warnings
  99. dolog("%s=%d %s=%s %s=%s %s=%d %s=%d %s=%d %s=%d %s=%d %s=%d %s=%d %s=%d %s=%d",
  100. sqlite3_column_name(stmt, 0), // int, uid
  101. sqlite3_column_int(stmt, 0),
  102. sqlite3_column_name(stmt, 1), // text, nick
  103. sqlite3_column_text(stmt, 1),
  104. sqlite3_column_name(stmt, 2), // text, real
  105. sqlite3_column_text(stmt, 2),
  106. sqlite3_column_name(stmt, 3), // int, experiece
  107. sqlite3_column_int(stmt, 3),
  108. sqlite3_column_name(stmt, 4), // int, metal
  109. sqlite3_column_int(stmt, 4),
  110. sqlite3_column_name(stmt, 5), // int, fuel
  111. sqlite3_column_int(stmt, 5),
  112. sqlite3_column_name(stmt, 6), // int, guns
  113. sqlite3_column_int(stmt, 6),
  114. sqlite3_column_name(stmt, 7), // int, armors
  115. sqlite3_column_int(stmt, 7),
  116. sqlite3_column_name(stmt, 8), // int, shields
  117. sqlite3_column_int(stmt, 8),
  118. sqlite3_column_name(stmt, 9), // int, armorpoints
  119. sqlite3_column_int(stmt, 9),
  120. sqlite3_column_name(stmt, 10), // int, shieldpoints
  121. sqlite3_column_int(stmt, 10),
  122. sqlite3_column_name(stmt, 11), // int, hitpoints
  123. sqlite3_column_int(stmt, 11)
  124. ); */
  125. md_printf("`white`%s=%d %s=%s %s=%s %s=%d %s=%d %s=%d %s=%d %s=%d %s=%d %s=%d %s=%d %s=%d\r\n",
  126. sqlite3_column_name(stmt, 0), // int, uid
  127. sqlite3_column_int(stmt, 0),
  128. sqlite3_column_name(stmt, 1), // text, nick
  129. sqlite3_column_text(stmt, 1),
  130. sqlite3_column_name(stmt, 2), // text, real
  131. sqlite3_column_text(stmt, 2),
  132. sqlite3_column_name(stmt, 3), // int, experiece
  133. sqlite3_column_int(stmt, 3),
  134. sqlite3_column_name(stmt, 4), // int, metal
  135. sqlite3_column_int(stmt, 4),
  136. sqlite3_column_name(stmt, 5), // int, fuel
  137. sqlite3_column_int(stmt, 5),
  138. sqlite3_column_name(stmt, 6), // int, guns
  139. sqlite3_column_int(stmt, 6),
  140. sqlite3_column_name(stmt, 7), // int, armors
  141. sqlite3_column_int(stmt, 7),
  142. sqlite3_column_name(stmt, 8), // int, shields
  143. sqlite3_column_int(stmt, 8),
  144. sqlite3_column_name(stmt, 9), // int, armorpoints
  145. sqlite3_column_int(stmt, 9),
  146. sqlite3_column_name(stmt, 10), // int, shieldpoints
  147. sqlite3_column_int(stmt, 10),
  148. sqlite3_column_name(stmt, 11), // int, hitpoints
  149. sqlite3_column_int(stmt, 11),
  150. sqlite3_column_name(stmt, 12), // int, shieldsup
  151. sqlite3_column_int(stmt, 12)
  152. );
  153. } // Clean up database
  154. sqlite3_finalize(stmt);
  155. sqlite3_close(db);
  156. }
  157. int check_lock() {
  158. // Checks stats of lock, (1 = Lock is in effect, 0 = No Lock established)
  159. struct stat s;
  160. if (stat("lock.flg", &s) == 0) {
  161. return 1;
  162. } else {
  163. return 0;
  164. }
  165. }
  166. void grab_lock() {
  167. // Attempt to grab lock
  168. int valid = check_lock();
  169. FILE *fhandle;
  170. if (valid == 0) {
  171. fhandle = fopen("lock.flg", "w");
  172. if(!fhandle) {
  173. dolog("E: Unable to make lock.flg!");
  174. fprintf(stderr, "Unable to establish lock!\r\n");
  175. md_exit(-1);
  176. }
  177. fprintf(fhandle, "I am in use already!\n");
  178. fclose(fhandle);
  179. } else {
  180. dolog("W: Lock already established!");
  181. }
  182. }
  183. void rel_lock() {
  184. // Attempt to release lock
  185. int valid = check_lock();
  186. if (valid == 1) {
  187. if (unlink("lock.flg") != 0) {
  188. dolog("E: Unable to release lock.flg!");
  189. fprintf(stderr, "Unable to release lock!\r\n");
  190. md_exit(-1);
  191. }
  192. } else {
  193. dolog("W: Lock already released!");
  194. }
  195. }
  196. void log_drop() {
  197. // Spits out info from Drop File:
  198. /* Disabled to reduce logs to errors/warnings
  199. dolog("First=%s Last=%s Alias=%s TimeLeft=%d SecLevel=%d Location=%s Node=%d Socket=%d Sysop=%s",
  200. mdcontrol.user_firstname,
  201. mdcontrol.user_lastname,
  202. mdcontrol.user_alias,
  203. mdcontrol.user_timeleft,
  204. mdcontrol.user_seclevel,
  205. mdcontrol.user_location,
  206. mdcontrol.node,
  207. mdcontrol.socket,
  208. mdcontrol.sysop_name
  209. );
  210. */
  211. md_printf("`white`First=%s Last=%s Alias=%s TimeLeft=%d SecLevel=%d Location=%s Node=%d Socket=%d Sysop=%s\r\n",
  212. mdcontrol.user_firstname,
  213. mdcontrol.user_lastname,
  214. mdcontrol.user_alias,
  215. mdcontrol.user_timeleft,
  216. mdcontrol.user_seclevel,
  217. mdcontrol.user_location,
  218. mdcontrol.node,
  219. mdcontrol.socket,
  220. mdcontrol.sysop_name
  221. );
  222. }
  223. void paws() {
  224. // Aaah, DRY
  225. md_printf("`white`Press any key to continue...");
  226. md_getc();
  227. md_printf("\r\n");
  228. }
  229. int locate_player(char first[], char last[]) {
  230. // returns user id for given real name and 0 for no record found
  231. sqlite3 *db;
  232. sqlite3_stmt *stmt;
  233. char sqlbuffer[256];
  234. int result = 0;
  235. char name[256];
  236. int rc = sqlite3_open("spaceconstruct.db3", &db);
  237. if(rc) { // Did we do a successful open?
  238. dolog("E: failed opening database %s", sqlite3_errmsg(db));
  239. sqlite3_close(db);
  240. md_exit(1);
  241. }
  242. sqlite3_busy_timeout(db, 5000);
  243. // Form Real Name
  244. strcpy(name, "");
  245. strcat(name, first);
  246. strcat(name, " ");
  247. strcat(name, last);
  248. //md_printf("realname = '%s'\r\n", name);
  249. // Locating user with given name
  250. strcpy(sqlbuffer, "SELECT * from user where real=? COLLATE NOCASE;");
  251. sqlite3_prepare_v2(db, sqlbuffer, strlen(sqlbuffer) + 1, &stmt, NULL);
  252. sqlite3_bind_text(stmt, 1, name, strlen(name), SQLITE_STATIC);
  253. rc = sqlite3_step(stmt);
  254. if (rc == SQLITE_ROW) {
  255. //dolog("User=%s uid=%d", name, sqlite3_column_int(stmt, 0));
  256. result = sqlite3_column_int(stmt, 0);
  257. } else {
  258. dolog("W: Unable to locate user=%s", name);
  259. result = 0;
  260. } // Clean Up, return results
  261. sqlite3_finalize(stmt);
  262. sqlite3_close(db);
  263. return result;
  264. }
  265. user_inf load_player(int uuid) {
  266. // Returns a player Structure from database
  267. sqlite3 *db;
  268. sqlite3_stmt *stmt;
  269. char sqlbuffer[256];
  270. user_inf result;
  271. int rc = sqlite3_open("spaceconstruct.db3", &db);
  272. if(rc) { // Did we do a successful open?
  273. dolog("E: failed opening database %s", sqlite3_errmsg(db));
  274. sqlite3_close(db);
  275. md_exit(1);
  276. }
  277. sqlite3_busy_timeout(db, 5000);
  278. strcpy(sqlbuffer, "SELECT * from user where uid=?;");
  279. sqlite3_prepare_v2(db, sqlbuffer, strlen(sqlbuffer) + 1, &stmt, NULL);
  280. sqlite3_bind_int(stmt, uuid, 1);
  281. rc = sqlite3_step(stmt);
  282. if (rc == SQLITE_ROW) {
  283. result.uid = sqlite3_column_int(stmt, 0);
  284. strcpy(result.nick, sqlite3_column_text(stmt, 1));
  285. strcpy(result.real, sqlite3_column_text(stmt, 2));
  286. result.experience = sqlite3_column_int(stmt, 3);
  287. result.metal = sqlite3_column_int(stmt, 4);
  288. result.fuel = sqlite3_column_int(stmt, 5);
  289. result.guns = sqlite3_column_int(stmt, 6);
  290. result.armors = sqlite3_column_int(stmt, 7);
  291. result.shields = sqlite3_column_int(stmt, 8);
  292. result.armorpoints = sqlite3_column_int(stmt, 9);
  293. result.shieldpoints = sqlite3_column_int(stmt, 10);
  294. result.hitpoints = sqlite3_column_int(stmt, 11);
  295. result.shieldsup = sqlite3_column_int(stmt, 12);
  296. } else {
  297. dolog("E: Unable to locate user with id=%d", uuid);
  298. sqlite3_finalize(stmt);
  299. sqlite3_close(db);
  300. md_exit(-1);
  301. }
  302. sqlite3_finalize(stmt);
  303. sqlite3_close(db);
  304. return result;
  305. }
  306. void update_player(user_inf data) {
  307. sqlite3 *db;
  308. sqlite3_stmt *stmt;
  309. char sqlbuffer[1024];
  310. int rc = sqlite3_open("spaceconstruct.db3", &db);
  311. if(rc) { // Did we do a successful open?
  312. dolog("E: failed opening database %s", sqlite3_errmsg(db));
  313. sqlite3_close(db);
  314. md_exit(1);
  315. }
  316. sqlite3_busy_timeout(db, 5000);
  317. // Bad, don't do this... opens to SQL injection!
  318. //snprintf(sqlbuffer, 1024, "UPDATE user SET nick = '%s', experience = %d, metal = %d, fuel = %d, guns = %d, armors = %d, shields = %d, armorpoints = %d, shieldpoints = %d, hitpoints = %d WHERE uid=%d;",
  319. // data.nick, data.experience, data.metal, data.fuel, data.guns, data.armors, data.shields, data.armorpoints, data.shieldpoints, data.hitpoints, data.uid);
  320. strcpy(sqlbuffer, "UPDATE user SET nick=?, experience=?, metal=?, fuel=?, guns=?, armors=?, shields=?, armorpoints=?, shieldpoints=?, hitpoints=?, shieldsup=? WHERE uid=?;");
  321. sqlite3_prepare_v2(db, sqlbuffer, strlen(sqlbuffer) + 1, &stmt, NULL);
  322. // Bind All data values
  323. sqlite3_bind_text(stmt, 1, data.nick, strlen(data.nick), SQLITE_STATIC);
  324. sqlite3_bind_int(stmt, 2, data.experience);
  325. sqlite3_bind_int(stmt, 3, data.metal);
  326. sqlite3_bind_int(stmt, 4, data.fuel);
  327. sqlite3_bind_int(stmt, 5, data.guns);
  328. sqlite3_bind_int(stmt, 6, data.armors);
  329. sqlite3_bind_int(stmt, 7, data.shields);
  330. sqlite3_bind_int(stmt, 8, data.armorpoints);
  331. sqlite3_bind_int(stmt, 9, data.shieldpoints);
  332. sqlite3_bind_int(stmt, 10, data.hitpoints);
  333. sqlite3_bind_int(stmt, 11, data.shieldsup);
  334. sqlite3_bind_int(stmt, 12, data.uid);
  335. // Execute
  336. rc = sqlite3_step(stmt);
  337. if(rc != SQLITE_DONE) {
  338. dolog("E: failed updating player=%d got error %s (%d)", data.uid, sqlite3_errmsg(db), rc);
  339. sqlite3_finalize(stmt);
  340. sqlite3_close(db);
  341. md_exit(-1);
  342. }
  343. sqlite3_finalize(stmt);
  344. sqlite3_close(db);
  345. }
  346. void main_menu() {
  347. // Main menu for once things are done being initalized
  348. int done = 0;
  349. char ch;
  350. while(!done) {
  351. md_clr_scr();
  352. if(mdcontrol.user_seclevel == 99 || mdcontrol.user_seclevel == 255) { // Display a menu for sysops
  353. md_sendfile("ansis/sc_mainh.ans", TRUE);
  354. ch = md_get_answer("PpLlVvQqEe\r");
  355. } else { // And display a different menu for non-sysops
  356. md_sendfile("ansis/sc_mainl.ans", TRUE);
  357. ch = md_get_answer("PpLlVvQq\r");
  358. }
  359. md_clr_scr();
  360. switch(tolower(ch)){
  361. case 'q':
  362. // Quit
  363. md_printf("`bright white`Farewell!\r\n");
  364. // Hmm sleep?
  365. done = 1;
  366. break;
  367. case '\r':
  368. case 'p':
  369. // Play Game (Default if the player just hits enter)
  370. if (inuse == 1) {
  371. md_printf("`bright red`Game in use!\r\n");
  372. } else {
  373. md_printf("`bright white`Play\r\n");
  374. }
  375. paws();
  376. break;
  377. case 'l':
  378. // List Players in the game
  379. md_printf("`bright red`There are no players!\r\n");
  380. paws();
  381. break;
  382. case 'v':
  383. // Version
  384. md_clr_scr();
  385. md_printf("`bright yellow`|--------------------------|\r\n");
  386. md_printf("`bright yellow`| Space Construct v%d.%d-%s |\r\n", VERSION_MAJOR, VERSION_MINOR, VERSION_TYPE);
  387. md_printf("`bright yellow`|--------------------------|\r\n");
  388. paws();
  389. break;
  390. case 'e':
  391. // Edit Game (User Editor, Game Settings)
  392. if(mdcontrol.user_seclevel == 99 || mdcontrol.user_seclevel == 255) {
  393. md_printf("`bright green`Sysop Menu\r\n");
  394. paws();
  395. break;
  396. }
  397. }
  398. }
  399. }
  400. int main(int argc, char **argv) {
  401. int socket;
  402. if (argc < 2) { // Not enough arguments
  403. fprintf(stderr, "usage:\n%s (DROPFILE [SOCKET])\r\n", argv[0]);
  404. dolog("E %s (DROPFILE [SOCKET])", argv[0]);
  405. return 0;
  406. }
  407. if (argc > 2) { // If socket is found use socket
  408. if (argv[2][0] >= '0' && argv[2][0] <= '9') {
  409. socket = strtol(argv[2], NULL, 10);
  410. } else {
  411. socket = -1;
  412. }
  413. } else {
  414. socket = -1;
  415. }
  416. // Initiate MagiDoor
  417. md_init(argv[1], socket);
  418. md_clr_scr();
  419. // Debug System
  420. if (debug) {
  421. dolog("=== Debug ===");
  422. md_printf("`white`=== Debug ===\r\n");
  423. md_printf("DropFile...\r\n");
  424. log_drop();
  425. int test = check_lock();
  426. if (test == 0) {
  427. md_printf("Lock is: Avalible\r\n");
  428. md_printf("Database...\r\n");
  429. db_test();
  430. } else {
  431. md_printf("Lock is: Taken\r\n");
  432. md_printf("CANCELED Database Dump\r\n");
  433. }
  434. md_printf("`bright green`Continue to Program?\r\n");
  435. md_printf("`bright black`(`bright white`Y`bright black`)`white`es `bright black`(`bright red`N`bright black`)`red`o");
  436. char t = md_get_answer("YyNn\r");
  437. md_printf("\r\n`white`");
  438. switch(tolower(t)) {
  439. case '\r':
  440. case 'y':
  441. break;
  442. case 'n':
  443. md_exit(0);
  444. break;
  445. }
  446. md_clr_scr();
  447. } else {
  448. dolog("--- Debug ---");
  449. }
  450. // Check Lock
  451. inuse = check_lock();
  452. // 0 means we got the lock first, 1 means someone else has it already!
  453. // Lock game
  454. if (inuse == 0) {
  455. grab_lock();
  456. }
  457. // Main Menu
  458. //main_menu();
  459. //user_inf ply = load_player(locate_player(mdcontrol.user_firstname, mdcontrol.user_lastname));
  460. //update_player(ply);
  461. // Unlock game
  462. if (inuse == 0) {
  463. rel_lock();
  464. }
  465. // Goodbye
  466. md_exit(0);
  467. }