diff --git a/src/items/flyable.cpp b/src/items/flyable.cpp index 0c8ef09e0..aeee03927 100644 --- a/src/items/flyable.cpp +++ b/src/items/flyable.cpp @@ -689,7 +689,19 @@ void Flyable::restoreState(BareNetworkString *buffer, int count) { // At the moment we only have cannon animation for rubber ball if (!m_animation) - setAnimation(new CannonAnimation(this, buffer)); + { + try + { + CannonAnimation* ca = new CannonAnimation(this, buffer); + setAnimation(ca); + } + catch (const KartAnimationCreationException& kace) + { + Log::error("Flyable", "Kart animation creation error: %s", + kace.what()); + buffer->skip(kace.getSkippingOffset()); + } + } else m_animation->restoreState(buffer); } diff --git a/src/karts/abstract_kart_animation.hpp b/src/karts/abstract_kart_animation.hpp index 262971098..fea5c42f0 100644 --- a/src/karts/abstract_kart_animation.hpp +++ b/src/karts/abstract_kart_animation.hpp @@ -25,6 +25,7 @@ #include "utils/no_copy.hpp" #include "utils/vec3.hpp" +#include #include #include @@ -38,6 +39,14 @@ enum KartAnimationType : uint8_t KAT_CANNON = 2 }; +/** Exception for kart animation creation in networking, so if thrown it will + * tell the num of bytes skipping in the game state. */ +class KartAnimationCreationException : public std::exception +{ +public: + virtual int getSkippingOffset() const = 0; +}; + /** The base class for all kart animation, like rescue, explosion, or cannon. * Kart animations are done by removing the physics body from the physics * world, and instead modifying the rotation and position of the kart diff --git a/src/karts/cannon_animation.cpp b/src/karts/cannon_animation.cpp index 5d516181e..a160276db 100644 --- a/src/karts/cannon_animation.cpp +++ b/src/karts/cannon_animation.cpp @@ -380,18 +380,36 @@ void CannonAnimation::restoreState(BareNetworkString* buffer) // ---------------------------------------------------------------------------- void CannonAnimation::restoreData(BareNetworkString* buffer) { + // Kart cannon has 2 floats + 1 compressed quaternion + // Flyable has 1 float (delta) + const int skipping_offset = m_kart ? 12 : 4; + class CannonCreationException : public KartAnimationCreationException + { + private: + const std::string m_error; + + const int m_skipping_offset; + public: + CannonCreationException(const std::string& error, int skipping_offset) + : m_error(error), m_skipping_offset(skipping_offset) {} + // -------------------------------------------------------------------- + virtual int getSkippingOffset() const { return m_skipping_offset; } + // -------------------------------------------------------------------- + virtual const char* what() const throw() { return m_error.c_str(); } + }; + int cc_idx = buffer->getInt8(); if ((unsigned)cc_idx > CheckManager::get()->getCheckStructureCount()) { - throw std::invalid_argument( - "Server has different check structure size."); + throw CannonCreationException( + "Server has different check structure size.", skipping_offset); } CheckCannon* cc = dynamic_cast (CheckManager::get()->getCheckStructure(cc_idx)); if (!cc) { - throw std::invalid_argument( - "Server has different check cannon index."); + throw CannonCreationException( + "Server has different check cannon index.", skipping_offset); } float skid_rot = 0.0f; float fraction_of_line = 0.0f; diff --git a/src/karts/cannon_animation.hpp b/src/karts/cannon_animation.hpp index b60141382..721522fe7 100644 --- a/src/karts/cannon_animation.hpp +++ b/src/karts/cannon_animation.hpp @@ -30,7 +30,6 @@ class CheckCannon; class Flyable; class Ipo; - /** This animation shoots the kart to a specified point on the track. * * \ingroup karts diff --git a/src/karts/kart_rewinder.cpp b/src/karts/kart_rewinder.cpp index 049adcf5a..1421e811c 100644 --- a/src/karts/kart_rewinder.cpp +++ b/src/karts/kart_rewinder.cpp @@ -330,17 +330,27 @@ void KartRewinder::restoreState(BareNetworkString *buffer, int count) { delete m_kart_animation; m_kart_animation = NULL; - switch (kat) + try { - case KAT_RESCUE: - new RescueAnimation(this, buffer); - break; - case KAT_EXPLOSION: - new ExplosionAnimation(this, buffer); - break; - case KAT_CANNON: - new CannonAnimation(this, buffer); - break; + switch (kat) + { + case KAT_RESCUE: + new RescueAnimation(this, buffer); + break; + case KAT_EXPLOSION: + new ExplosionAnimation(this, buffer); + break; + case KAT_CANNON: + new CannonAnimation(this, buffer); + break; + } + } + catch (const KartAnimationCreationException& kace) + { + Log::error("KartRewinder", "Kart animation creation error: %s", + kace.what()); + buffer->skip(kace.getSkippingOffset()); + m_kart_animation = NULL; } } else