more u.ustuck issues on save/restore
During a synchronous save operation initiated by the player (or other trigger for dosave0()), the u.usteed_mid and u.ustuck_mid values get set by savemonch(), and the monst pointers that u.ustuck and u.usteed point to are no longer valid, but not cleared. The checkpoint operation, which also needs to ensure that u.ustuck_mid and u.usteed_mid are set, must set them during the checkpoint, which is okay because the u.usteed and u.ustuck pointers _are_ valid during a checkpoint operation. So, we need to distinguish between a save game sequence, and a checkpoint sequence when writing out the u struct.
This commit is contained in:
@@ -3433,6 +3433,8 @@ set_ustuck(struct monst *mtmp)
|
||||
|
||||
disp.botl = TRUE;
|
||||
u.ustuck = mtmp;
|
||||
if (u.ustuck_mid)
|
||||
u.ustuck_mid = 0;
|
||||
if (!u.ustuck) {
|
||||
u.uswallow = 0;
|
||||
u.uswldtim = 0;
|
||||
|
||||
+1
-2
@@ -1219,8 +1219,7 @@ getlev(NHFILE *nhfp, int pid, xint8 lev)
|
||||
u.usteed_mid = 0;
|
||||
} else {
|
||||
if (mtmp->m_id == u.ustuck_mid) {
|
||||
set_ustuck(mtmp);
|
||||
u.ustuck_mid = 0;
|
||||
set_ustuck(mtmp); /* set_ustuck clears u.ustuck_mid */
|
||||
}
|
||||
place_monster(mtmp, mtmp->mx, mtmp->my);
|
||||
if (mtmp->wormno)
|
||||
|
||||
+24
-5
@@ -285,13 +285,32 @@ savegamestate(NHFILE *nhfp)
|
||||
Sfo_long(nhfp, &svw.wreserve, "wreserve");
|
||||
Sfo_int32(nhfp, &svw.wtreserved, "wtreserved");
|
||||
/*
|
||||
* It is critical to ensure that u.ustuck_mid and u.usteed_mid
|
||||
* hold current and correct data, in case this is needed by
|
||||
* recover.
|
||||
* In a normal save operation initiated by the player,
|
||||
* the u.ustuck_mid and u.usteed_mid were already set
|
||||
* by savemonchn() called from savelev_core(). Under
|
||||
* that operation, u.ustuck and u.usteed pointers no longer
|
||||
* point to valid locations here. Their non-zero values serve
|
||||
* only to flag that they are were set, but the pointers
|
||||
* must not be dereferenced.
|
||||
*/
|
||||
u.ustuck_mid = (u.ustuck) ? u.ustuck->m_id : 0;
|
||||
u.usteed_mid = (u.usteed) ? u.usteed->m_id : 0;
|
||||
if (program_state.in_checkpoint) {
|
||||
/*
|
||||
* It is critical to ensure that u.ustuck_mid and u.usteed_mid
|
||||
* hold current and correct data, in case this is needed by
|
||||
* recover. The pointers, if set, are still pointing at
|
||||
* valid data during a checkpoint operation, unlike during
|
||||
* a synchronized save operation.
|
||||
*/
|
||||
u.ustuck_mid = (u.ustuck) ? u.ustuck->m_id : 0;
|
||||
u.usteed_mid = (u.usteed) ? u.usteed->m_id : 0;
|
||||
}
|
||||
Sfo_you(nhfp, &u, "gamestate-you");
|
||||
|
||||
/* clear the in-memory value of these, now that they have been
|
||||
* successfully written out.
|
||||
*/
|
||||
u.ustuck_mid = 0;
|
||||
u.usteed_mid = 0;
|
||||
Sfo_char(nhfp, yyyymmddhhmmss(ubirthday), "gamestate-ubirthday", 14);
|
||||
Sfo_long(nhfp, &urealtime.realtime, "gamestate-realtime");
|
||||
Sfo_char(nhfp, yyyymmddhhmmss(urealtime.start_timing), "gamestate-start_timing", 14);
|
||||
|
||||
Reference in New Issue
Block a user