From 9de7376b0a62e491d817583406b939cac9634758 Mon Sep 17 00:00:00 2001 From: Benau Date: Tue, 13 Nov 2018 12:56:40 +0800 Subject: [PATCH 1/2] Make a lossless compression for btKart state saving --- src/karts/kart.cpp | 9 +++++---- src/karts/kart_rewinder.cpp | 13 +++++++------ src/karts/skidding.cpp | 3 ++- src/physics/btKart.cpp | 26 ++++++++++++-------------- src/physics/btKart.hpp | 27 +++++++++++++++------------ src/physics/physics.cpp | 14 ++++++++------ 6 files changed, 49 insertions(+), 43 deletions(-) diff --git a/src/karts/kart.cpp b/src/karts/kart.cpp index 71772df13..458bfe08f 100644 --- a/src/karts/kart.cpp +++ b/src/karts/kart.cpp @@ -2291,7 +2291,7 @@ void Kart::crashed(const Material *m, const Vec3 &normal) const LinearWorld *lw = dynamic_cast(World::getWorld()); if(m_kart_properties->getTerrainImpulseType() ==KartProperties::IMPULSE_NORMAL && - m_vehicle->getCentralImpulseTime()<=0 ) + m_vehicle->getCentralImpulseTicks()<=0 ) { // Restrict impule to plane defined by gravity (i.e. X/Z plane). // This avoids the problem that karts can be pushed up, e.g. above @@ -2312,7 +2312,7 @@ void Kart::crashed(const Material *m, const Vec3 &normal) m_bounce_back_ticks = 0; impulse = Vec3(0, 0, 0); //m_vehicle->setTimedCentralImpulse(0.1f, impulse); - m_vehicle->setTimedCentralImpulse(0.0, impulse); + m_vehicle->setTimedCentralImpulse(0, impulse); } // If there is a quad graph, push the kart towards the previous // graph node center (we have to use the previous point since the @@ -2320,7 +2320,7 @@ void Kart::crashed(const Material *m, const Vec3 &normal) // would be pushed forward). else if(m_kart_properties->getTerrainImpulseType() ==KartProperties::IMPULSE_TO_DRIVELINE && - lw && m_vehicle->getCentralImpulseTime()<=0 && + lw && m_vehicle->getCentralImpulseTicks()<=0 && Track::getCurrentTrack()->isPushBackEnabled()) { int sector = lw->getSectorForKart(this); @@ -2338,7 +2338,8 @@ void Kart::crashed(const Material *m, const Vec3 &normal) impulse = Vec3(0, 0, -1); // Arbitrary impulse *= m_kart_properties->getCollisionTerrainImpulse(); m_bounce_back_ticks = stk_config->time2Ticks(0.2f); - m_vehicle->setTimedCentralImpulse(0.1f, impulse); + m_vehicle->setTimedCentralImpulse( + (uint16_t)stk_config->time2Ticks(0.1f), impulse); } } diff --git a/src/karts/kart_rewinder.cpp b/src/karts/kart_rewinder.cpp index e83c21d66..227c8e2cc 100644 --- a/src/karts/kart_rewinder.cpp +++ b/src/karts/kart_rewinder.cpp @@ -154,13 +154,13 @@ BareNetworkString* KartRewinder::saveState(std::vector* ru) buffer->add(body->getLinearVelocity()); buffer->add(body->getAngularVelocity()); - buffer->addFloat(m_vehicle->getTimedRotationTime()); + buffer->addUInt16(m_vehicle->getTimedRotationTicks()); buffer->add(m_vehicle->getTimedRotation()); buffer->addUInt8(m_vehicle->getCushioningDisableTime()); // For collision rewind buffer->addUInt16(m_bounce_back_ticks); - buffer->addFloat(m_vehicle->getCentralImpulseTime()); + buffer->addUInt16(m_vehicle->getCentralImpulseTicks()); buffer->add(m_vehicle->getAdditionalImpulse()); // 3) Steering and other player controls @@ -262,16 +262,17 @@ void KartRewinder::restoreState(BareNetworkString *buffer, int count) setTrans(m_transfrom_from_network); } - float time_rot = buffer->getFloat(); + uint16_t time_rot = buffer->getUInt16(); // Set timed rotation divides by time_rot - m_vehicle->setTimedRotation(time_rot, time_rot*buffer->getVec3()); + m_vehicle->setTimedRotation(time_rot, + stk_config->ticks2Time(time_rot) * buffer->getVec3()); m_vehicle->setCushioningDisableTime(buffer->getUInt8()); // Collision rewind m_bounce_back_ticks = buffer->getUInt16(); - float central_impulse_time = buffer->getFloat(); + uint16_t central_impulse_ticks = buffer->getUInt16(); Vec3 additional_impulse = buffer->getVec3(); - m_vehicle->setTimedCentralImpulse(central_impulse_time, + m_vehicle->setTimedCentralImpulse(central_impulse_ticks, additional_impulse, true/*rewind*/); // For the raycast to determine the current material under the kart diff --git a/src/karts/skidding.cpp b/src/karts/skidding.cpp index e81fc28f7..5b75f5a4c 100644 --- a/src/karts/skidding.cpp +++ b/src/karts/skidding.cpp @@ -536,7 +536,8 @@ void Skidding::update(int ticks, bool is_on_ground, t = std::min(t, kp->getSkidRevertVisualTime()); btVector3 rot(0, m_visual_rotation * kp->getSkidPostSkidRotateFactor(), 0); - m_kart->getVehicle()->setTimedRotation(t, rot); + m_kart->getVehicle()->setTimedRotation( + (uint16_t)stk_config->time2Ticks(t), rot); // skid_time is used to count backwards for the GFX m_skid_time = stk_config->time2Ticks(t); if(bonus_time>0) diff --git a/src/physics/btKart.cpp b/src/physics/btKart.cpp index a5a6a32cd..f7135c0ec 100644 --- a/src/physics/btKart.cpp +++ b/src/physics/btKart.cpp @@ -124,9 +124,9 @@ void btKart::reset() m_allow_sliding = false; m_num_wheels_on_ground = 0; m_additional_impulse = btVector3(0,0,0); - m_time_additional_impulse = 0; + m_ticks_additional_impulse = 0; m_additional_rotation = btVector3(0,0,0); - m_time_additional_rotation = 0; + m_ticks_additional_rotation = 0; m_max_speed = -1.0f; m_min_speed = 0.0f; m_cushioning_disable_time = 0; @@ -598,23 +598,21 @@ void btKart::updateVehicle( btScalar step ) // Apply additional impulse set by supertuxkart // -------------------------------------------- - if(m_time_additional_impulse>0) + if(m_ticks_additional_impulse>0) { - float dt = step > m_time_additional_impulse - ? m_time_additional_impulse - : step; + // We have fixed timestep + float dt = stk_config->ticks2Time(1); m_chassisBody->applyCentralImpulse(m_additional_impulse*dt); - m_time_additional_impulse -= dt; + m_ticks_additional_impulse--; } // Apply additional rotation set by supertuxkart // --------------------------------------------- - if(m_time_additional_rotation>0) + if(m_ticks_additional_rotation>0) { btTransform &t = m_chassisBody->getWorldTransform(); - float dt = step > m_time_additional_rotation - ? m_time_additional_rotation - : step; + // We have fixed timestep + float dt = stk_config->ticks2Time(1); btQuaternion add_rot(m_additional_rotation.getY()*dt, m_additional_rotation.getX()*dt, m_additional_rotation.getZ()*dt); @@ -628,7 +626,7 @@ void btKart::updateVehicle( btScalar step ) // kart, or a strongly 'visual jolt' of the kart btTransform &iwt=m_chassisBody->getInterpolationWorldTransform(); iwt.setRotation(iwt.getRotation()*add_rot); - m_time_additional_rotation -= dt; + m_ticks_additional_rotation--; } adjustSpeed(m_min_speed, m_max_speed); } // updateVehicle @@ -883,7 +881,7 @@ void btKart::updateFriction(btScalar timeStep) m_forwardImpulse[wheel] = rollingFriction; - if(m_time_additional_impulse>0) + if(m_ticks_additional_impulse>0) { sliding = true; m_wheelInfo[wheel].m_skidInfo = 0.0f; @@ -913,7 +911,7 @@ void btKart::updateFriction(btScalar timeStep) // Note: don't reset zipper speed, or the kart rewinder will // get incorrect zipper information. - if (sliding && (m_allow_sliding || m_time_additional_impulse>0) ) + if (sliding && (m_allow_sliding || m_ticks_additional_impulse>0) ) { for (int wheel = 0; wheel < getNumWheels(); wheel++) { diff --git a/src/physics/btKart.hpp b/src/physics/btKart.hpp index bfcecffba..06a0f1868 100644 --- a/src/physics/btKart.hpp +++ b/src/physics/btKart.hpp @@ -19,6 +19,8 @@ class btDynamicsWorld; #include "BulletDynamics/Vehicle/btWheelInfo.h" #include "BulletDynamics/Dynamics/btActionInterface.h" +#include "config/stk_config.hpp" + class btVehicleTuning; class Kart; struct btWheelContactPoint; @@ -79,13 +81,13 @@ private: btVector3 m_additional_impulse; /** The time the additional impulse should be applied. */ - float m_time_additional_impulse; + uint16_t m_ticks_additional_impulse; /** Additional rotation that is applied over a certain amount of time. */ btVector3 m_additional_rotation; /** Duration over which the additional rotation is applied. */ - float m_time_additional_rotation; + uint16_t m_ticks_additional_rotation; /** The rigid body that is the chassis of the kart. */ btRigidBody *m_chassisBody; @@ -221,36 +223,37 @@ public: unsigned int getNumWheelsOnGround() const {return m_num_wheels_on_ground;} // ------------------------------------------------------------------------ /** Sets an impulse that is applied for a certain amount of time. - * \param t Time for the impulse to be active. + * \param t Ticks for the impulse to be active. * \param imp The impulse to apply. */ - void setTimedCentralImpulse(float t, const btVector3 &imp, + void setTimedCentralImpulse(uint16_t t, const btVector3 &imp, bool rewind = false) { // Only add impulse if no other impulse is active. - if (m_time_additional_impulse > 0 && !rewind) return; + if (m_ticks_additional_impulse > 0 && !rewind) return; m_additional_impulse = imp; - m_time_additional_impulse = t; + m_ticks_additional_impulse = t; } // setTimedImpulse // ------------------------------------------------------------------------ /** Returns the time an additional impulse is activated. */ - float getCentralImpulseTime() const { return m_time_additional_impulse; } + uint16_t getCentralImpulseTicks() const + { return m_ticks_additional_impulse; } // ------------------------------------------------------------------------ const btVector3& getAdditionalImpulse() const { return m_additional_impulse; } // ------------------------------------------------------------------------ /** Sets a rotation that is applied over a certain amount of time (to avoid * a too rapid changes in the kart). - * \param t Time for the rotation to be applied. + * \param t Ticks for the rotation to be applied. * \param torque The rotation to apply. */ - void setTimedRotation(float t, const btVector3 &rot) + void setTimedRotation(uint16_t t, const btVector3 &rot) { - if(t>0) m_additional_rotation = rot/t; - m_time_additional_rotation = t; + if(t>0) m_additional_rotation = rot / (stk_config->ticks2Time(t)); + m_ticks_additional_rotation = t; } // setTimedTorque // ------------------------------------------------------------------------ const btVector3& getTimedRotation() const { return m_additional_rotation; } // ------------------------------------------------------------------------ - float getTimedRotationTime() const { return m_time_additional_rotation; } + uint16_t getTimedRotationTicks() const { return m_ticks_additional_rotation; } // ------------------------------------------------------------------------ /** Returns the time cushioning is disabled. Used for networking state * saving. */ diff --git a/src/physics/physics.cpp b/src/physics/physics.cpp index 63a053581..33bebceeb 100644 --- a/src/physics/physics.cpp +++ b/src/physics/physics.cpp @@ -496,27 +496,29 @@ void Physics::KartKartCollision(AbstractKart *kart_a, // First push one kart to the left (if there is not already // an impulse happening - one collision might cause more // than one impulse otherwise) - if(right_kart->getVehicle()->getCentralImpulseTime()<=0) + if(right_kart->getVehicle()->getCentralImpulseTicks()<=0) { const KartProperties *kp = left_kart->getKartProperties(); Vec3 impulse(kp->getCollisionImpulse()*f_right, 0, 0); impulse = right_kart->getTrans().getBasis() * impulse; right_kart->getVehicle() - ->setTimedCentralImpulse(kp->getCollisionImpulseTime(), - impulse); + ->setTimedCentralImpulse( + (uint16_t)stk_config->time2Ticks(kp->getCollisionImpulseTime()), + impulse); right_kart ->getBody()->setAngularVelocity(btVector3(0,0,0)); } // Then push the other kart to the right (if there is no // impulse happening atm). - if(left_kart->getVehicle()->getCentralImpulseTime()<=0) + if(left_kart->getVehicle()->getCentralImpulseTicks()<=0) { const KartProperties *kp = right_kart->getKartProperties(); Vec3 impulse = Vec3(-kp->getCollisionImpulse()*f_left, 0, 0); impulse = left_kart->getTrans().getBasis() * impulse; left_kart->getVehicle() - ->setTimedCentralImpulse(kp->getCollisionImpulseTime(), - impulse); + ->setTimedCentralImpulse( + (uint16_t)stk_config->time2Ticks(kp->getCollisionImpulseTime()), + impulse); left_kart->getBody()->setAngularVelocity(btVector3(0,0,0)); } From 1cb1923239943d027284861ad2caa334cddfd5f7 Mon Sep 17 00:00:00 2001 From: Benau Date: Tue, 13 Nov 2018 14:15:34 +0800 Subject: [PATCH 2/2] Fix #3554 --- src/guiengine/widgets/icon_button_widget.cpp | 7 ++++++- src/guiengine/widgets/icon_button_widget.hpp | 2 ++ src/network/protocols/server_lobby.cpp | 12 +++++++++++- src/states_screens/online/networking_lobby.cpp | 16 ++++++++++++---- 4 files changed, 31 insertions(+), 6 deletions(-) diff --git a/src/guiengine/widgets/icon_button_widget.cpp b/src/guiengine/widgets/icon_button_widget.cpp index daadc4e91..edd89f397 100644 --- a/src/guiengine/widgets/icon_button_widget.cpp +++ b/src/guiengine/widgets/icon_button_widget.cpp @@ -426,7 +426,6 @@ void IconButtonWidget::setLabelFont() } // ----------------------------------------------------------------------------- - void IconButtonWidget::setVisible(bool visible) { Widget::setVisible(visible); @@ -434,3 +433,9 @@ void IconButtonWidget::setVisible(bool visible) if (m_label != NULL) m_label->setVisible(visible); } + +// ----------------------------------------------------------------------------- +void IconButtonWidget::setText(const wchar_t *s) +{ + m_label->setText(s); +} diff --git a/src/guiengine/widgets/icon_button_widget.hpp b/src/guiengine/widgets/icon_button_widget.hpp index 5580195f5..4c56ca55f 100644 --- a/src/guiengine/widgets/icon_button_widget.hpp +++ b/src/guiengine/widgets/icon_button_widget.hpp @@ -170,6 +170,8 @@ namespace GUIEngine Widget::elementRemoved(); m_label = NULL; } + // -------------------------------------------------------------------- + virtual void setText(const wchar_t *s) OVERRIDE; }; } diff --git a/src/network/protocols/server_lobby.cpp b/src/network/protocols/server_lobby.cpp index a45765d38..4d3310d18 100644 --- a/src/network/protocols/server_lobby.cpp +++ b/src/network/protocols/server_lobby.cpp @@ -446,6 +446,7 @@ void ServerLobby::asynchronousUpdate() { if (ServerConfig::m_owner_less) { + m_game_setup->update(true/*remove_disconnected_players*/); int player_size = m_game_setup->getPlayerCount(); if ((player_size >= ServerConfig::m_min_start_game_players || m_game_setup->isGrandPrixStarted()) && @@ -458,10 +459,14 @@ void ServerLobby::asynchronousUpdate() else if (player_size < ServerConfig::m_min_start_game_players && !m_game_setup->isGrandPrixStarted()) { + resetPeersReady(); m_timeout.store(std::numeric_limits::max()); } - if (m_timeout.load() < (int64_t)StkTime::getRealTimeMs()) + if (m_timeout.load() < (int64_t)StkTime::getRealTimeMs() || + (checkPeersReady() && + player_size >= ServerConfig::m_min_start_game_players)) { + resetPeersReady(); startSelection(); return; } @@ -826,6 +831,11 @@ void ServerLobby::startSelection(const Event *event) m_state.load()); return; } + if (ServerConfig::m_owner_less) + { + m_peers_ready.at(event->getPeerSP()) = true; + return; + } if (event->getPeerSP() != m_server_owner.lock()) { Log::warn("ServerLobby", diff --git a/src/states_screens/online/networking_lobby.cpp b/src/states_screens/online/networking_lobby.cpp index 48938bf92..7314b9533 100644 --- a/src/states_screens/online/networking_lobby.cpp +++ b/src/states_screens/online/networking_lobby.cpp @@ -152,6 +152,7 @@ void NetworkingLobby::init() //I18N: In the networking lobby m_header->setText(_("Lobby"), false); m_server_info_height = GUIEngine::getFont()->getDimension(L"X").Height; + m_start_button->setText(_("Start race")); m_start_button->setVisible(false); m_state = LS_CONNECTING; getWidget("chat")->setVisible(false); @@ -290,9 +291,11 @@ void NetworkingLobby::onUpdate(float delta) if (remain < 0) remain = 0; //I18N: In the networking lobby, display the starting timeout - //for owner-less server - core::stringw msg = _P("Game will start after %d second.", - "Game will start after %d seconds.", (int)remain); + //for owner-less server to begin a game + core::stringw msg = _P("Starting after %d second " + "or everyone pressed 'Ready' button.", + "Starting after %d seconds " + "or everyone pressed 'Ready' button.", (int)remain); m_timeout_message->setText(msg, true); } } @@ -344,7 +347,9 @@ void NetworkingLobby::onUpdate(float delta) m_text_bubble->setText(total_msg, true); } - if (STKHost::get()->isAuthorisedToControl()) + if (STKHost::get()->isAuthorisedToControl() || + (m_has_auto_start_in_server && + m_cur_starting_timer != std::numeric_limits::max())) { m_start_button->setVisible(true); } @@ -571,6 +576,9 @@ void NetworkingLobby::initAutoStartTimer(bool grand_prix_started, if (min_players == 0 || start_timeout == 0.0f) return; + //I18N: In the networking lobby, ready button is to allow player to tell + //server that he is ready for next game for owner less server + m_start_button->setText(_("Ready")); m_has_auto_start_in_server = true; m_min_start_game_players = grand_prix_started ? 0 : min_players; m_start_timeout = start_timeout;