#ifndef CLIENT_ENTITY_ANIMATE_HH_ #define CLIENT_ENTITY_ANIMATE_HH_ #include #include #include #include #include #include #include #include "client/entity/entity.hh" #include "client/movement/movement.hh" #include "client/settings.hh" #include "client/state/state.hh" #include "shared/entity/animate.hh" #include "shared/entity/entity.hh" #include "shared/movement/movement.hh" #include "shared/net/proto.hh" #include "shared/shared.hh" namespace client { class animate : virtual public shared::animate, virtual public client::entity { protected: struct animate_update { shared::tick_t tick_sequence; // tick or sequence, if LP then sequence. shared::animate animate; bool from_server; }; // We have 1 second of potential player interpolation to use here when we // initialise this with the server's tickrate. boost::circular_buffer updates{state::tickrate}; shared::tick_t latest_sequence = 0; private: float get_target_ticks_back() noexcept; public: animate(shared::player&& p) noexcept : shared::entity(p), shared::animate(p), client::entity(p) {} animate(const proto::animate& proto) noexcept : shared::entity(proto.entity()), shared::animate(proto), client::entity(proto.entity()) {} public: // Call when localplayer gets tick to update state timers. void update_time_factor(const shared::tick_t& sequence, const shared::tick_t& tick) noexcept; virtual void notify(const shared::animate& animate, const shared::tick_t& tick_sequence, const bool from_server) noexcept; shared::tick_t& get_mutable_latest_sequence() noexcept { return this->latest_sequence; } shared::tick_t get_latest_sequence() const noexcept { return this->latest_sequence; } // An animate may be interpolated, however it's the moveable class that is // required for extrapolation and other prediction. void interpolate() noexcept; }; } // namespace client #endif