add option idlecheckpoint
New experimental option This requires platform support to be useful. Currently an implementation for Windows TTY console is included. A Unix TTY implementation should be achievable I would think, but I haven't pursued that, at least not yet (contributions welcome). I'm not sure whether Qt or X11 interfaces offer a similar timeout capability.. How it works: When idlecheckpoint in on, if the wait for a new input is idle for 10 seconds (length of time to waite is controlled by IDLECHECKPOINT_WAIT_TIME #define in hack.h), save_currentstate() is called to bring everything up-to-date should a hangup or crash occur. The input wait then continues/resumes. The save_currentstate() call is only executed once per input request.
This commit is contained in:
@@ -681,6 +681,16 @@ typedef unsigned char uchar;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* experimential; if the platform/window-port supports it; when the game has
|
||||
* started to wait for player input, and the wait lasts longer than
|
||||
* IDLECHECKPOINT_WAIT_TIME seconds (defined in hack.h or *conf.h), the game
|
||||
* will perform an update to the checkpoint file.
|
||||
* Currently has support in:
|
||||
* WIN32CON
|
||||
*/
|
||||
|
||||
/* #define IDLECHECKPOINT */
|
||||
|
||||
/* End of Section 4 */
|
||||
|
||||
#ifdef TTY_TILES_ESCCODES
|
||||
|
||||
@@ -246,6 +246,8 @@ struct instance_flags {
|
||||
* to input becoming taken over);
|
||||
* True => enable fuzzer when entering moveloop */
|
||||
boolean herecmd_menu; /* use menu when mouseclick on yourself */
|
||||
boolean idlecheckpoint; /* platform should perform a checkpoint update
|
||||
* if waiting for input longer than 10 seconds */
|
||||
boolean invis_goldsym; /* gold symbol is ' '? */
|
||||
boolean in_lua; /* executing a lua script */
|
||||
boolean lua_testing; /* doing lua tests */
|
||||
|
||||
@@ -588,6 +588,13 @@ enum inventory_counts {
|
||||
/* 2023/11/30 invlet_max is not yet used anywhere */
|
||||
};
|
||||
|
||||
#ifndef IDLECHECKPOINT_WAIT_TIME
|
||||
#define IDLECHECKPOINT_WAIT_TIME 10 /* seconds to wait before executing a checkpoint;
|
||||
* always #define'd but only has meaning if
|
||||
* IDLECHECKPOINT is defined.
|
||||
*/
|
||||
#endif
|
||||
|
||||
struct kinfo {
|
||||
struct kinfo *next; /* chain of delayed killers */
|
||||
int id; /* uprop keys to ID a delayed killer */
|
||||
|
||||
@@ -387,6 +387,9 @@ static int optfn_##a(int, int, boolean, char *, char *);
|
||||
Yes, Yes, No, No, NoAlias,
|
||||
"load IBMGraphics display symbols into symset")
|
||||
#endif
|
||||
NHOPTB(idlecheckpoint, Advanced, 0, opt_in, set_in_game,
|
||||
Off, Yes, No, No, NoAlias, &iflags.idlecheckpoint, Term_Off,
|
||||
"update checkpoint file if input is idle for 10 seconds")
|
||||
#ifndef MAC
|
||||
NHOPTB(ignintr, Advanced, 0, opt_in, set_in_game,
|
||||
Off, Yes, No, No, NoAlias, &flags.ignintr, Term_False,
|
||||
|
||||
@@ -35,6 +35,10 @@
|
||||
#define EARLY_CONFIGFILE_PASS
|
||||
#define TTY_PERM_INVENT
|
||||
|
||||
#ifdef WIN32CON
|
||||
#define IDLECHECKPOINT
|
||||
#endif
|
||||
|
||||
/*
|
||||
* -----------------------------------------------------------------
|
||||
* The remaining code shouldn't need modification.
|
||||
|
||||
@@ -5310,6 +5310,14 @@ optfn_boolean(
|
||||
#endif
|
||||
go.opt_need_redraw = TRUE;
|
||||
break;
|
||||
#ifndef IDLECHECKPOINT
|
||||
case opt_idlecheckpoint:
|
||||
pline("There is no underlying support for 'idlecheckpoint'"
|
||||
" compiled in.");
|
||||
iflags.idlecheckpoint = FALSE;
|
||||
give_opt_msg = FALSE;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
+57
-32
@@ -3097,7 +3097,8 @@ default_checkinput(
|
||||
DWORD dwWait;
|
||||
#endif
|
||||
int ch = 0;
|
||||
boolean valid = 0, done = 0;
|
||||
boolean valid = 0, done = 0, done_a_checkpoint = FALSE;
|
||||
DWORD how_many_milliseconds = 0;
|
||||
|
||||
#ifdef QWERTZ_SUPPORT
|
||||
if (numberpad & 0x10) {
|
||||
@@ -3107,54 +3108,78 @@ default_checkinput(
|
||||
qwertz = FALSE;
|
||||
}
|
||||
#endif
|
||||
done_a_checkpoint = FALSE;
|
||||
how_many_milliseconds = (iflags.idlecheckpoint)
|
||||
? (IDLECHECKPOINT_WAIT_TIME * 1000)
|
||||
: INFINITE;
|
||||
while (!done) {
|
||||
#if defined(SAFERHANGUP)
|
||||
dwWait = WaitForSingleObjectEx(hConIn, // event object to wait for
|
||||
INFINITE, // waits indefinitely
|
||||
how_many_milliseconds,
|
||||
TRUE); // alertable wait enabled
|
||||
#if defined(SAFERHANGUP)
|
||||
if (dwWait == WAIT_FAILED)
|
||||
return '\033';
|
||||
#endif
|
||||
ReadConsoleInput(hConIn, ir, 1, count);
|
||||
if (mode == 0) {
|
||||
if ((ir->EventType == KEY_EVENT) && ir->Event.KeyEvent.bKeyDown) {
|
||||
ch = default_processkeystroke(hConIn, ir, &valid, numberpad, 0);
|
||||
done = valid;
|
||||
}
|
||||
} else {
|
||||
if (*count > 0) {
|
||||
if (ir->EventType == KEY_EVENT
|
||||
#ifdef INSURANCE
|
||||
if (iflags.idlecheckpoint
|
||||
&& dwWait == WAIT_TIMEOUT && !done_a_checkpoint) {
|
||||
/* no input for 30 seconds, so let's take
|
||||
* advantage and do a game checkpoint,
|
||||
* then resume the wait.
|
||||
*/
|
||||
save_currentstate();
|
||||
done_a_checkpoint = TRUE;
|
||||
} else
|
||||
#endif /* INSURANCE */
|
||||
{
|
||||
ReadConsoleInput(hConIn, ir, 1, count);
|
||||
if (mode == 0) {
|
||||
if ((ir->EventType == KEY_EVENT)
|
||||
&& ir->Event.KeyEvent.bKeyDown) {
|
||||
ch = default_processkeystroke(hConIn, ir, &valid,
|
||||
numberpad, 0);
|
||||
done = valid;
|
||||
}
|
||||
} else {
|
||||
if (*count > 0) {
|
||||
if (ir->EventType == KEY_EVENT
|
||||
&& ir->Event.KeyEvent.bKeyDown) {
|
||||
#ifdef QWERTZ_SUPPORT
|
||||
if (qwertz)
|
||||
numberpad |= 0x10;
|
||||
if (qwertz)
|
||||
numberpad |= 0x10;
|
||||
#endif
|
||||
ch = default_processkeystroke(hConIn, ir, &valid, numberpad, 0);
|
||||
ch = default_processkeystroke(hConIn, ir, &valid,
|
||||
numberpad, 0);
|
||||
#ifdef QWERTZ_SUPPORT
|
||||
numberpad &= ~0x10;
|
||||
numberpad &= ~0x10;
|
||||
#endif
|
||||
if (valid)
|
||||
return ch;
|
||||
} else if (ir->EventType == MOUSE_EVENT) {
|
||||
if ((ir->Event.MouseEvent.dwEventFlags == 0)
|
||||
&& (ir->Event.MouseEvent.dwButtonState & MOUSEMASK)) {
|
||||
cc->x = ir->Event.MouseEvent.dwMousePosition.X + 1;
|
||||
cc->y = ir->Event.MouseEvent.dwMousePosition.Y - 1;
|
||||
if (valid)
|
||||
return ch;
|
||||
} else if (ir->EventType == MOUSE_EVENT) {
|
||||
if ((ir->Event.MouseEvent.dwEventFlags == 0)
|
||||
&& (ir->Event.MouseEvent.dwButtonState
|
||||
& MOUSEMASK)) {
|
||||
cc->x =
|
||||
ir->Event.MouseEvent.dwMousePosition.X + 1;
|
||||
cc->y =
|
||||
ir->Event.MouseEvent.dwMousePosition.Y - 1;
|
||||
|
||||
if (ir->Event.MouseEvent.dwButtonState & LEFTBUTTON)
|
||||
*mod = CLICK_1;
|
||||
else if (ir->Event.MouseEvent.dwButtonState
|
||||
& RIGHTBUTTON)
|
||||
*mod = CLICK_2;
|
||||
if (ir->Event.MouseEvent.dwButtonState
|
||||
& LEFTBUTTON)
|
||||
*mod = CLICK_1;
|
||||
else if (ir->Event.MouseEvent.dwButtonState
|
||||
& RIGHTBUTTON)
|
||||
*mod = CLICK_2;
|
||||
#if 0 /* middle button */
|
||||
else if (ir->Event.MouseEvent.dwButtonState & MIDBUTTON)
|
||||
*mod = CLICK_3;
|
||||
#endif
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else
|
||||
done = 1;
|
||||
} else
|
||||
done = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return mode ? 0 : ch;
|
||||
|
||||
@@ -300,7 +300,7 @@ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);*/
|
||||
if WINDOWPORT(tty) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 20; ++i) {
|
||||
for (i = 0; i < 5; ++i) {
|
||||
nh_delay_output();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user