main.c 15 KB

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