mirror of
https://github.com/RYDE-WORK/ballistica.git
synced 2026-01-26 17:03:14 +08:00
work on replay rewind
This commit is contained in:
parent
978f32f9f0
commit
5bd7e05773
@ -120,6 +120,7 @@ from _bascenev1 import (
|
||||
release_keyboard_input,
|
||||
reset_random_player_names,
|
||||
resume_replay,
|
||||
rewind_replay,
|
||||
broadcastmessage,
|
||||
SessionData,
|
||||
SessionPlayer,
|
||||
@ -400,6 +401,7 @@ __all__ = [
|
||||
'release_keyboard_input',
|
||||
'reset_random_player_names',
|
||||
'resume_replay',
|
||||
'rewind_replay',
|
||||
'safecolor',
|
||||
'screenmessage',
|
||||
'SceneV1AppMode',
|
||||
|
||||
@ -1568,6 +1568,34 @@ static PyMethodDef PyResumeReplayDef = {
|
||||
"Resumes replay.",
|
||||
};
|
||||
|
||||
// ------------------------ rewind_replay --------------------------------------
|
||||
|
||||
static auto PyRewindReplay(PyObject* self, PyObject* args) -> PyObject* {
|
||||
BA_PYTHON_TRY;
|
||||
auto* appmode = SceneV1AppMode::GetActiveOrThrow();
|
||||
auto* session =
|
||||
dynamic_cast<ClientSessionReplay*>(appmode->GetForegroundSession());
|
||||
if (session == nullptr) {
|
||||
throw Exception(
|
||||
"Attempting to rewind a replay not in replay session context.");
|
||||
}
|
||||
session->RestoreState();
|
||||
Py_RETURN_NONE;
|
||||
BA_PYTHON_CATCH;
|
||||
}
|
||||
|
||||
static PyMethodDef PyRewindReplayDef = {
|
||||
"rewind_replay", // name
|
||||
PyRewindReplay, // method
|
||||
METH_VARARGS, // flags
|
||||
|
||||
"rewind_replay() -> None\n"
|
||||
"\n"
|
||||
"(internal)\n"
|
||||
"\n"
|
||||
"Rewinds replay.",
|
||||
};
|
||||
|
||||
// ----------------------- reset_random_player_names ---------------------------
|
||||
|
||||
static auto PyResetRandomPlayerNames(PyObject* self, PyObject* args,
|
||||
@ -1846,6 +1874,7 @@ auto PythonMethodsScene::GetMethods() -> std::vector<PyMethodDef> {
|
||||
PySetReplaySpeedExponentDef,
|
||||
PyGetReplaySpeedExponentDef,
|
||||
PyIsReplayPausedDef,
|
||||
PyRewindReplayDef,
|
||||
PyPauseReplayDef,
|
||||
PyResumeReplayDef,
|
||||
PySetDebugSpeedExponentDef,
|
||||
|
||||
@ -134,6 +134,17 @@ void ClientSessionReplay::FetchMessages() {
|
||||
|
||||
// If we have no messages left, read from the file until we get some.
|
||||
while (commands().empty()) {
|
||||
{
|
||||
// Before we read next message, let's save our current state.
|
||||
SessionStream out(nullptr, false);
|
||||
DumpFullState(&out);
|
||||
|
||||
fflush(file_);
|
||||
current_state_.file_position_ = ftell(file_);
|
||||
current_state_.message_ = out.GetOutMessage();
|
||||
SaveState();
|
||||
}
|
||||
|
||||
std::vector<uint8_t> buffer;
|
||||
uint8_t len8;
|
||||
uint32_t len32;
|
||||
@ -265,4 +276,31 @@ void ClientSessionReplay::OnReset(bool rewind) {
|
||||
}
|
||||
}
|
||||
|
||||
void ClientSessionReplay::SaveState() { states_.push_back(current_state_); }
|
||||
|
||||
void ClientSessionReplay::RestoreState() {
|
||||
ScreenMessage("restoring state " + std::to_string(states_.size()));
|
||||
const int N = 500;
|
||||
|
||||
if (states_.size() <= N) {
|
||||
states_.clear();
|
||||
Reset(true);
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < N; ++i) {
|
||||
states_.pop_back();
|
||||
}
|
||||
|
||||
current_state_ = states_.back();
|
||||
RestoreFromCurrentState();
|
||||
}
|
||||
|
||||
void ClientSessionReplay::RestoreFromCurrentState() {
|
||||
// what to do with messages_fetch_num_? is it used somewhere at all?
|
||||
Reset(true);
|
||||
fseek(file_, current_state_.file_position_, SEEK_SET);
|
||||
HandleSessionMessage(current_state_.message_);
|
||||
}
|
||||
|
||||
} // namespace ballistica::scene_v1
|
||||
|
||||
@ -28,8 +28,24 @@ class ClientSessionReplay : public ClientSession,
|
||||
|
||||
void Error(const std::string& description) override;
|
||||
void FetchMessages() override;
|
||||
void SaveState();
|
||||
void RestoreState();
|
||||
|
||||
private:
|
||||
struct IntermediateState {
|
||||
// Message containing full scene state at the moment.
|
||||
std::vector<uint8_t> message_;
|
||||
|
||||
// A position in replay file where we should continue from.
|
||||
long file_position_;
|
||||
};
|
||||
|
||||
void RestoreFromCurrentState();
|
||||
|
||||
// List of passed states which we can rewind to.
|
||||
std::vector<IntermediateState> states_;
|
||||
IntermediateState current_state_;
|
||||
|
||||
uint32_t message_fetch_num_{};
|
||||
bool have_sent_client_message_{};
|
||||
std::vector<ConnectionToClient*> connections_to_clients_;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user