/* Space Construct by Beanzilla Beanzilla@21:4/110 on fsxNet */ // Verion 0.1-dev #define VERSION_MAJOR 0 #define VERSION_MINOR 1 #ifndef VERSION_TYPE #define VERSION_TYPE "dev" #endif #define PATH_MAX 256 #define PATH_SEP "/" #include #include #if defined(_MSC_VER) || defined(WIN32) #define snprintf _snprintf #define strcasecmp _stricmp #include #ifndef _MSC_VER #define _MSC_VER 1 #endif #else #include #endif // Standard C #include #include #include #include #include #include #include #include #include // stat char * log_path = "logs"; int inuse = 0; // Are any other copies of us running? (We are a single door!) int debug = 0; // Are we in debug mode? // User Structure (This includes guns, fuel, armor, shields, HP) typedef struct user_info { int uid; // Primary Key int experience; // Think about this as score // Was ship structure, now is part of user int guns; // Placed Guns, More means more damage (Deals from 1-2 damage per attack) int fuel; // How many "turns" do we have 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) int armors; // Placed Armors (Each Armor takes 4 points of damage then breaks off) 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) int hitpoints; // Total hitpoints till we die (Rules for taking damage, shields first then armor then hitpoints) int armorpoints; // Points we get from armors (Repairable but costs 1 metal per point, but can break if taking too much damage) int shieldpoints; // Points we get from shields (Self-Regenerates, and does not get destroyed) char nick[256]; // What they go by on score board, this allows duping since we really go by real char real[256]; // Their real name to match with drop file info, prevents someone from loging in as another } user_inf; void dolog(char *fmt, ...) { // Low end Logging char buffer[PATH_MAX]; struct tm *time_now; time_t timen; FILE *logfptr; timen = time(NULL); time_now = localtime(&timen); if (log_path != NULL) { snprintf(buffer, PATH_MAX, "%s%s%04d%02d%02d.log", log_path, PATH_SEP, time_now->tm_year + 1900, time_now->tm_mon + 1, time_now->tm_mday); } else { snprintf(buffer, PATH_MAX, "%04d%02d%02d.log", time_now->tm_year + 1900, time_now->tm_mon + 1, time_now->tm_mday); } logfptr = fopen(buffer, "a"); if (!logfptr) { return; } va_list ap; va_start(ap, fmt); vsnprintf(buffer, 512, fmt, ap); va_end(ap); fprintf(logfptr, "%02d:%02d:%02d %s\n", time_now->tm_hour, time_now->tm_min, time_now->tm_sec, buffer); fclose(logfptr); } void db_test() { sqlite3 *db; sqlite3_stmt *stmt; char sqlbuffer[256]; char strbuffer[256]; int rc = sqlite3_open("spaceconstruct.db3", &db); if(rc) { // Did we do a successful open? dolog("E: failed opening database %s", sqlite3_errmsg(db)); sqlite3_close(db); md_exit(1); } sqlite3_busy_timeout(db, 5000); // DB open strcpy(sqlbuffer, "SELECT * FROM user;"); sqlite3_prepare_v2(db, sqlbuffer, strlen(sqlbuffer), &stmt, NULL); while(sqlite3_step(stmt) == SQLITE_ROW) { /* Disabled to reduce logs to errors/warnings 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", sqlite3_column_name(stmt, 0), // int, uid sqlite3_column_int(stmt, 0), sqlite3_column_name(stmt, 1), // text, nick sqlite3_column_text(stmt, 1), sqlite3_column_name(stmt, 2), // text, real sqlite3_column_text(stmt, 2), sqlite3_column_name(stmt, 3), // int, experiece sqlite3_column_int(stmt, 3), sqlite3_column_name(stmt, 4), // int, metal sqlite3_column_int(stmt, 4), sqlite3_column_name(stmt, 5), // int, fuel sqlite3_column_int(stmt, 5), sqlite3_column_name(stmt, 6), // int, guns sqlite3_column_int(stmt, 6), sqlite3_column_name(stmt, 7), // int, armors sqlite3_column_int(stmt, 7), sqlite3_column_name(stmt, 8), // int, shields sqlite3_column_int(stmt, 8), sqlite3_column_name(stmt, 9), // int, armorpoints sqlite3_column_int(stmt, 9), sqlite3_column_name(stmt, 10), // int, shieldpoints sqlite3_column_int(stmt, 10), sqlite3_column_name(stmt, 11), // int, hitpoints sqlite3_column_int(stmt, 11) ); */ 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", sqlite3_column_name(stmt, 0), // int, uid sqlite3_column_int(stmt, 0), sqlite3_column_name(stmt, 1), // text, nick sqlite3_column_text(stmt, 1), sqlite3_column_name(stmt, 2), // text, real sqlite3_column_text(stmt, 2), sqlite3_column_name(stmt, 3), // int, experiece sqlite3_column_int(stmt, 3), sqlite3_column_name(stmt, 4), // int, metal sqlite3_column_int(stmt, 4), sqlite3_column_name(stmt, 5), // int, fuel sqlite3_column_int(stmt, 5), sqlite3_column_name(stmt, 6), // int, guns sqlite3_column_int(stmt, 6), sqlite3_column_name(stmt, 7), // int, armors sqlite3_column_int(stmt, 7), sqlite3_column_name(stmt, 8), // int, shields sqlite3_column_int(stmt, 8), sqlite3_column_name(stmt, 9), // int, armorpoints sqlite3_column_int(stmt, 9), sqlite3_column_name(stmt, 10), // int, shieldpoints sqlite3_column_int(stmt, 10), sqlite3_column_name(stmt, 11), // int, hitpoints sqlite3_column_int(stmt, 11) ); } // Clean up database sqlite3_finalize(stmt); sqlite3_close(db); } int check_lock() { // Checks stats of lock, (1 = Lock is in effect, 0 = No Lock established) struct stat s; if (stat("lock.flg", &s) == 0) { return 1; } else { return 0; } } void grab_lock() { // Attempt to grab lock int valid = check_lock(); FILE *fhandle; if (valid == 0) { fhandle = fopen("lock.flg", "w"); if(!fhandle) { dolog("E: Unable to make lock.flg!"); fprintf(stderr, "Unable to establish lock!\r\n"); md_exit(-1); } fprintf(fhandle, "I am in use already!\n"); fclose(fhandle); } else { dolog("W: Lock already established!"); } } void rel_lock() { // Attempt to release lock int valid = check_lock(); if (valid == 1) { if (unlink("lock.flg") != 0) { dolog("E: Unable to release lock.flg!"); fprintf(stderr, "Unable to release lock!\r\n"); md_exit(-1); } } else { dolog("W: Lock already released!"); } } void log_drop() { // Spits out info from Drop File: /* Disabled to reduce logs to errors/warnings dolog("First=%s Last=%s Alias=%s TimeLeft=%d SecLevel=%d Location=%s Node=%d Socket=%d Sysop=%s", mdcontrol.user_firstname, mdcontrol.user_lastname, mdcontrol.user_alias, mdcontrol.user_timeleft, mdcontrol.user_seclevel, mdcontrol.user_location, mdcontrol.node, mdcontrol.socket, mdcontrol.sysop_name ); */ md_printf("`white`First=%s Last=%s Alias=%s TimeLeft=%d SecLevel=%d Location=%s Node=%d Socket=%d Sysop=%s\r\n", mdcontrol.user_firstname, mdcontrol.user_lastname, mdcontrol.user_alias, mdcontrol.user_timeleft, mdcontrol.user_seclevel, mdcontrol.user_location, mdcontrol.node, mdcontrol.socket, mdcontrol.sysop_name ); } void paws() { // Aaah, DRY md_printf("`white`Press any key to continue..."); md_getc(); md_printf("\r\n"); } int locate_player(char first[], char last[]) { // returns user id for given real name and 0 for no record found sqlite3 *db; sqlite3_stmt *stmt; char sqlbuffer[256]; int result = 0; char name[256]; int rc = sqlite3_open("spaceconstruct.db3", &db); if(rc) { // Did we do a successful open? dolog("E: failed opening database %s", sqlite3_errmsg(db)); sqlite3_close(db); md_exit(1); } sqlite3_busy_timeout(db, 5000); // Form Real Name strcpy(name, ""); strcat(name, first); strcat(name, " "); strcat(name, last); //md_printf("realname = '%s'\r\n", name); // Locating user with given name strcpy(sqlbuffer, "SELECT * from user where real=? COLLATE NOCASE;"); sqlite3_prepare_v2(db, sqlbuffer, strlen(sqlbuffer) + 1, &stmt, NULL); sqlite3_bind_text(stmt, 1, name, strlen(name), SQLITE_STATIC); rc = sqlite3_step(stmt); if (rc == SQLITE_ROW) { //dolog("User=%s uid=%d", name, sqlite3_column_int(stmt, 0)); result = sqlite3_column_int(stmt, 0); } else { dolog("W: Unable to locate user=%s", name); result = 0; } // Clean Up, return results sqlite3_finalize(stmt); sqlite3_close(db); return result; } user_inf load_player(int uuid) { // Returns a player Structure from database sqlite3 *db; sqlite3_stmt *stmt; char sqlbuffer[256]; user_inf result; int rc = sqlite3_open("spaceconstruct.db3", &db); if(rc) { // Did we do a successful open? dolog("E: failed opening database %s", sqlite3_errmsg(db)); sqlite3_close(db); md_exit(1); } sqlite3_busy_timeout(db, 5000); strcpy(sqlbuffer, "SELECT * from user where uid=?;"); sqlite3_prepare_v2(db, sqlbuffer, strlen(sqlbuffer) + 1, &stmt, NULL); sqlite3_bind_int(stmt, uuid, 1); rc = sqlite3_step(stmt); if (rc == SQLITE_ROW) { result.uid = sqlite3_column_int(stmt, 0); strcpy(result.nick, sqlite3_column_text(stmt, 1)); strcpy(result.real, sqlite3_column_text(stmt, 2)); result.experience = sqlite3_column_int(stmt, 3); result.metal = sqlite3_column_int(stmt, 4); result.fuel = sqlite3_column_int(stmt, 5); result.guns = sqlite3_column_int(stmt, 6); result.armors = sqlite3_column_int(stmt, 7); result.shields = sqlite3_column_int(stmt, 8); result.armorpoints = sqlite3_column_int(stmt, 9); result.shieldpoints = sqlite3_column_int(stmt, 10); result.hitpoints = sqlite3_column_int(stmt, 11); } else { dolog("E: Unable to locate user with id=%d", uuid); sqlite3_finalize(stmt); sqlite3_close(db); md_exit(-1); } sqlite3_finalize(stmt); sqlite3_close(db); return result; } void update_player(user_inf data) { sqlite3 *db; sqlite3_stmt *stmt; char sqlbuffer[1024]; int rc = sqlite3_open("spaceconstruct.db3", &db); if(rc) { // Did we do a successful open? dolog("E: failed opening database %s", sqlite3_errmsg(db)); sqlite3_close(db); md_exit(1); } sqlite3_busy_timeout(db, 5000); // Bad, don't do this... opens to SQL injection! //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;", // data.nick, data.experience, data.metal, data.fuel, data.guns, data.armors, data.shields, data.armorpoints, data.shieldpoints, data.hitpoints, data.uid); strcpy(sqlbuffer, "UPDATE user SET nick=?, experience=?, metal=?, fuel=?, guns=?, armors=?, shields=?, armorpoints=?, shieldpoints=?, hitpoints=? WHERE uid=?;"); sqlite3_prepare_v2(db, sqlbuffer, strlen(sqlbuffer) + 1, &stmt, NULL); // Bind All data values sqlite3_bind_text(stmt, 1, data.nick, strlen(data.nick), SQLITE_STATIC); sqlite3_bind_int(stmt, 2, data.experience); sqlite3_bind_int(stmt, 3, data.metal); sqlite3_bind_int(stmt, 4, data.fuel); sqlite3_bind_int(stmt, 5, data.guns); sqlite3_bind_int(stmt, 6, data.armors); sqlite3_bind_int(stmt, 7, data.shields); sqlite3_bind_int(stmt, 8, data.armorpoints); sqlite3_bind_int(stmt, 9, data.shieldpoints); sqlite3_bind_int(stmt, 10, data.hitpoints); sqlite3_bind_int(stmt, 11, data.uid); // Execute rc = sqlite3_step(stmt); if(rc != SQLITE_DONE) { dolog("E: failed updating player=%d got error %s (%d)", data.uid, sqlite3_errmsg(db), rc); sqlite3_finalize(stmt); sqlite3_close(db); md_exit(-1); } sqlite3_finalize(stmt); sqlite3_close(db); } void main_menu() { // Main menu for once things are done being initalized int done = 0; char ch; while(!done) { md_clr_scr(); if(mdcontrol.user_seclevel == 99 || mdcontrol.user_seclevel == 255) { // Display a menu for sysops md_sendfile("ansis/sc_mainh.ans", TRUE); ch = md_get_answer("PpLlVvQqEe\r"); } else { // And display a different menu for non-sysops md_sendfile("ansis/sc_mainl.ans", TRUE); ch = md_get_answer("PpLlVvQq\r"); } md_clr_scr(); switch(tolower(ch)){ case 'q': // Quit md_printf("`bright white`Farewell!\r\n"); // Hmm sleep? done = 1; break; case '\r': case 'p': // Play Game (Default if the player just hits enter) if (inuse == 1) { md_printf("`bright red`Game in use!\r\n"); } else { md_printf("`bright white`Play\r\n"); } paws(); break; case 'l': // List Players in the game md_printf("`bright red`There are no players!\r\n"); paws(); break; case 'v': // Version md_clr_scr(); md_printf("`bright yellow`|--------------------------|\r\n"); md_printf("`bright yellow`| Space Construct v%d.%d-%s |\r\n", VERSION_MAJOR, VERSION_MINOR, VERSION_TYPE); md_printf("`bright yellow`|--------------------------|\r\n"); paws(); break; case 'e': // Edit Game (User Editor, Game Settings) if(mdcontrol.user_seclevel == 99 || mdcontrol.user_seclevel == 255) { md_printf("`bright green`Sysop Menu\r\n"); paws(); break; } } } } int main(int argc, char **argv) { int socket; if (argc < 2) { // Not enough arguments fprintf(stderr, "usage:\n%s (DROPFILE [SOCKET])\r\n", argv[0]); dolog("E %s (DROPFILE [SOCKET])", argv[0]); return 0; } if (argc > 2) { // If socket is found use socket if (argv[2][0] >= '0' && argv[2][0] <= '9') { socket = strtol(argv[2], NULL, 10); } else { socket = -1; } } else { socket = -1; } // Initiate MagiDoor md_init(argv[1], socket); md_clr_scr(); // Debug System if (debug) { dolog("=== Debug ==="); md_printf("`white`=== Debug ===\r\n"); md_printf("DropFile...\r\n"); log_drop(); int test = check_lock(); if (test == 0) { md_printf("Lock is: Avalible\r\n"); md_printf("Database...\r\n"); db_test(); } else { md_printf("Lock is: Taken\r\n"); md_printf("CANCELED Database Dump\r\n"); } md_printf("`bright green`Continue to Program?\r\n"); md_printf("`bright black`(`bright white`Y`bright black`)`white`es `bright black`(`bright red`N`bright black`)`red`o"); char t = md_get_answer("YyNn\r"); md_printf("\r\n`white`"); switch(tolower(t)) { case '\r': case 'y': break; case 'n': md_exit(0); break; } md_clr_scr(); } else { dolog("--- Debug ---"); } // Check Lock inuse = check_lock(); // 0 means we got the lock first, 1 means someone else has it already! // Lock game if (inuse == 0) { grab_lock(); } // Main Menu //main_menu(); user_inf ply = load_player(locate_player(mdcontrol.user_firstname, mdcontrol.user_lastname)); ply.experience += 10; update_player(ply); // Unlock game if (inuse == 0) { rel_lock(); } // Goodbye md_exit(0); }