diff --git a/sources.cmake b/sources.cmake index dfc0e3774..5b3d0c21e 100644 --- a/sources.cmake +++ b/sources.cmake @@ -1,5 +1,5 @@ # Modify this file to change the last-modified date when you add/remove a file. -# This will then trigger a new cmake run automatically. +# This will then trigger a new cmake run automatically. file(GLOB_RECURSE STK_HEADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.hpp") file(GLOB_RECURSE STK_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.cpp") file(GLOB_RECURSE STK_SHADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "data/shaders/*") diff --git a/src/items/attachment.cpp b/src/items/attachment.cpp index 1521efb9d..6875f61b0 100644 --- a/src/items/attachment.cpp +++ b/src/items/attachment.cpp @@ -36,6 +36,7 @@ #include "karts/kart_properties.hpp" #include "modes/three_strikes_battle.hpp" #include "modes/world.hpp" +#include "network/rewind_manager.hpp" #include "physics/triangle_mesh.hpp" #include "tracks/track.hpp" #include "physics/triangle_mesh.hpp" @@ -45,6 +46,7 @@ /** Initialises the attachment each kart has. */ Attachment::Attachment(AbstractKart* kart) + : EventRewinder() { m_type = ATTACH_NOTHING; m_time_left = 0.0; @@ -182,6 +184,15 @@ void Attachment::set(AttachmentType type, float time, m_node->setVisible(true); irr_driver->applyObjectPassShader(m_node); + + // Save event about the new attachment + RewindManager *rwm = RewindManager::get(); + if(rwm->isEnabled() && !rwm->isRewinding()) + { + BareNetworkString *buffer = new BareNetworkString(2); + saveState(buffer); + rwm->addEvent(this, buffer); + } } // set // ----------------------------------------------------------------------------- @@ -276,6 +287,15 @@ void Attachment::rewindTo(BareNetworkString *buffer) } set(new_type, time_left, m_previous_owner); } // rewindTo +// ----------------------------------------------------------------------------- +/** Called when going forwards in time during a rewind. + * \param buffer Buffer with the rewind information. + */ +void Attachment::rewind(BareNetworkString *buffer) +{ + // Event has same info as a state, so re-use the restore function + rewindTo(buffer); +} // rewind // ----------------------------------------------------------------------------- /** Randomly selects the new attachment. For a server process, the diff --git a/src/items/attachment.hpp b/src/items/attachment.hpp index 2d1a06149..4f0d5243f 100644 --- a/src/items/attachment.hpp +++ b/src/items/attachment.hpp @@ -21,6 +21,7 @@ #include "config/stk_config.hpp" #include "items/attachment_plugin.hpp" +#include "network/event_rewinder.hpp" #include "utils/no_copy.hpp" #include "utils/random_generator.hpp" @@ -45,7 +46,8 @@ class SFXBase; * a scene node). * \ingroup items */ -class Attachment: public NoCopy, public scene::IAnimationEndCallBack +class Attachment: public NoCopy, public scene::IAnimationEndCallBack, + public EventRewinder { public: // Some loop in attachment.cpp depend on ATTACH_FIRST and ATTACH_MAX. @@ -114,6 +116,7 @@ public: void handleCollisionWithKart(AbstractKart *other); void set (AttachmentType type, float time, AbstractKart *previous_kart=NULL); + virtual void rewind(BareNetworkString *buffer); void rewindTo(BareNetworkString *buffer); void saveState(BareNetworkString *buffer); @@ -142,6 +145,10 @@ public: // ------------------------------------------------------------------------ /** Implement IAnimatedMeshSceneNode */ virtual void OnAnimationEnd(scene::IAnimatedMeshSceneNode* node); + // ------------------------------------------------------------------------ + /** Nothing to undo when going back during a rewind, the full state info + * will take care of creating the right attachment. */ + virtual void undo(BareNetworkString *buffer) { } }; // Attachment #endif diff --git a/src/items/item.hpp b/src/items/item.hpp index 4ed941ad4..f96ac821d 100644 --- a/src/items/item.hpp +++ b/src/items/item.hpp @@ -25,11 +25,6 @@ * Defines the various collectibles and weapons of STK. */ -namespace irr -{ - namespace scene { class IMesh; class ISceneNode; } -} -using namespace irr; #include "utils/leak_check.hpp" #include "utils/no_copy.hpp" @@ -38,8 +33,14 @@ using namespace irr; #include class AbstractKart; -class LODNode; class Item; +class LODNode; + +namespace irr +{ + namespace scene { class IMesh; class ISceneNode; } +} +using namespace irr; // ----------------------------------------------------------------------------- diff --git a/src/karts/kart_rewinder.cpp b/src/karts/kart_rewinder.cpp index 52ead37d2..7ea2d6993 100644 --- a/src/karts/kart_rewinder.cpp +++ b/src/karts/kart_rewinder.cpp @@ -37,7 +37,6 @@ KartRewinder::KartRewinder(AbstractKart *kart) : Rewinder(/*can_be_destroyed*/ f */ void KartRewinder::reset() { - m_previous_attachment = m_kart->getAttachment()->getType(); m_previous_control = m_kart->getControls(); } // reset @@ -120,10 +119,7 @@ void KartRewinder::update() // Check if an event has happened that needs to be recorded bool control_event = !(m_kart->getControls() == m_previous_control); - bool attach_event = m_kart->getAttachment()->getType() - != m_previous_attachment; - uint8_t type = (control_event ? EVENT_CONTROL : 0) | - (attach_event ? EVENT_ATTACH : 0) ; + uint8_t type = (control_event ? EVENT_CONTROL : 0); if(type == 0) return; // no event @@ -136,14 +132,8 @@ void KartRewinder::update() m_previous_control = m_kart->getControls(); m_previous_control.copyToBuffer(buffer); } - if(attach_event) - { - m_kart->getAttachment()->saveState(buffer); - m_previous_attachment = m_kart->getAttachment()->getType(); - - } // The rewind manager will free the memory once it's not needed anymore - RewindManager::get()->addEvent(this, buffer); + //XXXXXXXXXXXXXXX RewindManager::get()->addEvent(this, buffer); } // update // ---------------------------------------------------------------------------- @@ -153,8 +143,6 @@ void KartRewinder::rewindToEvent(BareNetworkString *buffer) uint8_t type = buffer->getUInt8(); if(type & EVENT_CONTROL) m_kart->getControls().setFromBuffer(buffer); - if(type & EVENT_ATTACH) - m_kart->getAttachment()->rewindTo(buffer); }; // rewindToEvent diff --git a/src/karts/kart_rewinder.hpp b/src/karts/kart_rewinder.hpp index 9f1d665dd..adab48939 100644 --- a/src/karts/kart_rewinder.hpp +++ b/src/karts/kart_rewinder.hpp @@ -19,7 +19,6 @@ #ifndef HEADER_KART_REWINDER_HPP #define HEADER_KART_REWINDER_HPP -#include "items/attachment.hpp" #include "karts/controller/kart_control.hpp" #include "network/rewinder.hpp" @@ -38,10 +37,6 @@ private: * needs to be created. */ KartControl m_previous_control; - /** The previous attachment type, used to detect if a new event - * needs to be created. */ - Attachment::AttachmentType m_previous_attachment; - // Flags to indicate the different event types enum { EVENT_CONTROL = 0x01, EVENT_ATTACH = 0x02 }; diff --git a/src/network/event_rewinder.cpp b/src/network/event_rewinder.cpp new file mode 100644 index 000000000..5f0ea8475 --- /dev/null +++ b/src/network/event_rewinder.cpp @@ -0,0 +1,35 @@ +// +// 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/event_rewinder.hpp" + +#include "network/rewind_manager.hpp" + +/** Constructor. It will add this object to the list of all rewindable + * objects in the rewind manager. + */ +EventRewinder::EventRewinder() +{ +} // Rewinder + +// ---------------------------------------------------------------------------- +/** Destructor. + */ +EventRewinder::~EventRewinder() +{ +} // ~EventRewinder diff --git a/src/network/event_rewinder.hpp b/src/network/event_rewinder.hpp new file mode 100644 index 000000000..1df4a8edc --- /dev/null +++ b/src/network/event_rewinder.hpp @@ -0,0 +1,41 @@ +// +// 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. + +#ifndef HEADER_EVENT_REWINDER_HPP +#define HEADER_EVENT_REWINDER_HPP + +class BareNetworkString; + +class EventRewinder +{ +public: + EventRewinder(); + virtual ~EventRewinder(); + + /** Called when an event needs to be undone. This is called while going + * backwards for rewinding - all stored events will get an 'undo' call. + */ + virtual void undo(BareNetworkString *buffer) = 0; + + /** Called when an event needs to be replayed. This is called during + * rewind, i.e. when going forward in time again. + */ + virtual void rewind(BareNetworkString *buffer) = 0; +}; // EventRewinder +#endif + diff --git a/src/network/rewind_info.cpp b/src/network/rewind_info.cpp index 81668305a..4340f2457 100644 --- a/src/network/rewind_info.cpp +++ b/src/network/rewind_info.cpp @@ -47,9 +47,11 @@ RewindInfoState::RewindInfoState(float time, Rewinder *rewinder, } // RewindInfoState // ============================================================================ -RewindInfoEvent::RewindInfoEvent(float time, Rewinder *rewinder, +RewindInfoEvent::RewindInfoEvent(float time, EventRewinder *event_rewinder, BareNetworkString *buffer, bool is_confirmed) - : RewindInfoRewinder(time, rewinder, buffer, is_confirmed) + : RewindInfo(time, is_confirmed) { + m_event_rewinder = event_rewinder; + m_buffer = buffer; } // RewindInfoEvent diff --git a/src/network/rewind_info.hpp b/src/network/rewind_info.hpp index e2ff2a9ac..de4b033e3 100644 --- a/src/network/rewind_info.hpp +++ b/src/network/rewind_info.hpp @@ -19,6 +19,7 @@ #ifndef HEADER_REWIND_INFO_HPP #define HEADER_REWIND_INFO_HPP +#include "network/event_rewinder.hpp" #include "network/network_string.hpp" #include "network/rewinder.hpp" #include "utils/leak_check.hpp" @@ -156,7 +157,7 @@ public: virtual void undo() { m_rewinder->undoState(getBuffer()); - } // undoEvent + } // undo // ------------------------------------------------------------------------ /** Rewinds to this state. This is called while going forwards in time * again to reach current time. It will call rewindToState(). @@ -174,10 +175,16 @@ public: }; // class RewindInfoState // ============================================================================ -class RewindInfoEvent : public RewindInfoRewinder +class RewindInfoEvent : public RewindInfo { +private: + /** Pointer to the event rewinder responsible for this event. */ + EventRewinder *m_event_rewinder; + + /** Buffer with the event data. */ + BareNetworkString *m_buffer; public: - RewindInfoEvent(float time, Rewinder *rewinder, + RewindInfoEvent(float time, EventRewinder *event_rewinder, BareNetworkString *buffer, bool is_confirmed); virtual ~RewindInfoEvent() {} @@ -185,10 +192,10 @@ public: virtual bool isEvent() const { return true; } // ------------------------------------------------------------------------ /** Called when going back in time to undo any rewind information. - * It calls undoEvent in the rewinder. */ + * It calls undoEvent in the rewinder. */ virtual void undo() { - m_rewinder->undoEvent(getBuffer()); + m_event_rewinder->undo(m_buffer); } // undo // ------------------------------------------------------------------------ /** This is called while going forwards in time again to reach current @@ -196,8 +203,13 @@ public: */ virtual void rewind() { - m_rewinder->rewindToEvent(getBuffer()); + // Make sure to reset the buffer so we read from the beginning + m_buffer->reset(); + m_event_rewinder->rewind(getBuffer()); } // rewind + // ------------------------------------------------------------------------ + /** Returns the buffer with the event information in it. */ + BareNetworkString *getBuffer() { return m_buffer; } }; // class RewindIndoEvent #endif diff --git a/src/network/rewind_manager.cpp b/src/network/rewind_manager.cpp index 60ce3922b..befd0b694 100644 --- a/src/network/rewind_manager.cpp +++ b/src/network/rewind_manager.cpp @@ -210,11 +210,17 @@ unsigned int RewindManager::findFirstIndex(float target_time) const * \param time Time at which the event was recorded. * \param buffer Pointer to the event data. */ -void RewindManager::addEvent(Rewinder *rewinder, BareNetworkString *buffer) +void RewindManager::addEvent(EventRewinder *event_rewinder, + BareNetworkString *buffer) { - if(m_is_rewinding) return; - RewindInfo *ri = new RewindInfoEvent(getCurrentTime(), rewinder, - buffer, /*is_confirmed*/true ); + if(m_is_rewinding) + { + delete buffer; + Log::error("RewindManager", "Adding event when rewinding"); + return; + } + RewindInfo *ri = new RewindInfoEvent(getCurrentTime(), event_rewinder, + buffer, /*is confirmed*/true); insertRewindInfo(ri); } // addEvent diff --git a/src/network/rewind_manager.hpp b/src/network/rewind_manager.hpp index 0097830f1..653072e47 100644 --- a/src/network/rewind_manager.hpp +++ b/src/network/rewind_manager.hpp @@ -26,6 +26,7 @@ #include class RewindInfo; +class EventRewinder; /** \ingroup network * This class manages rewinding. It keeps track of: @@ -172,7 +173,7 @@ public: void reset(); void saveStates(); void rewindTo(float target_time); - void addEvent(Rewinder *rewinder, BareNetworkString *buffer); + void addEvent(EventRewinder *event_rewinder, BareNetworkString *buffer); // ------------------------------------------------------------------------ /** Adds a Rewinder to the list of all rewinders. * \return true If rewinding is enabled, false otherwise.