src/Aircraft/replay-internal.cxx: fix replay of some legacy normal recordings.
Flightgear 2020.3 releases use a different encoding for multiplayer information in Normal recordings (these are saved from in-memory recording data), which we failed to parse. This commit restores handling of this encoding, enabling replay of older recordings. Also when replaying in-memory recording, don't do background in-memory record of multiplayer information, because this gradually prunes the information that is being replayed.
This commit is contained in:
parent
b216658ba1
commit
2d53280fba
1 changed files with 67 additions and 26 deletions
|
@ -1077,9 +1077,12 @@ FGReplayInternal::update( double dt )
|
||||||
if (reset_time)
|
if (reset_time)
|
||||||
m_replay_master->setIntValue(replay_state);
|
m_replay_master->setIntValue(replay_state);
|
||||||
|
|
||||||
if (m_replay_multiplayer->getIntValue())
|
if (m_replay_multiplayer->getIntValue() && !m_continuous->m_in_time_to_frameinfo.empty())
|
||||||
{
|
{
|
||||||
// Carry on recording while replaying.
|
// Carry on recording while replaying a Continuous
|
||||||
|
// recording. We don't want to do this with a Normal recording
|
||||||
|
// because it will prune the short, medium and long-term
|
||||||
|
// buffers, which will degrade the replay experience.
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1111,7 +1114,13 @@ FGReplayInternal::update( double dt )
|
||||||
|
|
||||||
if (m_simple_time_enabled->getBoolValue())
|
if (m_simple_time_enabled->getBoolValue())
|
||||||
{
|
{
|
||||||
m_sim_time = globals->get_subsystem<TimeManager>()->getMPProtocolClockSec();
|
double new_sim_time = globals->get_subsystem<TimeManager>()->getMPProtocolClockSec();
|
||||||
|
SG_LOG( SG_GENERAL, SG_ALERT,
|
||||||
|
"m_sim_time=" << m_sim_time
|
||||||
|
<< " new_sim_time=" << new_sim_time <<
|
||||||
|
" new_sim_time <= m_sim_time=" << (new_sim_time <= m_sim_time)
|
||||||
|
);
|
||||||
|
m_sim_time = new_sim_time;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1306,7 +1315,8 @@ loadRawReplayData(
|
||||||
//FGFlightRecorder* pRecorder,
|
//FGFlightRecorder* pRecorder,
|
||||||
std::deque<FGReplayData*>& replay_data,
|
std::deque<FGReplayData*>& replay_data,
|
||||||
size_t record_size,
|
size_t record_size,
|
||||||
bool multiplayer
|
bool multiplayer,
|
||||||
|
bool multiplayer_legacy
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
|
@ -1325,7 +1335,7 @@ loadRawReplayData(
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
SG_LOG(SG_SYSTEMS, SG_DEBUG, "multiplayer=" << multiplayer << " record_size=" << record_size << " Type=" << Type << " ize=" << size);
|
SG_LOG(SG_SYSTEMS, SG_DEBUG, "multiplayer=" << multiplayer << " record_size=" << record_size << " Type=" << Type << " size=" << size);
|
||||||
|
|
||||||
// read the raw data
|
// read the raw data
|
||||||
size_t count = size / record_size;
|
size_t count = size / record_size;
|
||||||
|
@ -1343,25 +1353,46 @@ loadRawReplayData(
|
||||||
|
|
||||||
if (multiplayer)
|
if (multiplayer)
|
||||||
{
|
{
|
||||||
uint32_t length;
|
if (multiplayer_legacy)
|
||||||
readRaw(input, length);
|
|
||||||
uint32_t pos = 0;
|
|
||||||
for(;;)
|
|
||||||
{
|
{
|
||||||
if (pos == length) break;
|
SG_LOG(SG_SYSTEMS, SG_DEBUG, "reading Normal multiplayer recording with legacy format");
|
||||||
assert(pos < length);
|
size_t num_messages = 0;
|
||||||
uint16_t message_size;
|
input.read(reinterpret_cast<char*>(&num_messages), sizeof(num_messages));
|
||||||
readRaw(input, message_size);
|
for (size_t i=0; i<num_messages; ++i)
|
||||||
pos += sizeof(message_size) + message_size;
|
|
||||||
if (pos > length)
|
|
||||||
{
|
{
|
||||||
SG_LOG(SG_SYSTEMS, SG_ALERT, "Tape appears to have corrupted multiplayer data");
|
size_t message_size;
|
||||||
return false;
|
input.read(reinterpret_cast<char*>(&message_size), sizeof(message_size));
|
||||||
|
std::shared_ptr<std::vector<char>> message(new std::vector<char>(message_size));
|
||||||
|
input.read(&message->front(), message_size);
|
||||||
|
buffer->multiplayer_messages.push_back( message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SG_LOG(SG_SYSTEMS, SG_DEBUG, "reading Normal multiplayer recording");
|
||||||
|
uint32_t length;
|
||||||
|
readRaw(input, length);
|
||||||
|
uint32_t pos = 0;
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
if (pos == length) break;
|
||||||
|
assert(pos < length);
|
||||||
|
uint16_t message_size;
|
||||||
|
readRaw(input, message_size);
|
||||||
|
pos += sizeof(message_size) + message_size;
|
||||||
|
if (pos > length)
|
||||||
|
{
|
||||||
|
SG_LOG(SG_SYSTEMS, SG_ALERT, "Tape appears to have corrupted multiplayer data"
|
||||||
|
<< " length=" << length
|
||||||
|
<< " message_size=" << message_size
|
||||||
|
<< " pos=" << pos
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto message = std::make_shared<std::vector<char>>(message_size);
|
||||||
|
input.read(&message->front(), message_size);
|
||||||
|
buffer->multiplayer_messages.push_back( message);
|
||||||
}
|
}
|
||||||
auto message = std::make_shared<std::vector<char>>(message_size);
|
|
||||||
//std::shared_ptr<std::vector<char>> message(new std::vector<char>(message_size));
|
|
||||||
input.read(&message->front(), message_size);
|
|
||||||
buffer->multiplayer_messages.push_back( message);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1911,8 +1942,7 @@ FGReplayInternal::loadTape(
|
||||||
<< filename << ". Invalid meta data.");
|
<< filename << ". Invalid meta data.");
|
||||||
ok = false;
|
ok = false;
|
||||||
}
|
}
|
||||||
else
|
else if (type != ReplayContainer::MetaData)
|
||||||
if (type != ReplayContainer::MetaData)
|
|
||||||
{
|
{
|
||||||
SG_LOG(SG_SYSTEMS, SG_DEBUG, "Invalid header. Container type " << type);
|
SG_LOG(SG_SYSTEMS, SG_DEBUG, "Invalid header. Container type " << type);
|
||||||
SG_LOG(SG_SYSTEMS, SG_ALERT, "File not recognized. This is not a valid FlightGear flight recorder tape: "
|
SG_LOG(SG_SYSTEMS, SG_ALERT, "File not recognized. This is not a valid FlightGear flight recorder tape: "
|
||||||
|
@ -1921,6 +1951,7 @@ FGReplayInternal::loadTape(
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
SG_LOG(SG_SYSTEMS, SG_BULK, "meta_data is:\n" << meta_data);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
readProperties(meta_data, size-1, meta_data_props);
|
readProperties(meta_data, size-1, meta_data_props);
|
||||||
|
@ -1968,6 +1999,7 @@ FGReplayInternal::loadTape(
|
||||||
SGPropertyNode_ptr config = new SGPropertyNode();
|
SGPropertyNode_ptr config = new SGPropertyNode();
|
||||||
if (ok)
|
if (ok)
|
||||||
{
|
{
|
||||||
|
SG_LOG(SG_SYSTEMS, SG_BULK, "config_xml is:\n" << config_xml);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
readProperties(config_xml, size-1, config);
|
readProperties(config_xml, size-1, config);
|
||||||
|
@ -2011,6 +2043,7 @@ FGReplayInternal::loadTape(
|
||||||
}
|
}
|
||||||
|
|
||||||
bool multiplayer = false;
|
bool multiplayer = false;
|
||||||
|
bool multiplayer_legacy = false;
|
||||||
for (auto data: meta_meta.getChildren("data"))
|
for (auto data: meta_meta.getChildren("data"))
|
||||||
{
|
{
|
||||||
if (data->getStringValue() == "multiplayer")
|
if (data->getStringValue() == "multiplayer")
|
||||||
|
@ -2018,10 +2051,18 @@ FGReplayInternal::loadTape(
|
||||||
multiplayer = true;
|
multiplayer = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!multiplayer)
|
||||||
|
{
|
||||||
|
multiplayer_legacy = meta_meta.getBoolValue("multiplayer", 0);
|
||||||
|
if (multiplayer_legacy)
|
||||||
|
{
|
||||||
|
multiplayer = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
SG_LOG(SG_SYSTEMS, SG_ALERT, "multiplayer=" << multiplayer);
|
SG_LOG(SG_SYSTEMS, SG_ALERT, "multiplayer=" << multiplayer);
|
||||||
if (ok) ok = loadRawReplayData(input, m_short_term, record_size, multiplayer);
|
if (ok) ok = loadRawReplayData(input, m_short_term, record_size, multiplayer, multiplayer_legacy);
|
||||||
if (ok) ok = loadRawReplayData(input, m_medium_term, record_size, multiplayer);
|
if (ok) ok = loadRawReplayData(input, m_medium_term, record_size, multiplayer, multiplayer_legacy);
|
||||||
if (ok) ok = loadRawReplayData(input, m_long_term, record_size, multiplayer);
|
if (ok) ok = loadRawReplayData(input, m_long_term, record_size, multiplayer, multiplayer_legacy);
|
||||||
|
|
||||||
// restore replay messages
|
// restore replay messages
|
||||||
if (ok)
|
if (ok)
|
||||||
|
|
Loading…
Reference in a new issue