1
0
Fork 0

If multiplayer record is enabled, carry on recording while replaying.

This background recording keeps the user aircraft stationary while recording
all movements of multiplayer aircraft. Allows one to look at replay without,
for example, disturbing continuous record to file.
This commit is contained in:
Julian Smith 2020-06-14 02:18:08 +01:00
parent 15915b5a79
commit 001c1d231d
4 changed files with 143 additions and 81 deletions

View file

@ -325,8 +325,29 @@ FGFlightRecorder::capture(double SimTime, FGReplayData* ReplayData)
if (!ReplayData)
return NULL;
}
int Offset = 0;
// When replaying, we are able to carry recording live multiplayer
// information. To make this work we need to record a stationay
// user aircraft, with information from the last live user aircraft
// FGReplayData. So we store the last live user aircraft information in
// this static vector.
//
static std::vector<char> s_recent_raw_data;
int in_replay = fgGetInt("/sim/replay/replay-state");
ReplayData->sim_time = SimTime;
if (in_replay) {
// Record the fixed position of live user aircraft at the point at
// which we started replay.
//
ReplayData->raw_data = s_recent_raw_data;
}
else {
// Find live information about the user aircraft.
//
int Offset = 0;
ReplayData->raw_data.resize( m_TotalRecordSize);
char* pBuffer = &ReplayData->raw_data.front();
@ -405,6 +426,12 @@ FGFlightRecorder::capture(double SimTime, FGReplayData* ReplayData)
assert(Offset + sizeof(double) == m_TotalRecordSize);
// Update s_recent_raw_data so that we will be able to carry recording
// while replaying.
//
s_recent_raw_data = ReplayData->raw_data;
}
// If m_ReplayMultiplayer is true, move all recent
// multiplayer messages from m_MultiplayMgr into
// ReplayData->multiplayer_messages. Otherwise clear m_MultiplayMgr's
@ -423,6 +450,15 @@ FGFlightRecorder::capture(double SimTime, FGReplayData* ReplayData)
}
ReplayData->UpdateStats();
// Note that if we are replaying, <ReplayData> will contain the last live
// position of the live user aircraft, plus any multiplayer packets that
// have arrived recently. If there were no recent multiplayer packets,
// then there's no actually no need to record anything (unless we're at the
// start of recording).
//
// But for now at least, we don't try to optimise the recording like that.
//
return ReplayData;
}

View file

@ -301,6 +301,7 @@ FGReplay::init()
replay_looped = fgGetNode("/sim/replay/looped", true);
replay_duration_act = fgGetNode("/sim/replay/duration-act", true);
speed_up = fgGetNode("/sim/speed-up", true);
replay_multiplayer = fgGetNode("/sim/replay/multiplayer", true);
// alias to keep backward compatibility
fgGetNode("/sim/freeze/replay-state", true)->alias(replay_master);
@ -724,10 +725,24 @@ FGReplay::update( double dt )
if (ResetTime)
replay_master->setIntValue(replay_state);
return; // don't record the replay session
if (replay_multiplayer->getIntValue()) {
// Carry on recording while replaying.
break;
}
else {
// Don't record while replaying.
return;
}
}
case 2: // normal replay operation
return; // don't record the replay session
if (replay_multiplayer->getIntValue()) {
// Carry on recording while replaying.
break;
}
else {
// Don't record while replaying.
return;
}
default:
throw sg_range_exception("unknown FGReplay state");
}
@ -749,6 +764,9 @@ FGReplay::update( double dt )
sim_time = new_sim_time;
}
// We still record even if we are replaying, if /sim/replay/multiplayer is
// true.
//
FGReplayData* r = record(sim_time);
if (!r)
{

View file

@ -151,6 +151,7 @@ private:
SGPropertyNode_ptr replay_looped;
SGPropertyNode_ptr replay_duration_act;
SGPropertyNode_ptr speed_up;
SGPropertyNode_ptr replay_multiplayer;
double replay_time_prev; // Used to detect jumps while replaying.
double m_high_res_time; // default: 60 secs of high res data

View file

@ -1765,21 +1765,28 @@ int FGMultiplayMgr::GetMsg(MsgBuf& msgBuf, simgear::IPAddress& SenderAddress)
for(;;) {
if (mReplayMessageQueue.empty()) {
// No recorded messages available, so look for chat messages
// only from <mSocket>.
// No recorded messages available, so look for live messages
// from <mSocket>.
//
int RecvStatus = GetMsgNetwork(msgBuf, SenderAddress);
if (RecvStatus == 0) {
// No recorded messages, and no live messages, so return 0.
return 0;
}
// Always record all messages.
//
std::shared_ptr<std::vector<char>> data( new std::vector<char>(RecvStatus));
memcpy( &data->front(), msgBuf.Msg, RecvStatus);
mRecordMessageQueue.push_back(data);
if (msgBuf.Header.MsgId == CHAT_MSG_ID) {
return RecvStatus;
}
// If we get here, there is a live message but it is a
// multiplayer aircraft position so we ignore it while
// replaying.
//
}
else {
// Replay recorded message, unless it is a chat message.
@ -1789,7 +1796,7 @@ int FGMultiplayMgr::GetMsg(MsgBuf& msgBuf, simgear::IPAddress& SenderAddress)
assert(replayMessage->size() <= sizeof(msgBuf));
int length = replayMessage->size();
memcpy(&msgBuf.Msg, &replayMessage->front(), length);
// Don't return chat messages.
// Don't return recorded chat messages.
if (msgBuf.Header.MsgId != CHAT_MSG_ID) {
SG_LOG(SG_NETWORK, SG_INFO,
"replaying message length=" << replayMessage->size()