X-Git-Url: https://git.artsoft.org/?p=rocksndiamonds.git;a=blobdiff_plain;f=src%2Ftape.c;h=f16e7ec9451a20ab68068add00155ed01870088a;hp=f5d78c6a8cb14e5e2710780501538b73e35445af;hb=HEAD;hpb=2ca6dedc8eb88f6d00eb3eaab129e655ae2e035f diff --git a/src/tape.c b/src/tape.c index f5d78c6a..f16e7ec9 100644 --- a/src/tape.c +++ b/src/tape.c @@ -18,6 +18,8 @@ #include "files.h" #include "network.h" #include "anim.h" +#include "api.h" + #define DEBUG_TAPE_WHEN_PLAYING FALSE @@ -662,6 +664,7 @@ void TapeErase(void) tape.level_nr = level_nr; tape.pos[tape.counter].delay = 0; tape.changed = TRUE; + tape.solved = FALSE; tape.random_seed = InitRND(level.random_seed); @@ -758,6 +761,7 @@ static void TapeAppendRecording(void) // start recording tape.recording = TRUE; tape.changed = TRUE; + tape.solved = FALSE; // set current delay (for last played move) tape.pos[tape.counter].delay = tape.delay_played; @@ -775,7 +779,9 @@ static void TapeAppendRecording(void) void TapeHaltRecording(void) { - tape.counter++; + // only advance tape counter if any input events have been recorded + if (tape.pos[tape.counter].delay > 0) + tape.counter++; // initialize delay for next tape entry (to be able to continue recording) if (tape.counter < MAX_TAPE_LEN) @@ -830,6 +836,8 @@ boolean TapeAddAction(byte action[MAX_TAPE_ACTIONS]) tape.pos[tape.counter].delay++; } + tape.changed = TRUE; + return TRUE; } @@ -928,6 +936,10 @@ void TapeTogglePause(boolean toggle_mode) ModifyPauseButtons(); } + + // stop tape when leaving auto-pause after completely replaying tape + if (tape.playing && !tape.pausing && tape.counter >= tape.length) + TapeStop(); } void TapeStartPlaying(void) @@ -985,21 +997,27 @@ byte *TapePlayAction(void) if (tape.pause_before_end) // stop some seconds before end of tape { - if (TapeTime > tape.length_seconds - TAPE_PAUSE_SECONDS_BEFORE_DEATH) + if (TapeTime > (int)tape.length_seconds - TAPE_PAUSE_SECONDS_BEFORE_DEATH) { TapeStopWarpForward(); TapeTogglePause(TAPE_TOGGLE_MANUAL); + if (setup.autorecord_after_replay) + TapeAppendRecording(); + return NULL; } } if (tape.counter >= tape.length) // end of tape reached { - if (tape.warp_forward && !tape.auto_play) + if (!tape.auto_play) { TapeStopWarpForward(); TapeTogglePause(TAPE_TOGGLE_MANUAL); + + if (setup.autorecord_after_replay) + TapeAppendRecording(); } else { @@ -1088,6 +1106,27 @@ void TapeStop(void) } } +static void TapeStopGameOrTape(boolean stop_game) +{ + if (score_info_tape_play || (!tape.playing && stop_game)) + RequestQuitGame(FALSE); + else + TapeStop(); +} + +void TapeStopGame(void) +{ + if (game_status == GAME_MODE_MAIN) + return; + + TapeStopGameOrTape(TRUE); +} + +void TapeStopTape(void) +{ + TapeStopGameOrTape(FALSE); +} + unsigned int GetTapeLengthFrames(void) { unsigned int tape_length_frames = 0; @@ -1154,22 +1193,25 @@ static void TapeSingleStep(void) void TapeQuickSave(void) { - if (game_status == GAME_MODE_MAIN) + if (game_status != GAME_MODE_PLAYING) { - Request("No game that can be saved!", REQ_CONFIRM); + Request("No game that could be saved!", REQ_CONFIRM); return; } - if (game_status != GAME_MODE_PLAYING) + if (!tape.recording) + { + Request("No recording that could be saved!", REQ_CONFIRM); + return; + } - if (tape.recording) - TapeHaltRecording(); // prepare tape for saving on-the-fly + TapeHaltRecording(); // prepare tape for saving on-the-fly if (TAPE_IS_EMPTY(tape)) { - Request("No tape that can be saved!", REQ_CONFIRM); + Request("No tape that could be saved!", REQ_CONFIRM); return; } @@ -1244,6 +1286,69 @@ void TapeQuickLoad(void) } } +static boolean checkRestartGame(char *message) +{ + if (game_status == GAME_MODE_MAIN) + return TRUE; + + if (!hasStartedNetworkGame()) + return FALSE; + + if (level_editor_test_game) + return TRUE; + + if (game.all_players_gone) + return TRUE; + + if (!setup.ask_on_quit_game) + return TRUE; + + if (Request(message, REQ_ASK | REQ_STAY_CLOSED)) + return TRUE; + + OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK); + + return FALSE; +} + +void TapeRestartGame(void) +{ + if (score_info_tape_play) + { + TapeStartGamePlaying(); + + return; + } + + if (!checkRestartGame("Restart game?")) + return; + + StartGameActions(network.enabled, setup.autorecord, level.random_seed); +} + +void TapeReplayAndPauseBeforeEnd(void) +{ + if (score_info_tape_play) + return; + + if (TAPE_IS_EMPTY(tape) && !tape.recording) + { + Request("No tape for this level!", REQ_CONFIRM); + + return; + } + + if (!checkRestartGame("Replay game and pause before end?")) + return; + + TapeStop(); + TapeStartGamePlaying(); + TapeStartWarpForward(AUTOPLAY_MODE_WARP_NO_DISPLAY); + + tape.pause_before_end = TRUE; + tape.quick_resume = TRUE; +} + boolean hasSolutionTape(void) { boolean tape_file_exists = fileExists(getSolutionTapeFilename(level_nr)); @@ -1292,6 +1397,93 @@ boolean PlaySolutionTape(void) return TRUE; } +static boolean PlayScoreTape_WaitForDownload(void) +{ + DelayCounter download_delay = { 10000 }; + + ResetDelayCounter(&download_delay); + + // wait for score tape to be successfully downloaded (and fail on timeout) + while (!server_scores.tape_downloaded) + { + if (DelayReached(&download_delay)) + return FALSE; + + UPDATE_BUSY_STATE_NOT_LOADING(); + + Delay(20); + } + + return TRUE; +} + +boolean PlayScoreTape(int entry_nr) +{ + struct ScoreEntry *entry = &scores.entry[entry_nr]; + char *tape_filename = + (entry->id == -1 ? + getScoreTapeFilename(entry->tape_basename, level_nr) : + getScoreCacheTapeFilename(entry->tape_basename, level_nr)); + boolean download_tape = (!fileExists(tape_filename)); + + if (download_tape && entry->id == -1) + { + FadeSkipNextFadeIn(); + + Request("Cannot find score tape!", REQ_CONFIRM); + + return FALSE; + } + + server_scores.tape_downloaded = FALSE; + + if (download_tape) + ApiGetScoreTapeAsThread(level_nr, entry->id, entry->tape_basename); + + SetGameStatus(GAME_MODE_PLAYING); + + FadeOut(REDRAW_FIELD); + + if (download_tape && !PlayScoreTape_WaitForDownload()) + { + SetGameStatus(GAME_MODE_SCOREINFO); + ClearField(); + + Request("Cannot download score tape from score server!", REQ_CONFIRM); + + return FALSE; + } + + if (!TAPE_IS_STOPPED(tape)) + TapeStop(); + + // if tape recorder already contains a tape, remove it without asking + TapeErase(); + + if (entry->id == -1) + LoadScoreTape(entry->tape_basename, level_nr); + else + LoadScoreCacheTape(entry->tape_basename, level_nr); + + if (TAPE_IS_EMPTY(tape)) + { + SetGameStatus(GAME_MODE_SCOREINFO); + ClearField(); + + Request("Cannot load score tape for this level!", REQ_CONFIRM); + + return FALSE; + } + + FadeSkipNextFadeOut(); + + TapeStartGamePlaying(); + + score_info_tape_play = TRUE; + + return TRUE; +} + static boolean checkTapesFromSameLevel(struct TapeInfo *t1, struct TapeInfo *t2) { return (strEqual(t1->level_identifier, t2->level_identifier) && @@ -1381,8 +1573,10 @@ static TreeInfo *getFirstValidAutoPlayEntry(TreeInfo *node) static void AutoPlayTapes_SetScoreEntry(int score, int time) { + char *name = (options.mytapes ? setup.player_name : options.player_name); + // set unique basename for score tape (for uploading to score server) - strcpy(tape.score_tape_basename, getScoreTapeBasename(setup.player_name)); + strcpy(tape.score_tape_basename, getScoreTapeBasename(name)); // store score in first score entry scores.last_added = 0; @@ -1400,22 +1594,24 @@ static void AutoPlayTapes_SetScoreEntry(int score, int time) server_scores.uploaded = FALSE; } -static void AutoPlayTapes_WaitForUpload(void) +static boolean AutoPlayTapes_WaitForUpload(void) { - unsigned int upload_delay = 0; - unsigned int upload_delay_value = 10000; + DelayCounter upload_delay = { 10000 }; ResetDelayCounter(&upload_delay); // wait for score tape to be successfully uploaded (and fail on timeout) while (!server_scores.uploaded) { - if (DelayReached(&upload_delay, upload_delay_value)) + if (DelayReached(&upload_delay)) { PrintNoLog("\r"); Print("- uploading score tape to score server - TIMEOUT.\n"); - Fail("cannot upload score tape to score server"); + if (program.headless) + Fail("cannot upload score tape to score server"); + + return FALSE; } UPDATE_BUSY_STATE(); @@ -1425,6 +1621,8 @@ static void AutoPlayTapes_WaitForUpload(void) PrintNoLog("\r"); Print("- uploading score tape to score server - uploaded.\n"); + + return TRUE; } static int AutoPlayTapesExt(boolean initialize) @@ -1535,7 +1733,7 @@ static int AutoPlayTapesExt(boolean initialize) // * solution tape may have native format (like Supaplex solution files) SaveScoreTape(level_nr); - SaveServerScore(level_nr); + SaveServerScore(level_nr, TRUE); AutoPlayTapes_WaitForUpload(); } @@ -1607,6 +1805,7 @@ static int AutoPlayTapesExt(boolean initialize) global.autoplay_level[tape.level_nr] = TRUE; global.autoplay_all = FALSE; + options.mytapes = FALSE; } if (autoplay.all_levelsets) @@ -1662,6 +1861,41 @@ static int AutoPlayTapesExt(boolean initialize) init_level_set = FALSE; } + if (autoplay.all_levelsets && global.autoplay_mode == AUTOPLAY_MODE_UPLOAD) + { + boolean skip_levelset = FALSE; + + if (!directoryExists(getTapeDir(autoplay.leveldir->subdir))) + { + Print("No tape directory for this level set found -- skipping.\n"); + + skip_levelset = TRUE; + } + + if (CheckTapeDirectoryUploadsComplete(autoplay.leveldir->subdir)) + { + Print("All tapes for this level set already uploaded -- skipping.\n"); + + skip_levelset = TRUE; + } + + if (skip_levelset) + { + PrintTapeReplaySummary(&autoplay); + + // continue with next level set + autoplay.leveldir = getNextValidAutoPlayEntry(autoplay.leveldir); + + // all level sets processed + if (autoplay.leveldir == NULL) + break; + + init_level_set = TRUE; + + continue; + } + } + if (global.autoplay_mode != AUTOPLAY_MODE_FIX || patch_nr == 0) level_nr = autoplay.level_nr++; @@ -1675,6 +1909,9 @@ static int AutoPlayTapesExt(boolean initialize) if (!autoplay.all_levelsets) break; + if (global.autoplay_mode == AUTOPLAY_MODE_UPLOAD) + MarkTapeDirectoryUploadsAsComplete(autoplay.leveldir->subdir); + // continue with next level set autoplay.leveldir = getNextValidAutoPlayEntry(autoplay.leveldir); @@ -1696,17 +1933,14 @@ static int AutoPlayTapesExt(boolean initialize) if (!global.autoplay_all && !global.autoplay_level[level_nr]) continue; - if (global.autoplay_mode == AUTOPLAY_MODE_UPLOAD) + // speed things up in case of missing private tapes (skip loading level) + if (options.mytapes && !fileExists(getTapeFilename(level_nr))) { - // speed things up when uploading all existing private tapes - if (autoplay.all_levelsets && !fileExists(getTapeFilename(level_nr))) - { - autoplay.num_tape_missing++; + autoplay.num_tape_missing++; - Print("Tape %03d: (no tape found)\n", level_nr); + Print("Tape %03d: (no tape found)\n", level_nr); - continue; - } + continue; } TapeErase(); @@ -1826,9 +2060,9 @@ static int AutoPlayTapesExt(boolean initialize) } } - SaveServerScoreFromFile(level_nr, autoplay.tape_filename); + SaveServerScoreFromFile(level_nr, TRUE, autoplay.tape_filename); - AutoPlayTapes_WaitForUpload(); + boolean success = AutoPlayTapes_WaitForUpload(); if (use_temporary_tape_file) unlink(autoplay.tape_filename); @@ -1836,6 +2070,13 @@ static int AutoPlayTapesExt(boolean initialize) // required for uploading multiple tapes autoplay.tape_filename = NULL; + if (!success) + { + num_tapes = -num_tapes; + + break; + } + continue; } @@ -1856,14 +2097,20 @@ static int AutoPlayTapesExt(boolean initialize) { Print("\n"); PrintLine("=", 79); - Print("SUMMARY: %d tapes uploaded.\n", num_tapes); + + if (num_tapes >= 0) + Print("SUMMARY: %d tapes uploaded.\n", num_tapes); + else + Print("SUMMARY: Uploading tapes failed.\n"); + PrintLine("=", 79); } // clear timestamp for batch tape upload (required after interactive upload) global.autoplay_time = 0; - if (program.headless) + // exit if running headless or if visually auto-playing tapes + if (program.headless || global.autoplay_mode != AUTOPLAY_MODE_UPLOAD) CloseAllAndExit(0); // when running interactively, restore last selected level set and number @@ -2284,7 +2531,7 @@ static void HandleTapeButtonsExt(int id) break; case TAPE_CTRL_ID_STOP: - TapeStop(); + TapeStopTape(); break;