nh_bool nhnet_exit_game(int exit_type) { json_t *jmsg; int ret; if (!nhnet_active()) return nh_exit_game(exit_type); xmalloc_cleanup(); if (!api_entry()) return 0; jmsg = json_pack("{si}", "exit_type", exit_type); jmsg = send_receive_msg("exit_game", jmsg); if (json_unpack(jmsg, "{si!}", "return", &ret) == -1) { print_error("Incorrect return object in nhnet_exit_game"); ret = 0; } json_decref(jmsg); current_game = 0; api_exit(); return ret; }
boolean nh_exit_game(int exit_type) { boolean log_disabled = iflags.disable_log; if (!api_entry_checkpoint()) { /* not sure anything in here can actually call panic */ iflags.disable_log = log_disabled; return TRUE; /* terminate was called, so exit is successful */ } program_state.forced_exit = TRUE; /* clean up after viewing a game replay */ if (program_state.viewing) nh_view_replay_finish(); xmalloc_cleanup(); iflags.disable_log = TRUE; if (program_state.game_running) { switch (exit_type) { case EXIT_REQUEST_SAVE: dosave(); /* will ask "really save?" and, if 'y', eventually call terminate. */ break; case EXIT_FORCE_SAVE: dosave0(TRUE); terminate(); break; case EXIT_REQUEST_QUIT: done2(); break; case EXIT_FORCE_QUIT: done(QUIT); break; /* not reached */ case EXIT_PANIC: /* freeing things should be safe */ freedynamicdata(); dlb_cleanup(); panic("UI problem."); break; } iflags.disable_log = log_disabled; api_exit(); return FALSE; } iflags.disable_log = log_disabled; /* calling terminate() will get us out of nested contexts safely, eg: * UI_cmdloop -> nh_command -> UI_update_screen (problem happens here) -> nh_exit_game * will jump all the way back to UI_cmdloop */ terminate(); api_exit(); /* not reached */ return TRUE; }
void nh_lib_exit(void) { int i; xmalloc_cleanup(); for (i = 0; i < PREFIX_COUNT; i++) { free(fqn_prefix[i]); fqn_prefix[i] = NULL; } cleanup_opt_struct(); }
int nhnet_command(const char *cmd, int rep, struct nh_cmd_arg *arg) { int ret; json_t *jmsg, *jarg; if (!nhnet_active()) return nh_command(cmd, rep, arg); if (!api_entry()) return ERR_NETWORK_ERROR; xmalloc_cleanup(); switch (arg->argtype) { case CMD_ARG_DIR: jarg = json_pack("{si,si}", "argtype", arg->argtype, "d", arg->d); break; case CMD_ARG_POS: jarg = json_pack("{si,si,si}", "argtype", arg->argtype, "x", arg->pos.x, "y", arg->pos.y); break; case CMD_ARG_OBJ: jarg = json_pack("{si,si}", "argtype", arg->argtype, "invlet", arg->invlet); break; case CMD_ARG_NONE: default: jarg = json_pack("{si}", "argtype", arg->argtype); break; } jmsg = json_pack("{ss,so,si}", "command", cmd ? cmd : "", "arg", jarg, "count", rep); jmsg = send_receive_msg("game_command", jmsg); if (json_unpack(jmsg, "{si!}", "return", &ret) == -1) { print_error("Incorrect return object in nhnet_command"); ret = 0; } json_decref(jmsg); api_exit(); return ret; }
void nhnet_lib_exit(void) { if (nhnet_connected()) nhnet_disconnect(); xmalloc_cleanup(); conn_err = FALSE; #ifdef WIN32 WSACleanup(); #else /* restore previous signale handler for SIGPIPE */ sigaction(SIGPIPE, &oldaction, NULL); #endif }
void nhnet_view_replay_finish(void) { if (!nhnet_active()) return nh_view_replay_finish(); xmalloc_cleanup(); alt_windowprocs = windowprocs; if (!api_entry()) return; send_receive_msg("view_finish", json_object()); api_exit(); }
static void vraw_printf(const char *line, va_list the_args) { if (!strchr(line, '%')) raw_print(line); else { /* We can't use msgvprintf here because the game might not be running. We use xmvasprintf instead (vasprintf would be a little more appropriate but might not be available), then transfer to the stack, so that there are no untracked allocations when we make the API call. */ struct xmalloc_block *xm_temp = NULL; const char *fmtline = xmvasprintf(&xm_temp, line, the_args); char fmtline_onstack[strlen(fmtline) + 1]; strcpy(fmtline_onstack, fmtline); xmalloc_cleanup(&xm_temp); raw_print(fmtline_onstack); } }
void nhnet_disconnect(void) { json_t *msg; if (sockfd != -1) { in_connect_disconnect = TRUE; msg = send_receive_msg("shutdown", json_object()); in_connect_disconnect = FALSE; if (msg) json_decref(msg); close(sockfd); } sockfd = -1; connection_id = 0; current_game = 0; conn_err = FALSE; net_active = FALSE; xmalloc_cleanup(); free_option_lists(); memset(&nhnet_server_ver, 0, sizeof(nhnet_server_ver)); }
/* perform the command given by cmdidx (in index into cmdlist in cmd.c) * returns -1 if the command completes */ int command_input(int cmdidx, int rep, struct nh_cmd_arg *arg) { boolean didmove = FALSE; if (multi >= 0 && occupation) handle_occupation(); else if (multi == 0 || (multi > 0 && cmdidx != -1)) { saved_cmd = cmdidx; do_command(cmdidx, rep, TRUE, arg); } else if (multi > 0) { /* allow interruption of multi-turn commands */ if (rep == -1) { nomul(0, NULL); return READY_FOR_INPUT; } if (flags.mv) { if (multi < COLNO && !--multi) flags.travel = iflags.travel1 = flags.mv = flags.run = 0; if (!domove(u.dx, u.dy, 0)) { /* Don't use a move when travelling into an obstacle. */ flags.move = FALSE; nomul(0, NULL); } } else do_command(saved_cmd, multi, FALSE, arg); } /* no need to do anything here for multi < 0 */ if (u.utotype) /* change dungeon level */ deferred_goto(); /* after rhack() */ /* !flags.move here: multiple movement command stopped */ else if (!flags.move || !flags.mv) iflags.botl = 1; if (vision_full_recalc) vision_recalc(0); /* vision! */ /* when running in non-tport mode, this gets done through domove() */ if ((!flags.run || iflags.runmode == RUN_TPORT) && (multi && (!flags.travel ? !(multi % 7) : !(moves % 7L)))) { if (flags.run) iflags.botl = 1; flush_screen(); } didmove = flags.move; if (didmove) { you_moved(); } /* actual time passed */ /****************************************/ /* once-per-player-input things go here */ /****************************************/ xmalloc_cleanup(); iflags.next_msg_nonblocking = FALSE; /* prepare for the next move */ flags.move = 1; pre_move_tasks(didmove); do_delay_msg(); if (multi == 0 && !occupation) { flush_screen(); /* Flush screen buffer */ maybe_tutorial(); } return -1; }