stk-code_catmod/src/network/rewind_info.cpp

117 lines
4.1 KiB
C++

//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2016 Joerg Henrichs
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "network/rewind_info.hpp"
#include "network/network_config.hpp"
#include "network/rewinder.hpp"
#include "network/rewind_manager.hpp"
#include "items/projectile_manager.hpp"
/** Constructor for a state: it only takes the size, and allocates a buffer
* for all state info.
* \param size Necessary buffer size for a state.
*/
RewindInfo::RewindInfo(int ticks, bool is_confirmed)
{
m_ticks = ticks;
m_is_confirmed = is_confirmed;
} // RewindInfo
// ----------------------------------------------------------------------------
/** Adjusts the time of this RewindInfo. This is only called on the server
* in case that an event is received in the past - in this case the server
* needs to avoid a Rewind by moving this event forward to the current time.
*/
void RewindInfo::setTicks(int ticks)
{
assert(NetworkConfig::get()->isServer());
assert(m_ticks < ticks);
m_ticks = ticks;
} // setTicks
// ============================================================================
RewindInfoState::RewindInfoState(int ticks, BareNetworkString *buffer,
bool is_confirmed)
: RewindInfo(ticks, is_confirmed)
{
m_rewinder_using = RewindManager::get()->getRewinderUsing();
m_buffer = buffer;
} // RewindInfoState
// ------------------------------------------------------------------------
/** Rewinds to this state. This is called while going forwards in time
* again to reach current time. It will call rewindToState().
* if the state is a confirmed state.
*/
void RewindInfoState::restore()
{
m_buffer->reset();
for (const std::string& name : m_rewinder_using)
{
const uint16_t data_size = m_buffer->getUInt16();
const unsigned current_offset_now = m_buffer->getCurrentOffset();
std::shared_ptr<Rewinder> r =
RewindManager::get()->getRewinder(name);
if (!r)
{
// For now we only need to get missing rewinder from
// projectile_manager
r = projectile_manager->addRewinderFromNetworkState(name);
}
if (!r)
{
Log::error("RewindInfoState", "Missing rewinder %s",
name.c_str());
m_buffer->skip(data_size);
continue;
}
try
{
r->restoreState(m_buffer, data_size);
}
catch (std::exception& e)
{
Log::error("RewindInfoState", "Restore state error: %s",
e.what());
m_buffer->reset();
m_buffer->skip(current_offset_now + data_size);
continue;
}
if (m_buffer->getCurrentOffset() - current_offset_now != data_size)
{
Log::error("RewindInfoState", "Wrong size read when restore "
"state, incompatible binary?");
m_buffer->reset();
m_buffer->skip(current_offset_now + data_size);
}
} // for all rewinder
} // restore
// ============================================================================
RewindInfoEvent::RewindInfoEvent(int ticks, EventRewinder *event_rewinder,
BareNetworkString *buffer, bool is_confirmed)
: RewindInfo(ticks, is_confirmed)
{
m_event_rewinder = event_rewinder;
m_buffer = buffer;
} // RewindInfoEvent