/* start_game: Start a new game * parameters: name, role, race, gend, align, playmode */ static void ccmd_start_game(json_t * params) { char filename[1024], basename[1024], path[1024]; json_t *j_msg; const char *name; int role, race, gend, align, mode, fd, ret; long t; if (json_unpack (params, "{ss,si,si,si,si,si*}", "name", &name, "role", &role, "race", &race, "gender", &gend, "alignment", &align, "mode", &mode) == -1) exit_client("Bad set of parameters for start_game"); /* reset cached display data from a previous game */ reset_cached_diplaydata(); if (mode == MODE_WIZARD && !user_info.can_debug) mode = MODE_EXPLORE; t = (long)time(NULL); snprintf(path, 1024, "%s/save/%s/", settings.workdir, user_info.username); snprintf(basename, 1024, "%ld_%s.nhgame", t, name); snprintf(filename, 1024, "%s%s", path, basename); mkdir(path, 0755); /* should already exist unless something went wrong while upgrading */ fd = open(filename, O_EXCL | O_CREAT | O_RDWR, 0600); if (fd == -1) exit_client("Could not create the logfile"); ret = nh_start_game(fd, name, role, race, gend, align, mode); if (ret) { struct nh_roles_info *ri = nh_get_roles(); const char *rolename = (gend && ri->rolenames_f[role]) ? ri-> rolenames_f[role] : ri->rolenames_m[role]; gamefd = fd; gameid = db_add_new_game(user_info.uid, basename, rolename, ri->racenames[race], ri->gendnames[gend], ri->alignnames[align], mode, name, player_info.level_desc); log_msg("%s has started a new game (%d) as %s", user_info.username, gameid, name); j_msg = json_pack("{si,si}", "return", ret, "gameid", gameid); } else { close(fd); unlink(filename); j_msg = json_pack("{si,si}", "return", ret, "gameid", -1); } client_msg("start_game", j_msg); }
static void ccmd_restore_game(json_t * params) { int gid, fd, status; char filename[1024], basename[1024]; if (json_unpack(params, "{si*}", "gameid", &gid) == -1) exit_client("Bad set of parameters for restore_game"); if (!db_get_game_filename(user_info.uid, gid, basename, 1024)) { client_msg("restore_game", json_pack("{si}", "return", ERR_BAD_FILE)); return; } snprintf(filename, 1024, "%s/save/%s/%s", settings.workdir, user_info.username, basename); fd = open(filename, O_RDWR); if (fd == -1) { client_msg("restore_game", json_pack("{si}", "return", ERR_BAD_FILE)); return; } /* reset cached display data from a previous game */ reset_cached_diplaydata(); status = nh_restore_game(fd, NULL, FALSE); if (status == ERR_REPLAY_FAILED) { log_msg("Failed to restore saved game %d, file %s", gid, filename); if (srv_yn_function ("Restoring the game failed. Would you like to remove it from the list?", "yn", 'n') == 'y') { db_delete_game(user_info.uid, gid); log_msg("%s has chosen to remove game %d from the database", user_info.username, gid); } } client_msg("restore_game", json_pack("{si}", "return", status)); if (status == GAME_RESTORED) { gameid = gid; gamefd = fd; db_update_game(gameid, player_info.moves, player_info.z, player_info.level_desc); log_msg("%s has restored game %d", user_info.username, gameid); } }
void exit_client(const char *err) { const char *msg = err ? err : ""; json_t *exit_obj; if (err) log_msg("Client error: %s. Exit.", err); if (outfd != -1) { exit_obj = json_object(); json_object_set_new(exit_obj, "error", err ? json_true() : json_false()); json_object_set_new(exit_obj, "message", json_string(msg)); if (can_send_msg) client_msg("server_error", exit_obj); else json_decref(exit_obj); usleep(100); /* try to make sure the server process handles write() before close(). */ close(infd); close(outfd); infd = outfd = -1; } termination_flag = 3; /* make sure the command loop exits if nh_exit_game jumps there */ if (!sigsegv_flag) nh_exit_game(EXIT_FORCE_SAVE); /* might not return here */ nh_lib_exit(); close_database(); if (user_info.username) free(user_info.username); free_config(); reset_cached_diplaydata(); end_logging(); exit(err != NULL); }