From 7ebd1fabd906b1cd10dbc32c17f57af260e31433 Mon Sep 17 00:00:00 2001 From: Benau Date: Thu, 19 Jul 2018 14:23:35 +0800 Subject: [PATCH 01/36] Add exception handling to prevent player hacking network string --- src/modes/cutscene_world.cpp | 1 - src/network/network_string.hpp | 11 +++++--- src/network/protocol_manager.cpp | 27 ++++++++++++++++--- .../protocols/game_events_protocol.cpp | 4 +-- src/network/stk_host.cpp | 10 ++++++- src/states_screens/race_gui_overworld.cpp | 4 --- 6 files changed, 41 insertions(+), 16 deletions(-) diff --git a/src/modes/cutscene_world.cpp b/src/modes/cutscene_world.cpp index e8a018b01..8bbfbd3f7 100644 --- a/src/modes/cutscene_world.cpp +++ b/src/modes/cutscene_world.cpp @@ -231,7 +231,6 @@ void CutsceneWorld::update(int ticks) { // this way of calculating time and dt is more in line with what // irrlicht does and provides better synchronisation - double prev_time = m_time; double now = StkTime::getRealTime(); m_time = now - m_time_at_second_reset; } diff --git a/src/network/network_string.hpp b/src/network/network_string.hpp index 760f0b4bd..94618309e 100644 --- a/src/network/network_string.hpp +++ b/src/network/network_string.hpp @@ -74,6 +74,10 @@ protected: */ std::string getString(int len) const { + if (m_current_offset > (int)m_buffer.size() || + m_current_offset + len > (int)m_buffer.size()) + throw std::out_of_range("getString out of range."); + std::string a(m_buffer.begin() + (m_current_offset ), m_buffer.begin() + (m_current_offset + len)); m_current_offset += len; @@ -101,7 +105,7 @@ protected: { result <<= 8; // offset one byte // add the data to result - result += m_buffer[offset - a]; + result += m_buffer.at(offset - a); } return result; } // get(int pos) @@ -110,7 +114,7 @@ protected: template T get() const { - return m_buffer[m_current_offset++]; + return m_buffer.at(m_current_offset++); } // get public: @@ -424,8 +428,7 @@ public: /** Returns the protocol type of this message. */ ProtocolType getProtocolType() const { - assert(!m_buffer.empty()); - return (ProtocolType)(m_buffer[0] & ~PROTOCOL_SYNCHRONOUS); + return (ProtocolType)(m_buffer.at(0) & ~PROTOCOL_SYNCHRONOUS); } // getProtocolType // ------------------------------------------------------------------------ diff --git a/src/network/protocol_manager.cpp b/src/network/protocol_manager.cpp index f0b740efc..4fe3cb5a2 100644 --- a/src/network/protocol_manager.cpp +++ b/src/network/protocol_manager.cpp @@ -378,14 +378,15 @@ bool ProtocolManager::sendEvent(Event* event) bool can_be_deleted = false; if (event->getType() == EVENT_TYPE_MESSAGE) { - OneProtocolType &opt = m_all_protocols[event->data().getProtocolType()]; + OneProtocolType &opt = + m_all_protocols.at(event->data().getProtocolType()); can_be_deleted = opt.notifyEvent(event); } else // connect or disconnect event --> test all protocols { for (unsigned int i = 0; i < m_all_protocols.size(); i++) { - can_be_deleted |= m_all_protocols[i].notifyEvent(event); + can_be_deleted |= m_all_protocols.at(i).notifyEvent(event); } } return can_be_deleted || StkTime::getTimeSinceEpoch() - event->getArrivalTime() @@ -432,7 +433,16 @@ void ProtocolManager::update(int ticks) while (i != m_sync_events_to_process.getData().end()) { m_sync_events_to_process.unlock(); - bool can_be_deleted = sendEvent(*i); + bool can_be_deleted = true; + try + { + can_be_deleted = sendEvent(*i); + } + catch (std::exception& e) + { + Log::error("ProtocolManager", "Synchronous event error: %s", + e.what()); + } m_sync_events_to_process.lock(); if (can_be_deleted) { @@ -478,7 +488,16 @@ void ProtocolManager::asynchronousUpdate() m_async_events_to_process.unlock(); m_all_protocols[(*i)->getType()].lock(); - bool result = sendEvent(*i); + bool result = true; + try + { + result = sendEvent(*i); + } + catch (std::exception& e) + { + Log::error("ProtocolManager", "Asynchronous event error: %s", + e.what()); + } m_all_protocols[(*i)->getType()].unlock(); m_async_events_to_process.lock(); diff --git a/src/network/protocols/game_events_protocol.cpp b/src/network/protocols/game_events_protocol.cpp index f7f8f7ebc..21ef36afd 100644 --- a/src/network/protocols/game_events_protocol.cpp +++ b/src/network/protocols/game_events_protocol.cpp @@ -54,14 +54,14 @@ bool GameEventsProtocol::notifyEvent(Event* event) case GE_RESET_BALL: { if (!sw) - throw("No soccer world"); + throw std::invalid_argument("No soccer world"); sw->handleResetBallFromServer(data); break; } case GE_PLAYER_GOAL: { if (!sw) - throw("No soccer world"); + throw std::invalid_argument("No soccer world"); sw->handlePlayerGoalFromServer(data); break; } diff --git a/src/network/stk_host.cpp b/src/network/stk_host.cpp index 046bcfc54..c707c25bc 100644 --- a/src/network/stk_host.cpp +++ b/src/network/stk_host.cpp @@ -720,7 +720,15 @@ void STKHost::mainLoop() auto sl = LobbyProtocol::get(); if (direct_socket && sl && sl->waitingForPlayers()) { - handleDirectSocketRequest(direct_socket, sl); + try + { + handleDirectSocketRequest(direct_socket, sl); + } + catch (std::exception& e) + { + Log::warn("STKHost", "Direct socket error: %s", + e.what()); + } } // if discovery host if (is_server) diff --git a/src/states_screens/race_gui_overworld.cpp b/src/states_screens/race_gui_overworld.cpp index 0b7405760..35ff7d434 100644 --- a/src/states_screens/race_gui_overworld.cpp +++ b/src/states_screens/race_gui_overworld.cpp @@ -189,10 +189,6 @@ void RaceGUIOverworld::renderGlobal(float dt) if (race_manager->getIfEmptyScreenSpaceExists() && !GUIEngine::ModalDialog::isADialogActive()) { - const float sqrt_num_players = - sqrtf((float)race_manager->getNumLocalPlayers()); - const int rows = (int)ceil(sqrt_num_players); - const int cols = (int)round(sqrt_num_players); static video::SColor black = video::SColor(255,0,0,0); GL32_draw2DRectangle(black, irr_driver->getSplitscreenWindow( race_manager->getNumLocalPlayers())); From 4ccb405cd18c9ae5b8fc2b896d646b7404950935 Mon Sep 17 00:00:00 2001 From: Benau Date: Thu, 19 Jul 2018 14:48:50 +0800 Subject: [PATCH 02/36] Add exception handling in handlePendingConnection --- src/network/protocols/server_lobby.cpp | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/network/protocols/server_lobby.cpp b/src/network/protocols/server_lobby.cpp index d30e80985..e31711317 100644 --- a/src/network/protocols/server_lobby.cpp +++ b/src/network/protocols/server_lobby.cpp @@ -1857,16 +1857,25 @@ void ServerLobby::handlePendingConnection() auto key = m_keys.find(online_id); if (key != m_keys.end() && key->second.m_tried == false) { - if (decryptConnectionRequest(peer, it->second.second, - key->second.m_aes_key, key->second.m_aes_iv, online_id, - key->second.m_name)) + try { - it = m_pending_connection.erase(it); - m_keys.erase(online_id); - continue; + if (decryptConnectionRequest(peer, it->second.second, + key->second.m_aes_key, key->second.m_aes_iv, online_id, + key->second.m_name)) + { + it = m_pending_connection.erase(it); + m_keys.erase(online_id); + continue; + } + else + key->second.m_tried = true; } - else + catch (std::exception& e) + { + Log::error("ServerLobby", + "handlePendingConnection error: %s", e.what()); key->second.m_tried = true; + } } it++; } From 639883ca48333d5b8e5d5bdb9579aa8cf2502502 Mon Sep 17 00:00:00 2001 From: Benau Date: Thu, 19 Jul 2018 15:26:15 +0800 Subject: [PATCH 03/36] Display the number of players required to start a game for owner-less server --- src/states_screens/networking_lobby.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/states_screens/networking_lobby.cpp b/src/states_screens/networking_lobby.cpp index 33bc0c2c6..ca4b9e3d1 100644 --- a/src/states_screens/networking_lobby.cpp +++ b/src/states_screens/networking_lobby.cpp @@ -17,6 +17,7 @@ #include "states_screens/networking_lobby.hpp" +#include #include #include @@ -220,7 +221,13 @@ void NetworkingLobby::onUpdate(float delta) else if (cur_player < m_server_max_player * m_start_threshold) { m_cur_starting_timer = std::numeric_limits::max(); - m_timeout_message->setText(L"", true); + //I18N: In the networking lobby, display the number of players + //required to start a game for owner-less server + core::stringw msg = + _P("Game will start if there is more than %d player.", + "Game will start if there are more than %d players.", + (int)floor(m_server_max_player * m_start_threshold)); + m_timeout_message->setText(msg, true); } if (m_cur_starting_timer != std::numeric_limits::max()) From f124bd9df325f59615df1d5974b56a78eb2b282a Mon Sep 17 00:00:00 2001 From: Benau Date: Thu, 19 Jul 2018 15:50:01 +0800 Subject: [PATCH 04/36] Don't allow the game to start if all players joined red or blue team --- src/main.cpp | 6 ++++-- src/network/protocols/client_lobby.cpp | 12 ++++++++++++ src/network/protocols/client_lobby.hpp | 1 + src/network/protocols/lobby_protocol.hpp | 3 ++- src/network/protocols/server_lobby.cpp | 25 ++++++++++++++++++++++++ 5 files changed, 44 insertions(+), 3 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 08cef4d72..d475ff7c3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -607,7 +607,8 @@ void cmdLineHelp() " --auto-end Automatically end network game after 1st player finished\n" " for some time (currently his finished time * 0.25 + 15.0). \n" " --team-choosing Allow choosing team in lobby, implicitly allowed in lan or\n" - " password protected server.\n" + " password protected server. This function cannot be used in\n" + " owner-less server.\n" " --soccer-timed Use time limit mode in network soccer game.\n" " --soccer-goals Use goals limit mode in network soccer game.\n" " --network-gp=n Specify number of tracks used in network grand prix.\n" @@ -1158,7 +1159,8 @@ int handleCmdLine() } if (CommandLine::has("--team-choosing")) { - NetworkConfig::get()->setTeamChoosing(true); + if (!NetworkConfig::get()->isOwnerLess()) + NetworkConfig::get()->setTeamChoosing(true); } if (CommandLine::has("--connect-now", &s)) { diff --git a/src/network/protocols/client_lobby.cpp b/src/network/protocols/client_lobby.cpp index 2b5753b02..8415e4218 100644 --- a/src/network/protocols/client_lobby.cpp +++ b/src/network/protocols/client_lobby.cpp @@ -166,6 +166,7 @@ bool ClientLobby::notifyEventAsynchronous(Event* event) case LE_CONNECTION_REFUSED: connectionRefused(event); break; case LE_VOTE: displayPlayerVote(event); break; case LE_SERVER_OWNERSHIP: becomingServerOwner(); break; + case LE_BAD_TEAM: handleBadTeam(); break; default: break; } // switch @@ -610,10 +611,21 @@ void ClientLobby::updatePlayerList(Event* event) NetworkingLobby::getInstance()->updatePlayers(players); } // updatePlayerList +//----------------------------------------------------------------------------- +void ClientLobby::handleBadTeam() +{ + SFXManager::get()->quickSound("anvil"); + //I18N: Display when all players are in red or blue team, which the race + //will not be allowed to start + core::stringw msg = _("All players joined red or blue team."); + MessageQueue::add(MessageQueue::MT_ERROR, msg); +} // handleBadTeam + //----------------------------------------------------------------------------- void ClientLobby::becomingServerOwner() { SFXManager::get()->quickSound("wee"); + //I18N: Display when a player is allow to control the server core::stringw msg = _("You are now the owner of server."); MessageQueue::add(MessageQueue::MT_GENERIC, msg); STKHost::get()->setAuthorisedToControl(true); diff --git a/src/network/protocols/client_lobby.hpp b/src/network/protocols/client_lobby.hpp index 9efc4c801..389d24675 100644 --- a/src/network/protocols/client_lobby.hpp +++ b/src/network/protocols/client_lobby.hpp @@ -45,6 +45,7 @@ private: void updatePlayerList(Event* event); void handleChat(Event* event); void handleServerInfo(Event* event); + void handleBadTeam(); void becomingServerOwner(); void clearPlayers(); diff --git a/src/network/protocols/lobby_protocol.hpp b/src/network/protocols/lobby_protocol.hpp index 27a1929cb..b047d5188 100644 --- a/src/network/protocols/lobby_protocol.hpp +++ b/src/network/protocols/lobby_protocol.hpp @@ -60,7 +60,8 @@ public: LE_CHAT, LE_SERVER_OWNERSHIP, LE_KICK_HOST, - LE_CHANGE_TEAM + LE_CHANGE_TEAM, + LE_BAD_TEAM }; enum RejectReason : uint8_t diff --git a/src/network/protocols/server_lobby.cpp b/src/network/protocols/server_lobby.cpp index e31711317..cff51a07a 100644 --- a/src/network/protocols/server_lobby.cpp +++ b/src/network/protocols/server_lobby.cpp @@ -761,6 +761,31 @@ void ServerLobby::startSelection(const Event *event) } } + if (NetworkConfig::get()->hasTeamChoosing()) + { + int red_count = 0; + int blue_count = 0; + auto players = m_game_setup->getConnectedPlayers(); + for (auto& player : players) + { + if (player->getTeam() == SOCCER_TEAM_RED) + red_count++; + else if (player->getTeam() == SOCCER_TEAM_BLUE) + blue_count++; + if (red_count != 0 && blue_count != 0) + break; + } + if ((red_count == 0 || blue_count == 0) && players.size() != 1) + { + Log::warn("ServerLobby", "Bad team choosing."); + NetworkString* bt = getNetworkString(); + bt->addUInt8(LE_BAD_TEAM); + sendMessageToPeers(bt, true/*reliable*/); + delete bt; + return; + } + } + ProtocolManager::lock()->findAndTerminate(PROTOCOL_CONNECTION); if (NetworkConfig::get()->isWAN()) { From 487227630fb657042058a50b6e1d2cd3a9fdd852 Mon Sep 17 00:00:00 2001 From: Benau Date: Fri, 20 Jul 2018 01:06:11 +0800 Subject: [PATCH 05/36] Invert x-z of position for soccer blue team player --- src/tracks/graph.cpp | 39 ++++++++++++++++++++++++++++++++------- src/tracks/graph.hpp | 9 ++++++--- src/tracks/track.cpp | 30 ++++++++++++++++++++++++++++-- src/tracks/track.hpp | 2 ++ 4 files changed, 68 insertions(+), 12 deletions(-) diff --git a/src/tracks/graph.cpp b/src/tracks/graph.cpp index 5ef0876dc..b53db294f 100644 --- a/src/tracks/graph.cpp +++ b/src/tracks/graph.cpp @@ -120,7 +120,7 @@ void Graph::cleanupDebugMesh() /** Creates the actual mesh that is used by createDebugMesh() or makeMiniMap() */ void Graph::createMesh(bool show_invisible, bool enable_transparency, - const video::SColor *track_color) + const video::SColor *track_color, bool invert_x_z) { #ifndef SERVER_ONLY // The debug track will not be lighted or culled. @@ -172,6 +172,18 @@ void Graph::createMesh(bool show_invisible, bool enable_transparency, differentNodeColor(count, &this_color); // Transfer the 4 points of the current quad to the list of vertices m_all_nodes[count]->getVertices(new_v+4*i, this_color); + if (invert_x_z) + { + auto* vptr = new_v + 4 * i; + vptr[0].Pos.X = -vptr[0].Pos.X; + vptr[0].Pos.Z = -vptr[0].Pos.Z; + vptr[1].Pos.X = -vptr[1].Pos.X; + vptr[1].Pos.Z = -vptr[1].Pos.Z; + vptr[2].Pos.X = -vptr[2].Pos.X; + vptr[2].Pos.Z = -vptr[2].Pos.Z; + vptr[3].Pos.X = -vptr[3].Pos.X; + vptr[3].Pos.Z = -vptr[3].Pos.Z; + } // Set up the indices for the triangles // (note, afaik with opengl we could use quads directly, but the code @@ -244,7 +256,7 @@ void Graph::createMesh(bool show_invisible, bool enable_transparency, /** Creates the actual mesh that is used by createDebugMesh() or makeMiniMap() */ void Graph::createMeshSP(bool show_invisible, bool enable_transparency, - const video::SColor *track_color) + const video::SColor *track_color, bool invert_x_z) { #ifndef SERVER_ONLY @@ -294,6 +306,18 @@ void Graph::createMeshSP(bool show_invisible, bool enable_transparency, differentNodeColor(count, &this_color); // Transfer the 4 points of the current quad to the list of vertices m_all_nodes[count]->getSPMVertices(vertices.data() + (4 * i), this_color); + if (invert_x_z) + { + auto* vptr = vertices.data() + (4 * i); + vptr[0].m_position.X = -vptr[0].m_position.X; + vptr[0].m_position.Z = -vptr[0].m_position.Z; + vptr[1].m_position.X = -vptr[1].m_position.X; + vptr[1].m_position.Z = -vptr[1].m_position.Z; + vptr[2].m_position.X = -vptr[2].m_position.X; + vptr[2].m_position.Z = -vptr[2].m_position.Z; + vptr[3].m_position.X = -vptr[3].m_position.X; + vptr[3].m_position.Z = -vptr[3].m_position.Z; + } // Set up the indices for the triangles indices[6 * i] = 4 * i + 2; // First triangle: vertex 0, 1, 2 @@ -366,7 +390,8 @@ void Graph::createMeshSP(bool show_invisible, bool enable_transparency, */ RenderTarget* Graph::makeMiniMap(const core::dimension2du &dimension, const std::string &name, - const video::SColor &fill_color) + const video::SColor &fill_color, + bool invert_x_z) { // Skip minimap when profiling if (ProfileWorld::isNoGraphics()) return NULL; @@ -384,14 +409,14 @@ RenderTarget* Graph::makeMiniMap(const core::dimension2du &dimension, if (CVS->isGLSL()) { createMeshSP(/*show_invisible part of the track*/ false, - /*enable_transparency*/ false, - /*track_color*/ &fill_color); + /*enable_transparency*/ false, /*track_color*/&fill_color, + invert_x_z); } else { createMesh(/*show_invisible part of the track*/ false, - /*enable_transparency*/ false, - /*track_color*/ &fill_color); + /*enable_transparency*/ false, /*track_color*/&fill_color, + invert_x_z); } #endif diff --git a/src/tracks/graph.hpp b/src/tracks/graph.hpp index b1079354a..b19a7de8c 100644 --- a/src/tracks/graph.hpp +++ b/src/tracks/graph.hpp @@ -93,11 +93,13 @@ private: // ------------------------------------------------------------------------ void createMesh(bool show_invisible=true, bool enable_transparency=false, - const video::SColor *track_color=NULL); + const video::SColor *track_color=NULL, + bool invert_x_z = false); // ------------------------------------------------------------------------ void createMeshSP(bool show_invisible=true, bool enable_transparency=false, - const video::SColor *track_color=NULL); + const video::SColor *track_color=NULL, + bool invert_x_z = false); // ------------------------------------------------------------------------ void cleanupDebugMesh(); // ------------------------------------------------------------------------ @@ -143,7 +145,8 @@ public: // ------------------------------------------------------------------------ RenderTarget* makeMiniMap(const core::dimension2du &dimension, const std::string &name, - const video::SColor &fill_color); + const video::SColor &fill_color, + bool invert_x_z); // ------------------------------------------------------------------------ void mapPoint2MiniMap(const Vec3 &xyz, Vec3 *out) const; // ------------------------------------------------------------------------ diff --git a/src/tracks/track.cpp b/src/tracks/track.cpp index 82bf23c50..4310abee5 100644 --- a/src/tracks/track.cpp +++ b/src/tracks/track.cpp @@ -105,6 +105,7 @@ Track::Track(const std::string &filename) m_magic_number = 0x17AC3802; #endif + m_minimap_invert_x_z = false; m_materials_loaded = false; m_filename = filename; m_root = @@ -709,6 +710,21 @@ void Track::startMusic() const */ void Track::loadArenaGraph(const XMLNode &node) { + // Determine if rotate minimap is needed for soccer mode (for blue team) + // Only need to test local player + if (race_manager->getMinorMode() == RaceManager::MINOR_MODE_SOCCER) + { + for (unsigned i = 0; i < race_manager->getNumberOfKarts(); i++) + { + if (race_manager->getKartType(i) != RaceManager::KT_PLAYER) + continue; + if (race_manager->getKartInfo(i).getSoccerTeam() == + SOCCER_TEAM_BLUE) + m_minimap_invert_x_z = true; + break; + } + } + ArenaGraph* graph = new ArenaGraph(m_root+"navmesh.xml", &node); Graph::setGraph(graph); @@ -786,7 +802,15 @@ void Track::loadDriveGraph(unsigned int mode_id, const bool reverse) void Track::mapPoint2MiniMap(const Vec3 &xyz, Vec3 *draw_at) const { - Graph::get()->mapPoint2MiniMap(xyz, draw_at); + if (m_minimap_invert_x_z) + { + Vec3 invert = xyz; + invert.setX(-xyz.x()); + invert.setZ(-xyz.z()); + Graph::get()->mapPoint2MiniMap(invert, draw_at); + } + else + Graph::get()->mapPoint2MiniMap(xyz, draw_at); draw_at->setX(draw_at->getX() * m_minimap_x_scale); draw_at->setY(draw_at->getY() * m_minimap_y_scale); } @@ -1115,7 +1139,9 @@ void Track::loadMinimap() m_mini_map_size = World::getWorld()->getRaceGUI()->getMiniMapSize(); //Use twice the size of the rendered minimap to reduce significantly aliasing - m_render_target = Graph::get()->makeMiniMap(m_mini_map_size*2, "minimap::" + m_ident, video::SColor(127, 255, 255, 255)); + m_render_target = Graph::get()->makeMiniMap(m_mini_map_size * 2, + "minimap::" + m_ident, video::SColor(127, 255, 255, 255), + m_minimap_invert_x_z); if (!m_render_target) return; core::dimension2du mini_map_texture_size = m_render_target->getTextureSize(); diff --git a/src/tracks/track.hpp b/src/tracks/track.hpp index e4547d592..d91f4ef55 100644 --- a/src/tracks/track.hpp +++ b/src/tracks/track.hpp @@ -365,6 +365,8 @@ private: float m_displacement_speed; int m_physical_object_uid; + bool m_minimap_invert_x_z; + /** The levels for color correction * m_color_inlevel(black, gamma, white) * m_color_outlevel(black, white)*/ From 1f7f64f3b5629f47da51c69aa3d354efaf2826f2 Mon Sep 17 00:00:00 2001 From: Benau Date: Fri, 20 Jul 2018 01:36:02 +0800 Subject: [PATCH 06/36] Prevent rescuing in soccer mode to go back to self goal immediately --- src/modes/soccer_world.cpp | 27 +++++++++++++++++++++------ src/modes/soccer_world.hpp | 3 ++- src/tracks/track_sector.cpp | 12 +++++++----- src/tracks/track_sector.hpp | 2 ++ 4 files changed, 32 insertions(+), 12 deletions(-) diff --git a/src/modes/soccer_world.cpp b/src/modes/soccer_world.cpp index b1e11448b..ac5b3dc0d 100644 --- a/src/modes/soccer_world.cpp +++ b/src/modes/soccer_world.cpp @@ -38,6 +38,8 @@ #include "network/stk_host.hpp" #include "physics/physics.hpp" #include "states_screens/race_gui_base.hpp" +#include "tracks/graph.hpp" +#include "tracks/quad.hpp" #include "tracks/track.hpp" #include "tracks/track_object_manager.hpp" #include "tracks/track_sector.hpp" @@ -211,10 +213,10 @@ const std::string& SoccerWorld::getIdent() const void SoccerWorld::update(int ticks) { updateBallPosition(ticks); + updateSectorForKarts(); if (Track::getCurrentTrack()->hasNavMesh() && !NetworkConfig::get()->isNetworking()) { - updateSectorForKarts(); updateAIData(); } @@ -808,13 +810,26 @@ int SoccerWorld::getTeamNum(SoccerTeam team) const //----------------------------------------------------------------------------- unsigned int SoccerWorld::getRescuePositionIndex(AbstractKart *kart) { - std::map::const_iterator n = - m_kart_position_map.find(kart->getWorldKartId()); - - assert (n != m_kart_position_map.end()); - return n->second; + int last_valid_node = + getTrackSector(kart->getWorldKartId())->getLastValidGraphNode(); + if (last_valid_node >= 0) + return last_valid_node; + Log::warn("SoccerWorld", "Missing last valid node for rescuing"); + return 0; } // getRescuePositionIndex +//----------------------------------------------------------------------------- +btTransform SoccerWorld::getRescueTransform(unsigned int rescue_pos) const +{ + const Vec3 &xyz = Graph::get()->getQuad(rescue_pos)->getCenter(); + const Vec3 &normal = Graph::get()->getQuad(rescue_pos)->getNormal(); + btTransform pos; + pos.setOrigin(xyz); + btQuaternion q1 = shortestArcQuat(Vec3(0.0f, 1.0f, 0.0f), normal); + pos.setRotation(q1); + return pos; +} // getRescueTransform + //----------------------------------------------------------------------------- void SoccerWorld::enterRaceOverState() { diff --git a/src/modes/soccer_world.hpp b/src/modes/soccer_world.hpp index 3fe790aa5..1d9943e03 100644 --- a/src/modes/soccer_world.hpp +++ b/src/modes/soccer_world.hpp @@ -329,7 +329,8 @@ public: virtual void reset() OVERRIDE; virtual unsigned int getRescuePositionIndex(AbstractKart *kart) OVERRIDE; - + virtual btTransform getRescueTransform(unsigned int rescue_pos) const + OVERRIDE; virtual bool useFastMusicNearEnd() const OVERRIDE { return false; } virtual void getKartsDisplayInfo( std::vector *info) OVERRIDE {} diff --git a/src/tracks/track_sector.cpp b/src/tracks/track_sector.cpp index b57fe5fb5..5f131e7eb 100644 --- a/src/tracks/track_sector.cpp +++ b/src/tracks/track_sector.cpp @@ -74,18 +74,21 @@ void TrackSector::update(const Vec3 &xyz, bool ignore_vertical) prev_sector, test_nodes, ignore_vertical); } - // ArenaGraph (battle and soccer mode) doesn't need the code below - if (ag) return; + // Keep the last valid graph node for arena mode + if (ag) + { + if (prev_sector != Graph::UNKNOWN_SECTOR) + m_last_valid_graph_node = prev_sector; + return; + } // keep the current quad as the latest valid one IF the player has one // of the required checklines const DriveNode* dn = DriveGraph::get()->getNode(m_current_graph_node); const std::vector& checkline_requirements = dn->getChecklineRequirements(); - bool isValidQuad = false; if (checkline_requirements.size() == 0) { - isValidQuad = true; if (m_on_road) m_last_valid_graph_node = m_current_graph_node; } @@ -98,7 +101,6 @@ void TrackSector::update(const Vec3 &xyz, bool ignore_vertical) //has_prerequisite = true; if (m_on_road) m_last_valid_graph_node = m_current_graph_node; - isValidQuad = true; break; } } diff --git a/src/tracks/track_sector.hpp b/src/tracks/track_sector.hpp index 08e60ef32..ed1ee45f4 100644 --- a/src/tracks/track_sector.hpp +++ b/src/tracks/track_sector.hpp @@ -81,6 +81,8 @@ public: bool isOnRoad() const { return m_on_road; } // ------------------------------------------------------------------------ void setLastTriggeredCheckline(int i) { m_last_triggered_checkline = i; } + // ------------------------------------------------------------------------ + int getLastValidGraphNode() const { return m_last_valid_graph_node; } }; // TrackSector From c4ae3dff694535a78fc93c3320c83bd7e757d6c6 Mon Sep 17 00:00:00 2001 From: Benau Date: Fri, 20 Jul 2018 01:42:31 +0800 Subject: [PATCH 07/36] Set the min max values for each mode properly --- src/states_screens/tracks_screen.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/states_screens/tracks_screen.cpp b/src/states_screens/tracks_screen.cpp index d72106858..7862585d6 100644 --- a/src/states_screens/tracks_screen.cpp +++ b/src/states_screens/tracks_screen.cpp @@ -277,12 +277,16 @@ void TracksScreen::init() //I18N: In track screen getWidget("lap-text")->setText(_("Number of goals to win"), false); m_laps->setValue(UserConfigParams::m_num_goals); + m_laps->setMin(1); + m_laps->setMax(10); } else { //I18N: In track screen getWidget("lap-text")->setText(_("Maximum time (min.)"), false); m_laps->setValue(UserConfigParams::m_soccer_time_limit); + m_laps->setMin(1); + m_laps->setMax(15); } getWidget("reverse-text")->setVisible(true); //I18N: In track screen @@ -296,6 +300,8 @@ void TracksScreen::init() //I18N: In track screen getWidget("lap-text")->setText(_("Number of laps"), false); m_laps->setVisible(true); + m_laps->setMin(1); + m_laps->setMax(20); m_laps->setValue(UserConfigParams::m_num_laps); getWidget("reverse-text")->setVisible(true); //I18N: In track screen From f4dced8172776cf2ebeda72a21abcc88293b71df Mon Sep 17 00:00:00 2001 From: "auria.mg" Date: Thu, 19 Jul 2018 20:56:46 -0400 Subject: [PATCH 08/36] A few steps forward for issue #3345, more issues remain --- src/modes/cutscene_world.cpp | 3 ++- src/modes/world_status.hpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/modes/cutscene_world.cpp b/src/modes/cutscene_world.cpp index 8bbfbd3f7..84eb1a862 100644 --- a/src/modes/cutscene_world.cpp +++ b/src/modes/cutscene_world.cpp @@ -56,7 +56,8 @@ CutsceneWorld::CutsceneWorld() : World() { m_time_at_second_reset = 0.0f; m_aborted = false; - WorldStatus::setClockMode(CLOCK_NONE); + WorldStatus::setClockMode(CLOCK_CHRONO); + m_phase = RACE_PHASE; m_use_highscores = false; m_play_track_intro_sound = false; m_play_ready_set_go_sounds = false; diff --git a/src/modes/world_status.hpp b/src/modes/world_status.hpp index 66afdacda..4da315508 100644 --- a/src/modes/world_status.hpp +++ b/src/modes/world_status.hpp @@ -112,9 +112,9 @@ private: protected: bool m_play_track_intro_sound; bool m_play_ready_set_go_sounds; + Phase m_phase; private: - Phase m_phase; /** * Remember previous phase e.g. on pause From a3a5befe63c62462e17ebc773334fa7234828665 Mon Sep 17 00:00:00 2001 From: "auria.mg" Date: Thu, 19 Jul 2018 21:09:33 -0400 Subject: [PATCH 09/36] Keep working on #3345, not there yet --- src/modes/cutscene_world.cpp | 7 ++++++- src/modes/cutscene_world.hpp | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/modes/cutscene_world.cpp b/src/modes/cutscene_world.cpp index 84eb1a862..32a2e6de7 100644 --- a/src/modes/cutscene_world.cpp +++ b/src/modes/cutscene_world.cpp @@ -171,7 +171,12 @@ void CutsceneWorld::init() CutsceneWorld::~CutsceneWorld() { } // ~CutsceneWorld - +//----------------------------------------------------------------------------- +void CutsceneWorld::reset() +{ + World::reset(); + m_phase = RACE_PHASE; +} //----------------------------------------------------------------------------- /** Returns the internal identifier for this race. */ diff --git a/src/modes/cutscene_world.hpp b/src/modes/cutscene_world.hpp index 5b8fd84bc..cc30a7672 100644 --- a/src/modes/cutscene_world.hpp +++ b/src/modes/cutscene_world.hpp @@ -65,6 +65,8 @@ public: virtual void init() OVERRIDE; + virtual void reset() OVERRIDE; + // clock events virtual bool isRaceOver() OVERRIDE; From 2b4d0629117b1760b479aba6c0ec583f5e1e34db Mon Sep 17 00:00:00 2001 From: Benau Date: Fri, 20 Jul 2018 14:09:27 +0800 Subject: [PATCH 10/36] Try to fix the remaining ipo issues --- src/animations/animation_base.hpp | 6 +++--- src/animations/three_d_animation.cpp | 6 ++---- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/animations/animation_base.hpp b/src/animations/animation_base.hpp index 8de3102b7..a462e3823 100644 --- a/src/animations/animation_base.hpp +++ b/src/animations/animation_base.hpp @@ -47,9 +47,6 @@ private: * one time only (which might get triggered more than once). */ enum AnimTimeType { ATT_CYCLIC, ATT_CYCLIC_ONCE } m_anim_type; - /** The current time used in the IPOs. */ - float m_current_time; - /** The inital position of this object. */ Vec3 m_initial_xyz; @@ -67,6 +64,9 @@ protected: float m_animation_duration; + /** The current time used in the IPOs. */ + float m_current_time; + public: AnimationBase(const XMLNode &node); AnimationBase(Ipo *ipo); diff --git a/src/animations/three_d_animation.cpp b/src/animations/three_d_animation.cpp index 5627d0dc0..a1ab67294 100644 --- a/src/animations/three_d_animation.cpp +++ b/src/animations/three_d_animation.cpp @@ -75,15 +75,13 @@ void ThreeDAnimation::updateWithWorldTicks() Vec3 xyz = m_object->getPosition(); Vec3 scale = m_object->getScale(); - float position = 0.0f; if (!m_is_paused) { int cur_ticks = World::getWorld()->getTicksSinceStart(); - float cur_time = stk_config->ticks2Time(cur_ticks); - position = fmodf(cur_time, m_animation_duration); + m_current_time = stk_config->ticks2Time(cur_ticks); } - AnimationBase::getAt(position, &xyz, &m_hpr, &scale); //updates all IPOs + AnimationBase::getAt(m_current_time, &xyz, &m_hpr, &scale); //updates all IPOs //m_node->setPosition(xyz.toIrrVector()); //m_node->setScale(scale.toIrrVector()); From 0e1a5ea285985a050bd341b19cd304c771e9a7de Mon Sep 17 00:00:00 2001 From: Benau Date: Fri, 20 Jul 2018 14:44:53 +0800 Subject: [PATCH 11/36] Properly check for soccer team of players --- src/tracks/track.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/tracks/track.cpp b/src/tracks/track.cpp index 4310abee5..e8c9dd71c 100644 --- a/src/tracks/track.cpp +++ b/src/tracks/track.cpp @@ -714,11 +714,11 @@ void Track::loadArenaGraph(const XMLNode &node) // Only need to test local player if (race_manager->getMinorMode() == RaceManager::MINOR_MODE_SOCCER) { - for (unsigned i = 0; i < race_manager->getNumberOfKarts(); i++) + const unsigned pk = race_manager->getNumPlayers(); + for (unsigned i = 0; i < pk; i++) { - if (race_manager->getKartType(i) != RaceManager::KT_PLAYER) - continue; - if (race_manager->getKartInfo(i).getSoccerTeam() == + if (!race_manager->getKartInfo(i).isNetworkPlayer() && + race_manager->getKartInfo(i).getSoccerTeam() == SOCCER_TEAM_BLUE) m_minimap_invert_x_z = true; break; @@ -1763,6 +1763,7 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id) } CameraEnd::clearEndCameras(); + m_minimap_invert_x_z = false; m_sky_type = SKY_NONE; m_track_object_manager = new TrackObjectManager(); From d4f7d6baaa362e3ec527d20f4b7e32d94f7d2144 Mon Sep 17 00:00:00 2001 From: Benau Date: Fri, 20 Jul 2018 15:46:07 +0800 Subject: [PATCH 12/36] Don't show the polling log if currently server --- src/online/online_player_profile.cpp | 8 ++++++++ src/online/online_player_profile.hpp | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/online/online_player_profile.cpp b/src/online/online_player_profile.cpp index 3ebb7bc33..aeef259a5 100644 --- a/src/online/online_player_profile.cpp +++ b/src/online/online_player_profile.cpp @@ -344,6 +344,14 @@ namespace Online request->queue(); } // requestPoll() + // ------------------------------------------------------------------------ + OnlinePlayerProfile::PollRequest::PollRequest() + : XMLRequest(true) + { + m_disable_sending_log = NetworkConfig::get()->isNetworking() && + NetworkConfig::get()->isServer(); + } // PollRequest + // ------------------------------------------------------------------------ /** Callback for the poll request. Parses the information and spawns * notifications accordingly. diff --git a/src/online/online_player_profile.hpp b/src/online/online_player_profile.hpp index 9f2935b56..2a7b9a222 100644 --- a/src/online/online_player_profile.hpp +++ b/src/online/online_player_profile.hpp @@ -61,7 +61,7 @@ namespace Online { virtual void callback (); public: - PollRequest() : XMLRequest(true) {} + PollRequest(); }; // PollRequest private: From 82b23b6c26114c66719553fa2ddefd47158d0f82 Mon Sep 17 00:00:00 2001 From: Benau Date: Fri, 20 Jul 2018 19:23:18 +0800 Subject: [PATCH 13/36] Fix ghost replay crashes --- src/karts/kart.cpp | 2 ++ src/karts/moveable.cpp | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/karts/kart.cpp b/src/karts/kart.cpp index 97bb92b34..3d3d68b20 100644 --- a/src/karts/kart.cpp +++ b/src/karts/kart.cpp @@ -858,6 +858,8 @@ void Kart::adjustSpeed(float f) */ void Kart::updateWeight() { + if (!m_body) + return; float mass = m_kart_properties->getMass() + m_attachment->weightAdjust(); if (m_weight != mass) { diff --git a/src/karts/moveable.cpp b/src/karts/moveable.cpp index de92b5d21..cf16491fe 100644 --- a/src/karts/moveable.cpp +++ b/src/karts/moveable.cpp @@ -62,7 +62,10 @@ void Moveable::setNode(scene::ISceneNode *n) //----------------------------------------------------------------------------- void Moveable::updateSmoothedGraphics(float dt) { - SmoothNetworkBody::updateSmoothedGraphics(m_transform, getVelocity(), dt); + Vec3 velocity; + if (m_body) + velocity = m_body->getLinearVelocity(); + SmoothNetworkBody::updateSmoothedGraphics(m_transform, velocity, dt); #undef DEBUG_SMOOTHING #ifdef DEBUG_SMOOTHING // Gnuplot compare command From a22fde85ecb46d5bacafd45bcc3087108c9918b7 Mon Sep 17 00:00:00 2001 From: Benau Date: Fri, 20 Jul 2018 19:49:06 +0800 Subject: [PATCH 14/36] Correct ghost kart starting position before start --- src/karts/ghost_kart.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/karts/ghost_kart.cpp b/src/karts/ghost_kart.cpp index 6c7c0c343..058991b7e 100644 --- a/src/karts/ghost_kart.cpp +++ b/src/karts/ghost_kart.cpp @@ -47,6 +47,7 @@ void GhostKart::reset() Kart::reset(); // This will set the correct start position update(0); + updateGraphics(0); m_last_egg_idx = 0; } // reset From ea13d97f6b02393993f8be6dfb860e08945be1b1 Mon Sep 17 00:00:00 2001 From: Deve Date: Sun, 22 Jul 2018 22:48:45 +0200 Subject: [PATCH 15/36] Allow to specify minimum number of players in command line --- src/main.cpp | 27 ++++++++++++++++++++----- src/network/protocols/server_lobby.cpp | 2 +- src/states_screens/networking_lobby.cpp | 4 ++-- 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index d475ff7c3..0a303d139 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -603,6 +603,7 @@ void cmdLineHelp() " --disable-lan Disable LAN detection (connect using WAN).\n" " --auto-connect Automatically connect to fist server and start race\n" " --max-players=n Maximum number of clients (server only).\n" + " --min-players=n Minimum number of clients (server only).\n" " --motd Message showing in all lobby of clients, can specify a .txt file.\n" " --auto-end Automatically end network game after 1st player finished\n" " for some time (currently his finished time * 0.25 + 15.0). \n" @@ -1140,12 +1141,28 @@ int handleCmdLine() NetworkConfig::get()->setServerIdFile( file_manager->getUserConfigFile(s)); } - if(CommandLine::has("--disable-polling")) + if (CommandLine::has("--disable-polling")) + { Online::RequestManager::m_disable_polling = true; - if(CommandLine::has("--max-players", &n)) - UserConfigParams::m_server_max_players=n; - NetworkConfig::get()-> - setMaxPlayers(UserConfigParams::m_server_max_players); + } + if (CommandLine::has("--max-players", &n)) + { + UserConfigParams::m_server_max_players = n; + } + + if (UserConfigParams::m_server_max_players < 1) + { + UserConfigParams::m_server_max_players = 1; + } + NetworkConfig::get()->setMaxPlayers(UserConfigParams::m_server_max_players); + + if (CommandLine::has("--min-players", &n)) + { + float threshold = ((float)(n) - 0.5f) / + UserConfigParams::m_server_max_players; + threshold = std::max(std::min(threshold, 1.0f), 0.0f); + UserConfigParams::m_start_game_threshold = threshold; + } if (CommandLine::has("--port", &n)) { // We don't know if this instance is going to be a client diff --git a/src/network/protocols/server_lobby.cpp b/src/network/protocols/server_lobby.cpp index cff51a07a..e7746949c 100644 --- a/src/network/protocols/server_lobby.cpp +++ b/src/network/protocols/server_lobby.cpp @@ -381,7 +381,7 @@ void ServerLobby::asynchronousUpdate() if (NetworkConfig::get()->isOwnerLess()) { auto players = m_game_setup->getPlayers(); - if (((float)players.size() > + if (((float)players.size() >= (float)NetworkConfig::get()->getMaxPlayers() * UserConfigParams::m_start_game_threshold || m_game_setup->isGrandPrixStarted()) && diff --git a/src/states_screens/networking_lobby.cpp b/src/states_screens/networking_lobby.cpp index ca4b9e3d1..a7b8a84cf 100644 --- a/src/states_screens/networking_lobby.cpp +++ b/src/states_screens/networking_lobby.cpp @@ -213,7 +213,7 @@ void NetworkingLobby::onUpdate(float delta) if (m_timeout_message->isVisible() && m_player_list) { float cur_player = (float)(m_player_list->getItemCount()); - if (cur_player > m_server_max_player * m_start_threshold && + if (cur_player >= m_server_max_player * m_start_threshold && m_cur_starting_timer == std::numeric_limits::max()) { m_cur_starting_timer = m_start_timeout; @@ -226,7 +226,7 @@ void NetworkingLobby::onUpdate(float delta) core::stringw msg = _P("Game will start if there is more than %d player.", "Game will start if there are more than %d players.", - (int)floor(m_server_max_player * m_start_threshold)); + (int)ceil(m_server_max_player * m_start_threshold) - 1); m_timeout_message->setText(msg, true); } From 39e218b2dc685b8a8983d72fb132c13d4ca42d53 Mon Sep 17 00:00:00 2001 From: hiker Date: Mon, 23 Jul 2018 09:28:12 +1000 Subject: [PATCH 16/36] Try to fix server-only build ... now non-server build is broken :( --- CMakeLists.txt | 1 + lib/irrlicht/CMakeLists.txt | 9 +++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e3dc736ee..5a028c745 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -113,6 +113,7 @@ if(WIN32) set(ENV{OPENALDIR} ${PROJECT_SOURCE_DIR}/${DEPENDENCIES}) add_definitions(-D_IRR_STATIC_LIB_) add_definitions(-DNO_IRR_COMPILE_WITH_X11_) + include_directories(${PROJECT_SOURCE_DIR}/${DEPENDENCIES}/include) endif() if(USE_GLES2) diff --git a/lib/irrlicht/CMakeLists.txt b/lib/irrlicht/CMakeLists.txt index 3c5a3907b..fb26e5739 100644 --- a/lib/irrlicht/CMakeLists.txt +++ b/lib/irrlicht/CMakeLists.txt @@ -1,10 +1,6 @@ # CMakeLists.txt for Irrlicht in STK -find_package(PNG REQUIRED) -find_package(JPEG REQUIRED) include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include/" - "${JPEG_INCLUDE_DIR}" - "${PNG_INCLUDE_DIRS}" "${ZLIB_INCLUDE_DIR}") if(MSVC OR APPLE) @@ -13,6 +9,11 @@ if(MSVC OR APPLE) endif() if(NOT SERVER_ONLY) + find_package(PNG REQUIRED) + find_package(JPEG REQUIRED) + include_directories("${JPEG_INCLUDE_DIR}" + "${PNG_INCLUDE_DIRS}") + if(NOT USE_GLES2) find_package(OpenGL REQUIRED) include_directories(${OPENGL_INCLUDE_DIR}) From 00a22a727a01674cfad9cf5245b6cfed2f42ab6d Mon Sep 17 00:00:00 2001 From: Benau Date: Mon, 23 Jul 2018 08:29:37 +0800 Subject: [PATCH 17/36] Check minimap invert for all players (required in network) --- src/tracks/track.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/tracks/track.cpp b/src/tracks/track.cpp index e8c9dd71c..3256a0ed0 100644 --- a/src/tracks/track.cpp +++ b/src/tracks/track.cpp @@ -720,8 +720,10 @@ void Track::loadArenaGraph(const XMLNode &node) if (!race_manager->getKartInfo(i).isNetworkPlayer() && race_manager->getKartInfo(i).getSoccerTeam() == SOCCER_TEAM_BLUE) + { m_minimap_invert_x_z = true; - break; + break; + } } } From 56b71e97ad74f6778185ac7e1146061f8382ced5 Mon Sep 17 00:00:00 2001 From: Benau Date: Mon, 23 Jul 2018 08:41:59 +0800 Subject: [PATCH 18/36] Remove unused class --- sources.cmake | 2 +- src/tracks/ambient_light_sphere.cpp | 91 ----------------------------- src/tracks/ambient_light_sphere.hpp | 60 ------------------- src/tracks/check_manager.cpp | 2 +- 4 files changed, 2 insertions(+), 153 deletions(-) delete mode 100644 src/tracks/ambient_light_sphere.cpp delete mode 100644 src/tracks/ambient_light_sphere.hpp diff --git a/sources.cmake b/sources.cmake index d4f28ae4d..ba4868d71 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/tracks/ambient_light_sphere.cpp b/src/tracks/ambient_light_sphere.cpp deleted file mode 100644 index bf31836c3..000000000 --- a/src/tracks/ambient_light_sphere.cpp +++ /dev/null @@ -1,91 +0,0 @@ -// -// SuperTuxKart - a fun racing game with go-kart -// Copyright (C) 2009-2015 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 "tracks/ambient_light_sphere.hpp" - -#include -#include - -#include "graphics/camera.hpp" -#include "io/xml_node.hpp" -#include "karts/abstract_kart.hpp" -#include "race/race_manager.hpp" -#include "tracks/track.hpp" - -/** Constructor for a checksphere. - * \param node XML node containing the parameters for this checkline. - */ -AmbientLightSphere::AmbientLightSphere(const XMLNode &node, - unsigned int index) - : CheckSphere(node, index) -{ - m_ambient_color = video::SColor(255, 0, 255, 0); // green - m_inner_radius2 = 1; - node.get("inner-radius", &m_inner_radius2); - m_inner_radius2 *= m_inner_radius2; // store the squared value - node.get("color", &m_ambient_color); -} // AmbientLightSphere - -// ---------------------------------------------------------------------------- -void AmbientLightSphere::update(float dt) -{ - CheckStructure::update(dt); - - for(unsigned int i=0; igetKart(); - if(!kart) continue; - if(isInside(i)) - { - float d2=getDistance2ForKart(i); - video::SColor color; - Track *track=Track::getCurrentTrack(); - if(d2 use new ambient color - color = m_ambient_color; - } - else // Interpolate between default and this ambient color - { - float f = (getRadius2()-d2)/(getRadius2()-m_inner_radius2); - const video::SColor &def = track->getDefaultAmbientColor(); - color = m_ambient_color.getInterpolated(def, f); - } - camera->setAmbientLight(color); - } // if active - } // for igetKart()->getWorldKartId()==indx) - return CheckSphere::isTriggered(old_pos, new_pos, indx); - } - return false; -} // isTriggered diff --git a/src/tracks/ambient_light_sphere.hpp b/src/tracks/ambient_light_sphere.hpp deleted file mode 100644 index d3dd28d93..000000000 --- a/src/tracks/ambient_light_sphere.hpp +++ /dev/null @@ -1,60 +0,0 @@ -// -// SuperTuxKart - a fun racing game with go-kart -// Copyright (C) 2009-2015 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_AMBIENT_LIGHT_SPHERE_HPP -#define HEADER_AMBIENT_LIGHT_SPHERE_HPP - -#include -using namespace irr; - -#include "tracks/check_sphere.hpp" - -class XMLNode; -class CheckManager; - -/** - * \brief This class implements a check sphere that is used to change the ambient - * light if a kart is inside this sphere. - * - * Besides a normal radius this sphere also has a 2nd 'inner' radius: player karts - * inside the inner radius will have the full new ambient light, karts outside the - * default light, and karts in between will mix the light dependent on distance. - * - * \ingroup tracks - */ -class AmbientLightSphere : public CheckSphere -{ -private: - /** The inner radius defines the area during which the ambient light - * is extrapolated. The square of the value specified in the scene - * file is stored. */ - float m_inner_radius2; - - /** THe full ambient color to use once the kart is inside the - * inner radius. */ - video::SColor m_ambient_color; -public: - AmbientLightSphere(const XMLNode &node, unsigned int index); - virtual ~AmbientLightSphere() {}; - virtual void update(float dt); - virtual bool isTriggered(const Vec3 &old_pos, const Vec3 &new_pos, - unsigned int indx); -}; // AmbientLightSphere - -#endif - diff --git a/src/tracks/check_manager.cpp b/src/tracks/check_manager.cpp index 19c9a85c3..a678aeac5 100644 --- a/src/tracks/check_manager.cpp +++ b/src/tracks/check_manager.cpp @@ -23,11 +23,11 @@ #include "io/xml_node.hpp" #include "karts/abstract_kart.hpp" -#include "tracks/ambient_light_sphere.hpp" #include "tracks/check_cannon.hpp" #include "tracks/check_goal.hpp" #include "tracks/check_lap.hpp" #include "tracks/check_line.hpp" +#include "tracks/check_sphere.hpp" #include "tracks/check_structure.hpp" #include "tracks/drive_graph.hpp" #include "utils/log.hpp" From d18e963ea617888c207b2f1c6f82d5d1893abdd9 Mon Sep 17 00:00:00 2001 From: hiker Date: Mon, 23 Jul 2018 12:51:59 +1000 Subject: [PATCH 19/36] Added Benau's new version. --- lib/irrlicht/CMakeLists.txt | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) mode change 100644 => 100755 lib/irrlicht/CMakeLists.txt diff --git a/lib/irrlicht/CMakeLists.txt b/lib/irrlicht/CMakeLists.txt old mode 100644 new mode 100755 index fb26e5739..bf25ef1a5 --- a/lib/irrlicht/CMakeLists.txt +++ b/lib/irrlicht/CMakeLists.txt @@ -1,18 +1,17 @@ # CMakeLists.txt for Irrlicht in STK - -include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include/" - "${ZLIB_INCLUDE_DIR}") - -if(MSVC OR APPLE) - include_directories("${CMAKE_CURRENT_BINARY_DIR}/../zlib/" # For zconf.h on WIN32 - "${CMAKE_CURRENT_BINARY_DIR}/../libpng/") -endif() - if(NOT SERVER_ONLY) find_package(PNG REQUIRED) find_package(JPEG REQUIRED) - include_directories("${JPEG_INCLUDE_DIR}" - "${PNG_INCLUDE_DIRS}") + + include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include/" + "${JPEG_INCLUDE_DIR}" + "${PNG_INCLUDE_DIRS}" + "${ZLIB_INCLUDE_DIR}") + + if(MSVC OR APPLE) + include_directories("${CMAKE_CURRENT_BINARY_DIR}/../zlib/" # For zconf.h on WIN32 + "${CMAKE_CURRENT_BINARY_DIR}/../libpng/") + endif() if(NOT USE_GLES2) find_package(OpenGL REQUIRED) @@ -59,6 +58,11 @@ if(NOT SERVER_ONLY) endif() endif() else() + include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include/" + "${ZLIB_INCLUDE_DIR}") + if(MSVC OR APPLE) + include_directories("${CMAKE_CURRENT_BINARY_DIR}/../zlib/") + endif() add_definitions(-DNO_IRR_COMPILE_WITH_LIBPNG_) add_definitions(-DNO_IRR_COMPILE_WITH_LIBJPEG_) add_definitions(-DNO_IRR_COMPILE_WITH_BMP_LOADER_) @@ -619,4 +623,4 @@ endif() if(WIN32) target_link_libraries(stkirrlicht imm32 xinput9_1_0) -endif() +endif() \ No newline at end of file From b6c893b03e2c9dc5b76329a460dc0eb8ce3f5013 Mon Sep 17 00:00:00 2001 From: Benau Date: Mon, 23 Jul 2018 13:27:14 +0800 Subject: [PATCH 20/36] Try to fix server only build in linux --- lib/irrlicht/CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) mode change 100755 => 100644 lib/irrlicht/CMakeLists.txt diff --git a/lib/irrlicht/CMakeLists.txt b/lib/irrlicht/CMakeLists.txt old mode 100755 new mode 100644 index bf25ef1a5..30b4b2955 --- a/lib/irrlicht/CMakeLists.txt +++ b/lib/irrlicht/CMakeLists.txt @@ -62,6 +62,8 @@ else() "${ZLIB_INCLUDE_DIR}") if(MSVC OR APPLE) include_directories("${CMAKE_CURRENT_BINARY_DIR}/../zlib/") + else() + find_package(ZLIB REQUIRED) endif() add_definitions(-DNO_IRR_COMPILE_WITH_LIBPNG_) add_definitions(-DNO_IRR_COMPILE_WITH_LIBJPEG_) @@ -623,4 +625,4 @@ endif() if(WIN32) target_link_libraries(stkirrlicht imm32 xinput9_1_0) -endif() \ No newline at end of file +endif() From a1ba27bc453657b5b80c32f2b097ad33969f37db Mon Sep 17 00:00:00 2001 From: hiker Date: Mon, 23 Jul 2018 15:40:25 +1000 Subject: [PATCH 21/36] Try again to fix our build environment in server only mode. --- lib/irrlicht/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/irrlicht/CMakeLists.txt b/lib/irrlicht/CMakeLists.txt index 30b4b2955..2dd3d80a5 100644 --- a/lib/irrlicht/CMakeLists.txt +++ b/lib/irrlicht/CMakeLists.txt @@ -58,12 +58,12 @@ if(NOT SERVER_ONLY) endif() endif() else() - include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include/" - "${ZLIB_INCLUDE_DIR}") + include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include/") if(MSVC OR APPLE) include_directories("${CMAKE_CURRENT_BINARY_DIR}/../zlib/") else() find_package(ZLIB REQUIRED) + include_directories("${ZLIB_INCLUDE_DIR}") endif() add_definitions(-DNO_IRR_COMPILE_WITH_LIBPNG_) add_definitions(-DNO_IRR_COMPILE_WITH_LIBJPEG_) From 1a9f0163e00d28d8c592af0ab1f12806da97bcf1 Mon Sep 17 00:00:00 2001 From: hiker Date: Mon, 23 Jul 2018 17:52:12 +1000 Subject: [PATCH 22/36] Try to fix odd behaviour of soccer ball. --- src/modes/soccer_world.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/modes/soccer_world.cpp b/src/modes/soccer_world.cpp index ac5b3dc0d..3f014b2fb 100644 --- a/src/modes/soccer_world.cpp +++ b/src/modes/soccer_world.cpp @@ -122,6 +122,7 @@ void SoccerWorld::init() Log::fatal("SoccerWorld","Ball is missing in soccer field, abort."); m_bgd.init(m_ball->getPhysicalObject()->getRadius()); + m_ball_body->setActivationState(DISABLE_DEACTIVATION); } // init From 973b29980dd260abd3fdd0ada7228332ebe11685 Mon Sep 17 00:00:00 2001 From: Marianne Gagnon Date: Mon, 23 Jul 2018 19:58:15 -0400 Subject: [PATCH 23/36] Fix #3347 --- lib/irrlicht/CMakeLists.txt | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/irrlicht/CMakeLists.txt b/lib/irrlicht/CMakeLists.txt index 2dd3d80a5..419caf9a6 100644 --- a/lib/irrlicht/CMakeLists.txt +++ b/lib/irrlicht/CMakeLists.txt @@ -8,9 +8,12 @@ if(NOT SERVER_ONLY) "${PNG_INCLUDE_DIRS}" "${ZLIB_INCLUDE_DIR}") + if(MSVC) + include_directories("${CMAKE_CURRENT_BINARY_DIR}/../zlib/") # For zconf.h on WIN32 + endif() + if(MSVC OR APPLE) - include_directories("${CMAKE_CURRENT_BINARY_DIR}/../zlib/" # For zconf.h on WIN32 - "${CMAKE_CURRENT_BINARY_DIR}/../libpng/") + include_directories("${CMAKE_CURRENT_BINARY_DIR}/../libpng/") endif() if(NOT USE_GLES2) @@ -59,7 +62,7 @@ if(NOT SERVER_ONLY) endif() else() include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include/") - if(MSVC OR APPLE) + if(MSVC) include_directories("${CMAKE_CURRENT_BINARY_DIR}/../zlib/") else() find_package(ZLIB REQUIRED) From 6369256022cc9634573bd3161ae469d328eb7e90 Mon Sep 17 00:00:00 2001 From: Benau Date: Tue, 24 Jul 2018 14:18:43 +0800 Subject: [PATCH 24/36] Reset rewinding manager at each online or offline game --- src/modes/world.cpp | 2 +- src/network/protocols/lobby_protocol.cpp | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/modes/world.cpp b/src/modes/world.cpp index 2d434bf7b..fafccb261 100644 --- a/src/modes/world.cpp +++ b/src/modes/world.cpp @@ -120,7 +120,7 @@ World* World::m_world = NULL; */ World::World() : WorldStatus() { - + RewindManager::setEnable(NetworkConfig::get()->isNetworking()); #ifdef DEBUG m_magic_number = 0xB01D6543; #endif diff --git a/src/network/protocols/lobby_protocol.cpp b/src/network/protocols/lobby_protocol.cpp index db6850259..7813238ea 100644 --- a/src/network/protocols/lobby_protocol.cpp +++ b/src/network/protocols/lobby_protocol.cpp @@ -28,7 +28,6 @@ #include "network/protocols/game_protocol.hpp" #include "network/protocols/game_events_protocol.hpp" #include "network/race_event_manager.hpp" -#include "network/rewind_manager.hpp" #include "race/race_manager.hpp" #include "states_screens/state_manager.hpp" @@ -59,8 +58,6 @@ LobbyProtocol::~LobbyProtocol() void LobbyProtocol::loadWorld() { Log::info("LobbyProtocol", "Ready !"); - RewindManager::setEnable(true); - // Race startup sequence // --------------------- // This creates the network world. From bbf5c54f874db8fbd4f85d31faf9e58057454cd2 Mon Sep 17 00:00:00 2001 From: Benau Date: Tue, 24 Jul 2018 14:21:42 +0800 Subject: [PATCH 25/36] Use rewinder with shared_ptr for easier item destroy handling --- src/items/network_item_manager.cpp | 3 +- src/karts/kart_rewinder.cpp | 3 +- src/network/rewind_info.cpp | 5 +-- src/network/rewind_manager.cpp | 49 +++++++++++++++++++----------- src/network/rewind_manager.hpp | 43 ++++++++++++++------------ src/network/rewind_queue.cpp | 11 ++++--- src/network/rewind_queue.hpp | 3 +- src/network/rewinder.cpp | 26 +++------------- src/network/rewinder.hpp | 32 +++++++++---------- src/physics/physical_object.cpp | 1 - 10 files changed, 87 insertions(+), 89 deletions(-) diff --git a/src/items/network_item_manager.cpp b/src/items/network_item_manager.cpp index f07235b28..0388bb411 100644 --- a/src/items/network_item_manager.cpp +++ b/src/items/network_item_manager.cpp @@ -39,8 +39,7 @@ void NetworkItemManager::create() /** Creates a new instance of the item manager. This is done at startup * of each race. */ NetworkItemManager::NetworkItemManager() - : Rewinder("N", /*can be deleted*/false), - ItemManager() + : Rewinder("N"), ItemManager() { m_last_confirmed_item_ticks.clear(); diff --git a/src/karts/kart_rewinder.cpp b/src/karts/kart_rewinder.cpp index 83e8edf0c..1d4de3f1a 100644 --- a/src/karts/kart_rewinder.cpp +++ b/src/karts/kart_rewinder.cpp @@ -38,8 +38,7 @@ KartRewinder::KartRewinder(const std::string& ident, const btTransform& init_transform, PerPlayerDifficulty difficulty, std::shared_ptr ri) - : Rewinder(std::string("K") + StringUtils::toString(world_kart_id), - /*can_be_destroyed*/ false) + : Rewinder(std::string("K") + StringUtils::toString(world_kart_id)) , Kart(ident, world_kart_id, position, init_transform, difficulty, ri) { diff --git a/src/network/rewind_info.cpp b/src/network/rewind_info.cpp index e0c19cd10..c0da5fa6f 100644 --- a/src/network/rewind_info.cpp +++ b/src/network/rewind_info.cpp @@ -64,8 +64,9 @@ void RewindInfoState::restore() for (const std::string& name : m_rewinder_using) { uint16_t count = m_buffer->getUInt16(); - Rewinder* r = RewindManager::get()->getRewinder(name); - if (r == NULL) + std::shared_ptr r = + RewindManager::get()->getRewinder(name); + if (!r) { Log::error("RewindInfoState", "Missing rewinder %s", name.c_str()); diff --git a/src/network/rewind_manager.cpp b/src/network/rewind_manager.cpp index eb37d92b2..88eff9409 100644 --- a/src/network/rewind_manager.cpp +++ b/src/network/rewind_manager.cpp @@ -82,18 +82,7 @@ void RewindManager::reset() if (!m_enable_rewind_manager) return; - for (auto it = m_all_rewinder.begin(); it != m_all_rewinder.end();) - { - if (!it->second->canBeDestroyed()) - { - it++; - continue; - } - Rewinder* rewinder = it->second; - it = m_all_rewinder.erase(it); - delete rewinder; - } - + clearExpiredRewinder(); m_rewind_queue.reset(); } // reset @@ -166,7 +155,9 @@ void RewindManager::saveState() { // TODO: check if it's worth passing in a sufficiently large buffer from // GameProtocol - this would save the copy operation. - BareNetworkString* buffer = p.second->saveState(&rewinder_using); + BareNetworkString* buffer = NULL; + if (auto r = p.second.lock()) + buffer = r->saveState(&rewinder_using); if (buffer != NULL) { m_overall_state_size += buffer->size(); @@ -197,12 +188,16 @@ void RewindManager::update(int ticks_not_used) if (ticks - m_last_saved_state < m_state_frequency) return; - // Save state + // Save state, remove expired rewinder first + clearExpiredRewinder(); if (NetworkConfig::get()->isClient()) { auto& ret = m_local_state[ticks]; for (auto& p : m_all_rewinder) - ret.push_back(p.second->getLocalStateRestoreFunction()); + { + if (auto r = p.second.lock()) + ret.push_back(r->getLocalStateRestoreFunction()); + } } else { @@ -255,6 +250,20 @@ void RewindManager::playEventsTill(int world_ticks, int *ticks) m_is_rewinding = false; } // playEventsTill +// ---------------------------------------------------------------------------- +/** Adds a Rewinder to the list of all rewinders. + * \return true If successfully added, false otherwise. + */ +bool RewindManager::addRewinder(std::shared_ptr rewinder) +{ + if (!m_enable_rewind_manager) return false; + // Maximum 1 bit to store no of rewinder used + if (m_all_rewinder.size() == 255) + return false; + m_all_rewinder[rewinder->getUniqueIdentity()] = rewinder; + return true; +} // addRewinder + // ---------------------------------------------------------------------------- /** Rewinds to the specified time, then goes forward till the current * World::getTime() is reached again: it will replay everything before @@ -274,7 +283,10 @@ void RewindManager::rewindTo(int rewind_ticks, int now_ticks) // can be computed between the transforms before and after // the rewind. for (auto& p : m_all_rewinder) - p.second->saveTransform(); + { + if (auto r = p.second.lock()) + r->saveTransform(); + } // Then undo the rewind infos going backwards in time // -------------------------------------------------- @@ -348,7 +360,10 @@ void RewindManager::rewindTo(int rewind_ticks, int now_ticks) // Now compute the errors which need to be visually smoothed for (auto& p : m_all_rewinder) - p.second->computeError(); + { + if (auto r = p.second.lock()) + r->computeError(); + } history->setReplayHistory(is_history); m_is_rewinding = false; diff --git a/src/network/rewind_manager.hpp b/src/network/rewind_manager.hpp index ef945b34b..a8aa929a8 100644 --- a/src/network/rewind_manager.hpp +++ b/src/network/rewind_manager.hpp @@ -19,7 +19,6 @@ #ifndef HEADER_REWIND_MANAGER_HPP #define HEADER_REWIND_MANAGER_HPP -#include "network/rewinder.hpp" #include "network/rewind_queue.hpp" #include "utils/ptr_vector.hpp" #include "utils/synchronised.hpp" @@ -27,9 +26,11 @@ #include #include #include +#include #include #include +class Rewinder; class RewindInfo; class EventRewinder; @@ -93,7 +94,7 @@ private: std::map > > m_local_state; /** A list of all objects that can be rewound. */ - std::map m_all_rewinder; + std::map > m_all_rewinder; /** The queue that stores all rewind infos. */ RewindQueue m_rewind_queue; @@ -117,6 +118,19 @@ private: RewindManager(); ~RewindManager(); + // ------------------------------------------------------------------------ + void clearExpiredRewinder() + { + for (auto it = m_all_rewinder.begin(); it != m_all_rewinder.end();) + { + if (it->second.expired()) + { + it = m_all_rewinder.erase(it); + continue; + } + it++; + } + } public: // First static functions to manage rewinding. @@ -151,27 +165,18 @@ public: void addNetworkState(BareNetworkString *buffer, int ticks); void saveState(); // ------------------------------------------------------------------------ - Rewinder* getRewinder(const std::string& name) + std::shared_ptr getRewinder(const std::string& name) { auto it = m_all_rewinder.find(name); - if (it == m_all_rewinder.end()) - return NULL; - return it->second; + if (it != m_all_rewinder.end()) + { + if (auto r = it->second.lock()) + return r; + } + return nullptr; } // ------------------------------------------------------------------------ - /** Adds a Rewinder to the list of all rewinders. - * \return true If rewinding is enabled, false otherwise. - */ - bool addRewinder(Rewinder *rewinder) - { - if (!m_enable_rewind_manager) return false; - // Maximum 1 bit to store no of rewinder used - if (m_all_rewinder.size() == 255) - return false; - m_all_rewinder[rewinder->getUniqueIdentity()] = rewinder; - return true; - } // addRewinder - + bool addRewinder(std::shared_ptr rewinder); // ------------------------------------------------------------------------ /** Returns true if currently a rewind is happening. */ bool isRewinding() const { return m_is_rewinding; } diff --git a/src/network/rewind_queue.cpp b/src/network/rewind_queue.cpp index ab14482d6..4e8bca753 100644 --- a/src/network/rewind_queue.cpp +++ b/src/network/rewind_queue.cpp @@ -21,6 +21,7 @@ #include "config/stk_config.hpp" #include "modes/world.hpp" #include "network/network_config.hpp" +#include "network/rewinder.hpp" #include "network/rewind_info.hpp" #include "network/rewind_manager.hpp" @@ -418,9 +419,9 @@ void RewindQueue::unitTesting() virtual void rewind(BareNetworkString *s) {} virtual void saveTransform() {} virtual void computeError() {} - DummyRewinder() : Rewinder("dummy_rewinder", true) {} + DummyRewinder() : Rewinder() {} }; - DummyRewinder *dummy_rewinder = new DummyRewinder(); + auto dummy_rewinder = std::make_shared(); // First tests: add a state first, then an event, and make // sure the state stays first @@ -434,7 +435,7 @@ void RewindQueue::unitTesting() assert(q0.hasMoreRewindInfo()); assert(q0.undoUntil(0) == 0); - q0.addNetworkEvent(dummy_rewinder, NULL, 0); + q0.addNetworkEvent(dummy_rewinder.get(), NULL, 0); // Network events are not immediately merged assert(q0.m_all_rewind_info.size() == 1); @@ -462,9 +463,9 @@ void RewindQueue::unitTesting() assert((*rii)->isEvent()); // Test time base comparisons: adding an event to the end - q0.addLocalEvent(dummy_rewinder, NULL, true, 4); + q0.addLocalEvent(dummy_rewinder.get(), NULL, true, 4); // Then adding an earlier event - q0.addLocalEvent(dummy_rewinder, NULL, false, 1); + q0.addLocalEvent(dummy_rewinder.get(), NULL, false, 1); // rii points to the 3rd element, the ones added just now // should be elements4 and 5: rii++; diff --git a/src/network/rewind_queue.hpp b/src/network/rewind_queue.hpp index 98f03290b..90f1b39fc 100644 --- a/src/network/rewind_queue.hpp +++ b/src/network/rewind_queue.hpp @@ -19,14 +19,13 @@ #ifndef HEADER_REWIND_QUEUE_HPP #define HEADER_REWIND_QUEUE_HPP -#include "network/rewinder.hpp" -#include "utils/ptr_vector.hpp" #include "utils/synchronised.hpp" #include #include #include +class BareNetworkString; class EventRewinder; class RewindInfo; class TimeStepInfo; diff --git a/src/network/rewinder.cpp b/src/network/rewinder.cpp index 48b8c9b41..9d6e39037 100644 --- a/src/network/rewinder.cpp +++ b/src/network/rewinder.cpp @@ -20,27 +20,11 @@ #include "network/rewind_manager.hpp" -/** Constructor. It will add this object to the list of all rewindable +// ---------------------------------------------------------------------------- +/** Add this object to the list of all rewindable * objects in the rewind manager. */ -Rewinder::Rewinder(const std::string& ui, bool can_be_destroyed, bool auto_add) - : m_unique_identity(ui) +bool Rewinder::add() { - assert(!m_unique_identity.empty() && m_unique_identity.size() < 255); - m_can_be_destroyed = can_be_destroyed; - if (auto_add) - add(); -} // Rewinder - -// ---------------------------------------------------------------------------- -/** Destructor. - */ -Rewinder::~Rewinder() -{ -} // ~Rewinder - -// ---------------------------------------------------------------------------- -void Rewinder::add() -{ - RewindManager::get()->addRewinder(this); -} // Rewinder + return RewindManager::get()->addRewinder(shared_from_this()); +} // add diff --git a/src/network/rewinder.hpp b/src/network/rewinder.hpp index 364023d29..952aca1cc 100644 --- a/src/network/rewinder.hpp +++ b/src/network/rewinder.hpp @@ -19,33 +19,26 @@ #ifndef HEADER_REWINDER_HPP #define HEADER_REWINDER_HPP +#include #include #include +#include #include class BareNetworkString; -class Rewinder +class Rewinder : public std::enable_shared_from_this { protected: - void add(); - // ------------------------------------------------------------------------- void setUniqueIdentity(const std::string& uid) { m_unique_identity = uid; } private: std::string m_unique_identity; - /** True if this object can be destroyed, i.e. if this object is a 'stand - * alone' (i.e. not used in inheritance). If the object is used in - * inheritance (e.g. KartRewinder, which is a Rewinder and Kart), then - * freeing the kart will free this rewinder instance as well. - */ - bool m_can_be_destroyed; - public: - Rewinder(const std::string& ui, bool can_be_destroyed, - bool auto_add = true); - virtual ~Rewinder(); + Rewinder(const std::string& ui = "") { m_unique_identity = ui; } + + virtual ~Rewinder() {} /** Called before a rewind. Is used to save the previous position of an * object before a rewind, so that the error due to a rewind can be @@ -89,14 +82,17 @@ public: /** Nothing to do here. */ virtual void reset() {} // ------------------------------------------------------------------------- - /** True if this rewinder can be destroyed. Karts can not be destroyed, - * cakes can. This is used by the RewindManager in reset. */ - bool canBeDestroyed() const { return m_can_be_destroyed; } - // ------------------------------------------------------------------------- virtual std::function getLocalStateRestoreFunction() { return nullptr; } // ------------------------------------------------------------------------- - const std::string& getUniqueIdentity() const { return m_unique_identity; } + const std::string& getUniqueIdentity() const + { + assert(!m_unique_identity.empty() && m_unique_identity.size() < 255); + return m_unique_identity; + } + // ------------------------------------------------------------------------- + bool add(); + }; // Rewinder #endif diff --git a/src/physics/physical_object.cpp b/src/physics/physical_object.cpp index d7434414e..fd5338084 100644 --- a/src/physics/physical_object.cpp +++ b/src/physics/physical_object.cpp @@ -136,7 +136,6 @@ PhysicalObject* PhysicalObject::fromXML(bool is_dynamic, PhysicalObject::PhysicalObject(bool is_dynamic, const PhysicalObject::Settings& settings, TrackObject* object) - : Rewinder("P", false/*can_be_destroyed*/, false/*auto_add*/) { m_shape = NULL; m_body = NULL; From 60bfc1840bf91c10ebec05a41450694ee0e21acd Mon Sep 17 00:00:00 2001 From: Benau Date: Tue, 24 Jul 2018 14:22:20 +0800 Subject: [PATCH 26/36] Port rewinders to use shared_ptr --- src/items/item_manager.cpp | 18 ++++---- src/items/item_manager.hpp | 9 ++-- src/items/network_item_manager.cpp | 5 ++- src/items/network_item_manager.hpp | 2 +- src/items/powerup_manager.cpp | 4 +- src/items/powerup_manager.hpp | 1 - src/modes/linear_world.cpp | 16 +++---- src/modes/profile_world.cpp | 27 ++++++------ src/modes/profile_world.hpp | 8 ++-- src/modes/soccer_world.cpp | 37 ++++++++-------- src/modes/soccer_world.hpp | 8 ++-- src/modes/standard_race.cpp | 4 +- src/modes/three_strikes_battle.cpp | 6 +-- src/modes/world.cpp | 70 +++++++++++++++--------------- src/modes/world.hpp | 13 +++--- src/modes/world_with_rank.cpp | 2 +- src/network/rewind_info.cpp | 2 +- src/network/rewind_info.hpp | 1 - src/network/rewinder.cpp | 4 +- src/network/rewinder.hpp | 2 +- src/physics/btKartRaycast.cpp | 2 - src/physics/physical_object.cpp | 9 ++-- src/physics/physical_object.hpp | 4 +- src/race/history.cpp | 4 +- src/replay/replay_play.cpp | 18 ++++---- src/replay/replay_play.hpp | 6 +-- src/tracks/track_object.cpp | 14 +++--- src/tracks/track_object.hpp | 9 ++-- 28 files changed, 154 insertions(+), 151 deletions(-) diff --git a/src/items/item_manager.cpp b/src/items/item_manager.cpp index 4fcf76c8e..49842321a 100644 --- a/src/items/item_manager.cpp +++ b/src/items/item_manager.cpp @@ -43,19 +43,20 @@ #include -std::vector ItemManager::m_item_mesh; -std::vector ItemManager::m_item_lowres_mesh; -std::vector ItemManager::m_glow_color; -bool ItemManager::m_disable_item_collection = false; -ItemManager * ItemManager::m_item_manager = NULL; -std::mt19937 ItemManager::m_random_engine; +std::vector ItemManager::m_item_mesh; +std::vector ItemManager::m_item_lowres_mesh; +std::vector ItemManager::m_glow_color; +bool ItemManager::m_disable_item_collection = false; +std::shared_ptr ItemManager::m_item_manager; +std::mt19937 ItemManager::m_random_engine; //----------------------------------------------------------------------------- /** Creates one instance of the item manager. */ void ItemManager::create() { assert(!m_item_manager); - m_item_manager = new ItemManager(); + // Due to protected constructor use new instead of make_shared + m_item_manager = std::shared_ptr(new ItemManager()); } // create //----------------------------------------------------------------------------- @@ -63,8 +64,7 @@ void ItemManager::create() void ItemManager::destroy() { assert(m_item_manager); - delete m_item_manager; - m_item_manager = NULL; + m_item_manager = nullptr; } // destroy //----------------------------------------------------------------------------- diff --git a/src/items/item_manager.hpp b/src/items/item_manager.hpp index 53924b5bc..83f5f9a9e 100644 --- a/src/items/item_manager.hpp +++ b/src/items/item_manager.hpp @@ -60,7 +60,7 @@ private: static std::mt19937 m_random_engine; protected: /** The instance of ItemManager while a race is on. */ - static ItemManager *m_item_manager; + static std::shared_ptr m_item_manager; public: static void loadDefaultItemMeshes(); static void removeTextures(); @@ -90,9 +90,10 @@ public: // ------------------------------------------------------------------------ /** Return an instance of the item manager (it does not automatically * create one, call create for that). */ - static ItemManager *get() { + static ItemManager *get() + { assert(m_item_manager); - return m_item_manager; + return m_item_manager.get(); } // get // ======================================================================== @@ -119,9 +120,9 @@ protected: virtual unsigned int insertItem(Item *item); void setSwitchItems(const std::vector &switch_items); ItemManager(); +public: virtual ~ItemManager(); -public: virtual Item* placeItem (ItemState::ItemType type, const Vec3& xyz, const Vec3 &normal); virtual Item* dropNewItem (ItemState::ItemType type, diff --git a/src/items/network_item_manager.cpp b/src/items/network_item_manager.cpp index 0388bb411..b1070f228 100644 --- a/src/items/network_item_manager.cpp +++ b/src/items/network_item_manager.cpp @@ -31,10 +31,11 @@ void NetworkItemManager::create() { assert(!m_item_manager); - m_item_manager = new NetworkItemManager(); + auto nim = std::shared_ptr(new NetworkItemManager()); + nim->rewinderAdd(); + m_item_manager = nim; } // create - // ============================================================================ /** Creates a new instance of the item manager. This is done at startup * of each race. */ diff --git a/src/items/network_item_manager.hpp b/src/items/network_item_manager.hpp index cfeec8e3d..1e1d93ff9 100644 --- a/src/items/network_item_manager.hpp +++ b/src/items/network_item_manager.hpp @@ -61,10 +61,10 @@ private: void forwardTime(int ticks); NetworkItemManager(); - virtual ~NetworkItemManager(); public: static void create(); + virtual ~NetworkItemManager(); void setSwitchItems(const std::vector &switch_items); void sendItemUpdate(); diff --git a/src/items/powerup_manager.cpp b/src/items/powerup_manager.cpp index d2f1d3b53..07aeb0f15 100644 --- a/src/items/powerup_manager.cpp +++ b/src/items/powerup_manager.cpp @@ -298,7 +298,7 @@ void PowerupManager::WeightsData::convertRankToSection(int rank, int *prev, } // The last kart always uses the data for the last section - if (rank == m_num_karts) + if (rank == (int)m_num_karts) { *prev = *next = m_weights_for_section.size() - 1; *weight = 1.0f; @@ -600,9 +600,11 @@ void PowerupManager::unitTesting() int num_weights = wd.m_summed_weights_for_rank[0].back(); for(int i=0; igetRandomPowerup(1, &n, i)==POWERUP_BOWLING ); assert(n==3); +#endif } // Test 2: Test all possible random numbers for 5 karts and rank 5 diff --git a/src/items/powerup_manager.hpp b/src/items/powerup_manager.hpp index f68b68dc2..bb2ef0cf1 100644 --- a/src/items/powerup_manager.hpp +++ b/src/items/powerup_manager.hpp @@ -139,7 +139,6 @@ public: }; private: - const int RAND_CLASS_RANGE = 1000; /** The icon for each powerup. */ Material* m_all_icons [POWERUP_MAX]; diff --git a/src/modes/linear_world.cpp b/src/modes/linear_world.cpp index e03eab9f7..c5f7f7059 100644 --- a/src/modes/linear_world.cpp +++ b/src/modes/linear_world.cpp @@ -176,7 +176,7 @@ void LinearWorld::update(int ticks) for(unsigned int n=0; ngetPosition(); @@ -799,7 +799,7 @@ void LinearWorld::updateRacePosition() // so that debug output is still correct!!!!!!!!!!! for (unsigned int i=0; igetIdent().c_str(), @@ -973,7 +973,7 @@ void LinearWorld::checkForWrongDirection(unsigned int i, float dt) KartInfo &ki = m_kart_info[i]; - const AbstractKart *kart=m_karts[i]; + const AbstractKart *kart=m_karts[i].get(); // If the kart can go in more than one directions from the current track // don't do any reverse message handling, since it is likely that there // will be one direction in which it isn't going backwards anyway. diff --git a/src/modes/profile_world.cpp b/src/modes/profile_world.cpp index 6f735b92e..147577aa0 100644 --- a/src/modes/profile_world.cpp +++ b/src/modes/profile_world.cpp @@ -103,19 +103,18 @@ void ProfileWorld::setProfileModeLaps(int laps) * this player globally (i.e. including network players). * \param init_pos The start XYZ coordinates. */ -AbstractKart *ProfileWorld::createKart(const std::string &kart_ident, int index, - int local_player_id, int global_player_id, - RaceManager::KartType type, - PerPlayerDifficulty difficulty) +std::shared_ptr ProfileWorld::createKart + (const std::string &kart_ident, int index, int local_player_id, + int global_player_id, RaceManager::KartType kart_type, + PerPlayerDifficulty difficulty) { btTransform init_pos = getStartTransform(index); - Kart *new_kart = new KartWithStats(kart_ident, - /*world kart id*/ index, - /*position*/ index+1, - init_pos, difficulty); + std::shared_ptr new_kart = + std::make_shared(kart_ident, /*world kart id*/ index, + /*position*/ index + 1, init_pos, difficulty); new_kart->init(RaceManager::KT_AI); - Controller *controller = loadAIController(new_kart); + Controller *controller = loadAIController(new_kart.get()); new_kart->setController(controller); // Create a camera for the last kart (since this way more of the @@ -123,7 +122,7 @@ AbstractKart *ProfileWorld::createKart(const std::string &kart_ident, int index, if (index == (int)race_manager->getNumberOfKarts()-1) { // The camera keeps track of all cameras and will free them - Camera::createCamera(new_kart, local_player_id); + Camera::createCamera(new_kart.get(), local_player_id); } return new_kart; } // createKart @@ -197,7 +196,7 @@ void ProfileWorld::enterRaceOverState() // ---------- update rank ------ if (m_karts[i]->hasFinishedRace() || m_karts[i]->isEliminated()) continue; - m_karts[i]->finishedRace(estimateFinishTimeForKart(m_karts[i])); + m_karts[i]->finishedRace(estimateFinishTimeForKart(m_karts[i].get())); } // Print framerate statistics @@ -229,9 +228,9 @@ void ProfileWorld::enterRaceOverState() std::set all_groups; - for ( KartList::size_type i = 0; i < m_karts.size(); ++i) + for (KartList::size_type i = 0; i < m_karts.size(); ++i) { - KartWithStats* kart = dynamic_cast(m_karts[i]); + auto kart = std::dynamic_pointer_cast(m_karts[i]); max_t = std::max(max_t, kart->getFinishTime()); min_t = std::min(min_t, kart->getFinishTime()); @@ -285,7 +284,7 @@ void ProfileWorld::enterRaceOverState() float av_time = 0.0f, energy = 0; for ( unsigned int i = 0; i < (unsigned int)m_karts.size(); ++i) { - KartWithStats* kart = dynamic_cast(m_karts[i]); + auto kart = std::dynamic_pointer_cast(m_karts[i]); const std::string &name=kart->getController()->getControllerName(); if(name!=*it) continue; diff --git a/src/modes/profile_world.hpp b/src/modes/profile_world.hpp index c4c1e0e00..255e9a4ba 100644 --- a/src/modes/profile_world.hpp +++ b/src/modes/profile_world.hpp @@ -72,10 +72,10 @@ protected: * used by DemoWorld. */ static int m_num_laps; - virtual AbstractKart *createKart(const std::string &kart_ident, int index, - int local_player_id, int global_player_id, - RaceManager::KartType type, - PerPlayerDifficulty difficulty); + virtual std::shared_ptr createKart + (const std::string &kart_ident, int index, int local_player_id, + int global_player_id, RaceManager::KartType type, + PerPlayerDifficulty difficulty); public: ProfileWorld(); diff --git a/src/modes/soccer_world.cpp b/src/modes/soccer_world.cpp index 3f014b2fb..afbd193d8 100644 --- a/src/modes/soccer_world.cpp +++ b/src/modes/soccer_world.cpp @@ -228,7 +228,7 @@ void SoccerWorld::update(int ticks) { for (unsigned int i = 0; i < m_karts.size(); i++) { - AbstractKart* kart = m_karts[i]; + auto& kart = m_karts[i]; if (kart->isEliminated()) continue; kart->getBody()->setLinearVelocity(Vec3(0.0f)); @@ -335,7 +335,7 @@ void SoccerWorld::onCheckGoalTriggered(bool first_goal) } for (unsigned i = 0; i < m_karts.size(); i++) { - AbstractKart* kart = m_karts[i]; + auto& kart = m_karts[i]; if (kart->isEliminated()) continue; kart->getBody()->setLinearVelocity(Vec3(0.0f)); @@ -406,7 +406,7 @@ void SoccerWorld::handlePlayerGoalFromServer(const NetworkString& ns) m_ball->setEnabled(false); for (unsigned i = 0; i < m_karts.size(); i++) { - AbstractKart* kart = m_karts[i]; + auto& kart = m_karts[i]; if (kart->isEliminated()) continue; btTransform transform_now = kart->getBody()->getWorldTransform(); @@ -431,7 +431,7 @@ void SoccerWorld::resetKartsToSelfGoals() setPhase(WorldStatus::RACE_PHASE); for (unsigned i = 0; i < m_karts.size(); i++) { - AbstractKart* kart = m_karts[i]; + auto& kart = m_karts[i]; if (kart->isEliminated()) continue; @@ -439,7 +439,7 @@ void SoccerWorld::resetKartsToSelfGoals() kart->getBody()->setAngularVelocity(Vec3(0.0f)); unsigned index = m_kart_position_map.at(kart->getWorldKartId()); btTransform t = Track::getCurrentTrack()->getStartTransform(index); - moveKartTo(kart, t); + moveKartTo(kart.get(), t); } } // resetKartsToSelfGoals @@ -532,10 +532,10 @@ bool SoccerWorld::getKartSoccerResult(unsigned int kart_id) const } // getKartSoccerResult //----------------------------------------------------------------------------- -AbstractKart *SoccerWorld::createKart(const std::string &kart_ident, int index, - int local_player_id, int global_player_id, - RaceManager::KartType kart_type, - PerPlayerDifficulty difficulty) +std::shared_ptr SoccerWorld::createKart + (const std::string &kart_ident, int index, int local_player_id, + int global_player_id, RaceManager::KartType kart_type, + PerPlayerDifficulty difficulty) { int cur_red = getTeamNum(SOCCER_TEAM_RED); int cur_blue = getTeamNum(SOCCER_TEAM_BLUE); @@ -590,16 +590,19 @@ AbstractKart *SoccerWorld::createKart(const std::string &kart_ident, int index, std::shared_ptr ri = std::make_shared(); ri = (team == SOCCER_TEAM_BLUE ? std::make_shared(0.66f) : std::make_shared(1.0f)); - AbstractKart* new_kart; + + std::shared_ptr new_kart; if (RewindManager::get()->isEnabled()) { - new_kart = new KartRewinder(kart_ident, index, position, init_pos, - difficulty, ri); + auto kr = std::make_shared(kart_ident, index, position, + init_pos, difficulty, ri); + kr->rewinderAdd(); + new_kart = kr; } else { - new_kart = new Kart(kart_ident, index, position, init_pos, difficulty, - ri); + new_kart = std::make_shared(kart_ident, index, position, + init_pos, difficulty, ri); } new_kart->init(race_manager->getKartType(index)); @@ -608,18 +611,18 @@ AbstractKart *SoccerWorld::createKart(const std::string &kart_ident, int index, switch(kart_type) { case RaceManager::KT_PLAYER: - controller = new LocalPlayerController(new_kart, local_player_id, + controller = new LocalPlayerController(new_kart.get(), local_player_id, difficulty); m_num_players ++; break; case RaceManager::KT_NETWORK_PLAYER: - controller = new NetworkPlayerController(new_kart); + controller = new NetworkPlayerController(new_kart.get()); if (!online_name.empty()) new_kart->setOnScreenText(online_name.c_str()); m_num_players++; break; case RaceManager::KT_AI: - controller = loadAIController(new_kart); + controller = loadAIController(new_kart.get()); break; case RaceManager::KT_GHOST: break; diff --git a/src/modes/soccer_world.hpp b/src/modes/soccer_world.hpp index 1d9943e03..190f76b3a 100644 --- a/src/modes/soccer_world.hpp +++ b/src/modes/soccer_world.hpp @@ -51,10 +51,10 @@ public: }; // ScorerData protected: - virtual AbstractKart *createKart(const std::string &kart_ident, int index, - int local_player_id, int global_player_id, - RaceManager::KartType type, - PerPlayerDifficulty difficulty) OVERRIDE; + virtual std::shared_ptr createKart + (const std::string &kart_ident, int index, int local_player_id, + int global_player_id, RaceManager::KartType type, + PerPlayerDifficulty difficulty) OVERRIDE; private: class KartDistanceMap diff --git a/src/modes/standard_race.cpp b/src/modes/standard_race.cpp index e701c6e6b..b90152369 100644 --- a/src/modes/standard_race.cpp +++ b/src/modes/standard_race.cpp @@ -103,7 +103,7 @@ void StandardRace::endRaceEarly() for (unsigned int i = 1; i <= kart_amount; i++) { int kartid = m_position_index[i-1]; - AbstractKart* kart = m_karts[kartid]; + AbstractKart* kart = m_karts[kartid].get(); if (kart->hasFinishedRace()) { @@ -140,7 +140,7 @@ void StandardRace::endRaceEarly() int kartid = active_players[i]; int position = getNumKarts() - (int) active_players.size() + 1 + i; setKartPosition(kartid, position); - float punished_time = estimateFinishTimeForKart(m_karts[kartid]) + float punished_time = estimateFinishTimeForKart(m_karts[kartid].get()) + worse_finish_time - WorldStatus::getTime(); m_karts[kartid]->finishedRace(punished_time); diff --git a/src/modes/three_strikes_battle.cpp b/src/modes/three_strikes_battle.cpp index b21d504f8..14c930854 100644 --- a/src/modes/three_strikes_battle.cpp +++ b/src/modes/three_strikes_battle.cpp @@ -722,18 +722,18 @@ void ThreeStrikesBattle::loadCustomModels() // Now add them for (unsigned int i = 0; i < pos.size(); i++) { - AbstractKart* sta = new Kart(sta_list[i], (int)m_karts.size(), + auto sta = std::make_shared(sta_list[i], (int)m_karts.size(), (int)m_karts.size() + 1, pos[i], PLAYER_DIFFICULTY_NORMAL, std::make_shared(1.0f)); sta->init(RaceManager::KartType::KT_SPARE_TIRE); - sta->setController(new SpareTireAI(sta)); + sta->setController(new SpareTireAI(sta.get())); m_karts.push_back(sta); race_manager->addSpareTireKart(sta_list[i]); // Copy STA pointer to m_spare_tire_karts array, allowing them // to respawn easily - m_spare_tire_karts.push_back(sta); + m_spare_tire_karts.push_back(sta.get()); } unsigned int sta_num = race_manager->getNumSpareTireKarts(); assert(m_spare_tire_karts.size() == sta_num); diff --git a/src/modes/world.cpp b/src/modes/world.cpp index fafccb261..7685bc81b 100644 --- a/src/modes/world.cpp +++ b/src/modes/world.cpp @@ -212,10 +212,9 @@ void World::init() : race_manager->getKartIdent(i); int local_player_id = race_manager->getKartLocalPlayerId(i); int global_player_id = race_manager->getKartGlobalPlayerId(i); - AbstractKart* newkart = createKart(kart_ident, i, local_player_id, - global_player_id, - race_manager->getKartType(i), - race_manager->getPlayerDifficulty(i)); + auto newkart = createKart(kart_ident, i, local_player_id, + global_player_id, race_manager->getKartType(i), + race_manager->getPlayerDifficulty(i)); m_karts.push_back(newkart); } // for i @@ -334,10 +333,10 @@ void World::createRaceGUI() * \param global_player_id If the kart is a player kart this is the index of * this player globally (i.e. including network players). */ -AbstractKart *World::createKart(const std::string &kart_ident, int index, - int local_player_id, int global_player_id, - RaceManager::KartType kart_type, - PerPlayerDifficulty difficulty) +std::shared_ptr World::createKart + (const std::string &kart_ident, int index, int local_player_id, + int global_player_id, RaceManager::KartType kart_type, + PerPlayerDifficulty difficulty) { unsigned int gk = 0; if (race_manager->hasGhostKarts()) @@ -355,13 +354,19 @@ AbstractKart *World::createKart(const std::string &kart_ident, int index, int position = index+1; btTransform init_pos = getStartTransform(index - gk); - AbstractKart *new_kart; + std::shared_ptr new_kart; if (RewindManager::get()->isEnabled()) - new_kart = new KartRewinder(kart_ident, index, position, init_pos, - difficulty, ri); + { + auto kr = std::make_shared(kart_ident, index, position, + init_pos, difficulty, ri); + kr->rewinderAdd(); + new_kart = kr; + } else - new_kart = new Kart(kart_ident, index, position, init_pos, difficulty, - ri); + { + new_kart = std::make_shared(kart_ident, index, position, + init_pos, difficulty, ri); + } new_kart->init(race_manager->getKartType(index)); Controller *controller = NULL; @@ -369,7 +374,7 @@ AbstractKart *World::createKart(const std::string &kart_ident, int index, { case RaceManager::KT_PLAYER: { - controller = new LocalPlayerController(new_kart, local_player_id, + controller = new LocalPlayerController(new_kart.get(), local_player_id, difficulty); const PlayerProfile* p = StateManager::get() ->getActivePlayer(local_player_id)->getConstProfile(); @@ -383,7 +388,7 @@ AbstractKart *World::createKart(const std::string &kart_ident, int index, } case RaceManager::KT_NETWORK_PLAYER: { - controller = new NetworkPlayerController(new_kart); + controller = new NetworkPlayerController(new_kart.get()); if (!online_name.empty()) new_kart->setOnScreenText(online_name.c_str()); m_num_players++; @@ -391,7 +396,7 @@ AbstractKart *World::createKart(const std::string &kart_ident, int index, } case RaceManager::KT_AI: { - controller = loadAIController(new_kart); + controller = loadAIController(new_kart.get()); break; } case RaceManager::KT_GHOST: @@ -417,7 +422,7 @@ const btTransform &World::getStartTransform(int index) /** Creates an AI controller for the kart. * \param kart The kart to be controlled by an AI. */ -Controller* World::loadAIController(AbstractKart *kart) +Controller* World::loadAIController(AbstractKart* kart) { Controller *controller; int turn=0; @@ -485,13 +490,7 @@ World::~World() Weather::kill(); - for ( unsigned int i = 0 ; i < m_karts.size() ; i++ ) - { - // Let ReplayPlay destroy the ghost karts - if (m_karts[i]->isGhostKart()) continue; - delete m_karts[i]; - } - + m_karts.clear(); if(race_manager->hasGhostKarts() || race_manager->isRecordingRace()) { // Destroy the old replay object, which also stored the ghost @@ -502,7 +501,6 @@ World::~World() ReplayPlay::destroy(); ReplayPlay::create(); } - m_karts.clear(); if(race_manager->isRecordingRace()) ReplayRecorder::get()->reset(); race_manager->setRaceGhostKarts(false); @@ -567,7 +565,8 @@ void World::terminateRace() { if(!m_karts[i]->hasFinishedRace() && !m_karts[i]->isEliminated()) { - m_karts[i]->finishedRace(estimateFinishTimeForKart(m_karts[i])); + m_karts[i]->finishedRace( + estimateFinishTimeForKart(m_karts[i].get())); } } // igetNormal() * (0.5f * ((*i)->getKartHeight())); (*i)->setXYZ(xyz+up_offset); - bool kart_over_ground = Track::getCurrentTrack()->findGround(*i); + bool kart_over_ground = Track::getCurrentTrack()->findGround(i->get()); if (!kart_over_ground) { @@ -1165,7 +1164,7 @@ void World::updateHighscores(int* best_highscore_rank) if (!m_karts[index[pos]]->hasFinishedRace()) continue; assert(index[pos] < m_karts.size()); - Kart *k = (Kart*)m_karts[index[pos]]; + Kart *k = (Kart*)m_karts[index[pos]].get(); Highscores* highscores = getHighscores(); @@ -1197,14 +1196,17 @@ void World::updateHighscores(int* best_highscore_rank) */ AbstractKart *World::getPlayerKart(unsigned int n) const { - unsigned int count=-1; + unsigned int count = -1; - for(unsigned int i=0; igetController()->isPlayerController()) + for(unsigned int i = 0; i < m_karts.size(); i++) + { + if (m_karts[i]->getController()->isPlayerController()) { count++; - if(count==n) return m_karts[i]; + if (count == n) + return m_karts[i].get(); } + } return NULL; } // getPlayerKart @@ -1225,7 +1227,7 @@ AbstractKart *World::getLocalPlayerKart(unsigned int n) const void World::eliminateKart(int kart_id, bool notify_of_elimination) { assert(kart_id < (int)m_karts.size()); - AbstractKart *kart = m_karts[kart_id]; + AbstractKart *kart = m_karts[kart_id].get(); if (kart->isGhostKart()) return; // Display a message about the eliminated kart in the race guia diff --git a/src/modes/world.hpp b/src/modes/world.hpp index 4be4522e6..34ba7a37d 100644 --- a/src/modes/world.hpp +++ b/src/modes/world.hpp @@ -25,6 +25,7 @@ * battle, etc.) */ +#include #include #include @@ -80,7 +81,7 @@ public: class World : public WorldStatus { public: - typedef std::vector KartList; + typedef std::vector > KartList; private: /** A pointer to the global world object for a race. */ static World *m_world; @@ -117,10 +118,10 @@ protected: Controller* loadAIController (AbstractKart *kart); - virtual AbstractKart *createKart(const std::string &kart_ident, int index, - int local_player_id, int global_player_id, - RaceManager::KartType type, - PerPlayerDifficulty difficulty); + virtual std::shared_ptr createKart + (const std::string &kart_ident, int index, int local_player_id, + int global_player_id, RaceManager::KartType type, + PerPlayerDifficulty difficulty); /** Pointer to the race GUI. The race GUI is handled by world. */ RaceGUIBase *m_race_gui; @@ -293,7 +294,7 @@ public: /** Returns the kart with a given world id. */ AbstractKart *getKart(int kartId) const { assert(kartId >= 0 && kartId < int(m_karts.size())); - return m_karts[kartId]; } + return m_karts[kartId].get(); } // ------------------------------------------------------------------------ /** Returns all karts. */ const KartList & getKarts() const { return m_karts; } diff --git a/src/modes/world_with_rank.cpp b/src/modes/world_with_rank.cpp index 6d23e20f2..862b3182d 100644 --- a/src/modes/world_with_rank.cpp +++ b/src/modes/world_with_rank.cpp @@ -82,7 +82,7 @@ AbstractKart* WorldWithRank::getKartAtPosition(unsigned int p) const if(p<1 || p>m_position_index.size()) return NULL; - return m_karts[m_position_index[p-1]]; + return m_karts[m_position_index[p-1]].get(); } // getKartAtPosition //----------------------------------------------------------------------------- diff --git a/src/network/rewind_info.cpp b/src/network/rewind_info.cpp index c0da5fa6f..6dd9d841a 100644 --- a/src/network/rewind_info.cpp +++ b/src/network/rewind_info.cpp @@ -19,8 +19,8 @@ #include "network/rewind_info.hpp" #include "network/network_config.hpp" +#include "network/rewinder.hpp" #include "network/rewind_manager.hpp" -#include "physics/physics.hpp" /** Constructor for a state: it only takes the size, and allocates a buffer * for all state info. diff --git a/src/network/rewind_info.hpp b/src/network/rewind_info.hpp index 5ca1bf0cb..8d55ff387 100644 --- a/src/network/rewind_info.hpp +++ b/src/network/rewind_info.hpp @@ -21,7 +21,6 @@ #include "network/event_rewinder.hpp" #include "network/network_string.hpp" -#include "network/rewinder.hpp" #include "utils/cpp2011.hpp" #include "utils/leak_check.hpp" #include "utils/ptr_vector.hpp" diff --git a/src/network/rewinder.cpp b/src/network/rewinder.cpp index 9d6e39037..00d76c1dc 100644 --- a/src/network/rewinder.cpp +++ b/src/network/rewinder.cpp @@ -24,7 +24,7 @@ /** Add this object to the list of all rewindable * objects in the rewind manager. */ -bool Rewinder::add() +bool Rewinder::rewinderAdd() { return RewindManager::get()->addRewinder(shared_from_this()); -} // add +} // rewinderAdd diff --git a/src/network/rewinder.hpp b/src/network/rewinder.hpp index 952aca1cc..045eb7413 100644 --- a/src/network/rewinder.hpp +++ b/src/network/rewinder.hpp @@ -91,7 +91,7 @@ public: return m_unique_identity; } // ------------------------------------------------------------------------- - bool add(); + bool rewinderAdd(); }; // Rewinder #endif diff --git a/src/physics/btKartRaycast.cpp b/src/physics/btKartRaycast.cpp index 2a607a3ab..331e80a59 100644 --- a/src/physics/btKartRaycast.cpp +++ b/src/physics/btKartRaycast.cpp @@ -71,8 +71,6 @@ void* btKartRaycaster::castRay(const btVector3& from, const btVector3& to, result.m_hitNormalInWorld.normalize(); result.m_distFraction = rayCallback.m_closestHitFraction; result.m_triangle_index = -1; - const TriangleMesh &tm = - Track::getCurrentTrack()->getTriangleMesh(); // FIXME: this code assumes atm that the object the kart is // driving on is the main track (and not e.g. a physical object). // If this should not be the case (i.e. the object hit by the diff --git a/src/physics/physical_object.cpp b/src/physics/physical_object.cpp index fd5338084..8482861ae 100644 --- a/src/physics/physical_object.cpp +++ b/src/physics/physical_object.cpp @@ -123,12 +123,11 @@ void PhysicalObject::Settings::init() } // Settings // ============================================================================ -PhysicalObject* PhysicalObject::fromXML(bool is_dynamic, - const XMLNode &xml_node, - TrackObject* object) +std::shared_ptr PhysicalObject::fromXML + (bool is_dynamic, const XMLNode &xml_node, TrackObject* object) { PhysicalObject::Settings settings(xml_node); - return new PhysicalObject(is_dynamic, settings, object); + return std::make_shared(is_dynamic, settings, object); } // fromXML // ---------------------------------------------------------------------------- @@ -792,7 +791,7 @@ void PhysicalObject::addForRewind() SmoothNetworkBody::setAdjustVerticalOffset(false); Rewinder::setUniqueIdentity(std::string("P") + StringUtils::toString (Track::getCurrentTrack()->getPhysicalObjectUID())); - Rewinder::add(); + Rewinder::rewinderAdd(); } // addForRewind // ---------------------------------------------------------------------------- diff --git a/src/physics/physical_object.hpp b/src/physics/physical_object.hpp index a2c115d55..480e5ca5f 100644 --- a/src/physics/physical_object.hpp +++ b/src/physics/physical_object.hpp @@ -197,8 +197,8 @@ public: PhysicalObject(bool is_dynamic, const Settings& settings, TrackObject* object); - static PhysicalObject* fromXML(bool is_dynamic, const XMLNode &node, - TrackObject* object); + static std::shared_ptr fromXML + (bool is_dynamic, const XMLNode &node, TrackObject* object); virtual ~PhysicalObject (); virtual void reset (); diff --git a/src/race/history.cpp b/src/race/history.cpp index c7dcbced4..b51f99ce1 100644 --- a/src/race/history.cpp +++ b/src/race/history.cpp @@ -296,11 +296,13 @@ void History::Load() { fgets(s, 1023, fd); InputEvent &ie = m_all_input_events[i]; + int action = 0; if (sscanf(s, "%d %d %d %d\n", &ie.m_world_ticks, &ie.m_kart_index, - &ie.m_action, &ie.m_value) != 4 ) + &action, &ie.m_value) != 4) { Log::warn("History", "Problems reading event: '%s'", s); } + ie.m_action = (PlayerAction)action; } // for i RewindManager::setEnable(rewind_manager_was_enabled); diff --git a/src/replay/replay_play.cpp b/src/replay/replay_play.cpp index 9be552705..6207cf77d 100644 --- a/src/replay/replay_play.cpp +++ b/src/replay/replay_play.cpp @@ -58,7 +58,7 @@ void ReplayPlay::reset() { for(unsigned int i=0; i<(unsigned int)m_ghost_karts.size(); i++) { - m_ghost_karts[i].reset(); + m_ghost_karts[i]->reset(); } } // reset @@ -297,7 +297,7 @@ bool ReplayPlay::addReplayFile(const std::string& fn, bool custom_replay, int ca //----------------------------------------------------------------------------- void ReplayPlay::load() { - m_ghost_karts.clearAndDeleteAll(); + m_ghost_karts.clear(); if (m_second_replay_enabled) loadFile(/* second replay */ true); @@ -365,11 +365,11 @@ void ReplayPlay::readKartData(FILE *fd, char *next_line, bool second_replay) first_loaded_f_num = m_replay_file_list.at(m_second_replay_file).m_kart_list.size(); ReplayData &rd = m_replay_file_list[replay_index]; - m_ghost_karts.push_back(new GhostKart(rd.m_kart_list.at(kart_num-first_loaded_f_num), - kart_num, kart_num + 1, - rd.m_kart_color.at(kart_num-first_loaded_f_num))); - m_ghost_karts[kart_num].init(RaceManager::KT_GHOST); - Controller* controller = new GhostController(getGhostKart(kart_num), + m_ghost_karts.push_back(std::make_shared + (rd.m_kart_list.at(kart_num-first_loaded_f_num), kart_num, kart_num + 1, + rd.m_kart_color.at(kart_num-first_loaded_f_num))); + m_ghost_karts[kart_num]->init(RaceManager::KT_GHOST); + Controller* controller = new GhostController(getGhostKart(kart_num).get(), rd.m_name_list[kart_num-first_loaded_f_num]); getGhostKart(kart_num)->setController(controller); @@ -423,7 +423,7 @@ void ReplayPlay::readKartData(FILE *fd, char *next_line, bool second_replay) kre.m_skidding_effect = skidding; kre.m_red_skidding = red_skidding!=0; kre.m_jumping = jumping != 0; - m_ghost_karts[kart_num].addReplayEvent(time, + m_ghost_karts[kart_num]->addReplayEvent(time, btTransform(q, xyz), pi, bi, kre); } else @@ -472,7 +472,7 @@ void ReplayPlay::readKartData(FILE *fd, char *next_line, bool second_replay) kre.m_skidding_effect = skidding; kre.m_red_skidding = red_skidding!=0; kre.m_jumping = jumping != 0; - m_ghost_karts[kart_num].addReplayEvent(time, + m_ghost_karts[kart_num]->addReplayEvent(time, btTransform(q, xyz), pi, bi, kre); } else diff --git a/src/replay/replay_play.hpp b/src/replay/replay_play.hpp index ad0b1a703..ec12e4c30 100644 --- a/src/replay/replay_play.hpp +++ b/src/replay/replay_play.hpp @@ -20,10 +20,10 @@ #define HEADER_REPLAY__PLAY_HPP #include "replay/replay_base.hpp" -#include "utils/ptr_vector.hpp" #include "irrString.h" #include +#include #include #include @@ -118,7 +118,7 @@ private: std::vector m_replay_file_list; /** All ghost karts. */ - PtrVector m_ghost_karts; + std::vector > m_ghost_karts; ReplayPlay(); ~ReplayPlay(); @@ -162,7 +162,7 @@ public: const unsigned int getNumReplayFile() const { return (unsigned int)m_replay_file_list.size(); } // ------------------------------------------------------------------------ - GhostKart* getGhostKart(int n) { return m_ghost_karts.get(n); } + std::shared_ptr getGhostKart(int n) { return m_ghost_karts[n]; } // ------------------------------------------------------------------------ const unsigned int getNumGhostKart() const { diff --git a/src/tracks/track_object.cpp b/src/tracks/track_object.cpp index 58b9636ac..a4fc0f856 100644 --- a/src/tracks/track_object.cpp +++ b/src/tracks/track_object.cpp @@ -74,7 +74,6 @@ TrackObject::TrackObject(const core::vector3df& xyz, const core::vector3df& hpr, m_enabled = true; m_presentation = NULL; m_animator = NULL; - m_physical_object = NULL; m_parent_library = NULL; m_interaction = interaction; m_presentation = presentation; @@ -86,9 +85,8 @@ TrackObject::TrackObject(const core::vector3df& xyz, const core::vector3df& hpr, if (m_interaction != "ghost" && m_interaction != "none" && physics_settings ) { - m_physical_object = new PhysicalObject(is_dynamic, - *physics_settings, - this); + m_physical_object = std::make_shared + (is_dynamic, *physics_settings, this); } reset(); @@ -112,7 +110,6 @@ void TrackObject::init(const XMLNode &xml_node, scene::ISceneNode* parent, m_presentation = NULL; m_animator = NULL; m_parent_library = parent_library; - m_physical_object = NULL; xml_node.get("id", &m_id ); xml_node.get("model", &m_name ); @@ -455,7 +452,6 @@ TrackObject::~TrackObject() { delete m_presentation; delete m_animator; - delete m_physical_object; } // ~TrackObject // ---------------------------------------------------------------------------- @@ -482,7 +478,7 @@ void TrackObject::setEnabled(bool enabled) if (getType() == "mesh") { - if (m_physical_object != NULL) + if (m_physical_object) { if (enabled) m_physical_object->addBody(); @@ -508,7 +504,7 @@ void TrackObject::resetEnabled() if (getType() == "mesh") { - if (m_physical_object != NULL) + if (m_physical_object) { if (m_initially_visible) m_physical_object->addBody(); @@ -581,7 +577,7 @@ void TrackObject::move(const core::vector3df& xyz, const core::vector3df& hpr, if (m_presentation != NULL) m_presentation->move(xyz, hpr, scale, isAbsoluteCoord); - if (update_rigid_body && m_physical_object != NULL) + if (update_rigid_body && m_physical_object) { movePhysicalBodyToGraphicalNode(xyz, hpr); } diff --git a/src/tracks/track_object.hpp b/src/tracks/track_object.hpp index 65905a040..e16b302cb 100644 --- a/src/tracks/track_object.hpp +++ b/src/tracks/track_object.hpp @@ -86,7 +86,7 @@ protected: /** True if a kart can drive on this object. This will */ bool m_is_driveable; - PhysicalObject* m_physical_object; + std::shared_ptr m_physical_object; ThreeDAnimation* m_animator; @@ -164,9 +164,10 @@ public: // ------------------------------------------------------------------------ bool isSoccerBall() const { return m_soccer_ball; } // ------------------------------------------------------------------------ - const PhysicalObject* getPhysicalObject() const { return m_physical_object; } + const PhysicalObject* getPhysicalObject() const + { return m_physical_object.get(); } // ------------------------------------------------------------------------ - PhysicalObject* getPhysicalObject() { return m_physical_object; } + PhysicalObject* getPhysicalObject() { return m_physical_object.get(); } // ------------------------------------------------------------------------ const core::vector3df getInitXYZ() const { return m_init_xyz; } // ------------------------------------------------------------------------ @@ -214,7 +215,7 @@ public: /** Get the physics representation of an object. * On the script side, the returned object is of type : @ref Scripting_PhysicalObject */ - PhysicalObject* getPhysics() { return m_physical_object; } + PhysicalObject* getPhysics() { return m_physical_object.get(); } /** Hide or show the object */ void setEnabled(bool mode); From 4a9a0fba0f2af97236e0c6596cb1aaf20489d95f Mon Sep 17 00:00:00 2001 From: Benau Date: Tue, 24 Jul 2018 15:43:31 +0800 Subject: [PATCH 27/36] Make flyable to work with shared_ptr --- src/items/flyable.cpp | 31 +++++- src/items/flyable.hpp | 24 ++++- src/items/powerup.cpp | 5 + src/items/powerup.hpp | 4 +- src/items/projectile_manager.cpp | 177 ++++++++++++++++++++++--------- src/items/projectile_manager.hpp | 18 +++- src/karts/kart_rewinder.cpp | 5 - src/karts/kart_rewinder.hpp | 2 +- src/karts/moveable.cpp | 2 +- src/modes/world.cpp | 6 +- src/network/rewinder.hpp | 4 +- 11 files changed, 205 insertions(+), 73 deletions(-) diff --git a/src/items/flyable.cpp b/src/items/flyable.cpp index 63e2d2127..474e3a384 100644 --- a/src/items/flyable.cpp +++ b/src/items/flyable.cpp @@ -37,6 +37,7 @@ #include "karts/explosion_animation.hpp" #include "modes/linear_world.hpp" #include "modes/soccer_world.hpp" +#include "network/network_string.hpp" #include "physics/physics.hpp" #include "tracks/track.hpp" #include "utils/constants.hpp" @@ -378,7 +379,7 @@ void Flyable::setAnimation(AbstractKartAnimation *animation) */ void Flyable::updateGraphics(float dt) { - updateSmoothedGraphics(dt); + Moveable::updateSmoothedGraphics(dt); Moveable::updateGraphics(); } // updateGraphics @@ -573,5 +574,31 @@ HitEffect* Flyable::getHitEffect() const unsigned int Flyable::getOwnerId() { return m_owner->getWorldKartId(); -} +} // getOwnerId + +// ---------------------------------------------------------------------------- +BareNetworkString* Flyable::saveState(std::vector* ru) +{ +} // saveState + +// ---------------------------------------------------------------------------- +void Flyable::restoreState(BareNetworkString *buffer, int count) +{ +} // restoreState + +// ---------------------------------------------------------------------------- +std::function Flyable::getLocalStateRestoreFunction() +{ +} // getLocalStateRestoreFunction + +// ---------------------------------------------------------------------------- +void Flyable::addForRewind(const std::string& uid) +{ + SmoothNetworkBody::setEnable(true); + SmoothNetworkBody::setSmoothRotation(false); + SmoothNetworkBody::setAdjustVerticalOffset(false); + Rewinder::setUniqueIdentity(uid); + Rewinder::rewinderAdd(); +} // addForRewind + /* EOF */ diff --git a/src/items/flyable.hpp b/src/items/flyable.hpp index 8eba2bc6e..c9e22a951 100644 --- a/src/items/flyable.hpp +++ b/src/items/flyable.hpp @@ -24,6 +24,7 @@ #include "items/powerup_manager.hpp" #include "karts/moveable.hpp" +#include "network/rewinder.hpp" #include "tracks/terrain_info.hpp" #include "utils/cpp2011.hpp" @@ -43,7 +44,8 @@ class XMLNode; /** * \ingroup items */ -class Flyable : public Moveable, public TerrainInfo +class Flyable : public Moveable, public TerrainInfo, + public Rewinder { public: private: @@ -128,7 +130,7 @@ protected: /** Time since thrown. used so a kart can't hit himself when trying * something, and also to put some time limit to some collectibles */ - int m_ticks_since_thrown; + int16_t m_ticks_since_thrown; /** Set to something > -1 if this flyable should auto-destrcut after * that may ticks. */ @@ -217,6 +219,24 @@ public: /** Returns the size (extend) of the mesh. */ const Vec3 &getExtend() const { return m_extend; } // ------------------------------------------------------------------------ + void addForRewind(const std::string& uid); + // ------------------------------------------------------------------------ + virtual void undoEvent(BareNetworkString *buffer) OVERRIDE {} + // ------------------------------------------------------------------------ + virtual void rewindToEvent(BareNetworkString *buffer) OVERRIDE {} + // ------------------------------------------------------------------------ + virtual void undoState(BareNetworkString *buffer) OVERRIDE {} + // ------------------------------------------------------------------------ + virtual void saveTransform() OVERRIDE { Moveable::prepareSmoothing(); } + // ------------------------------------------------------------------------ + virtual void computeError() OVERRIDE { Moveable::checkSmoothing(); } + // ------------------------------------------------------------------------ + virtual BareNetworkString* saveState(std::vector* ru) + OVERRIDE; + // ------------------------------------------------------------------------ + virtual void restoreState(BareNetworkString *buffer, int count) OVERRIDE; + // ------------------------------------------------------------------------ + virtual std::function getLocalStateRestoreFunction() OVERRIDE; }; // Flyable #endif diff --git a/src/items/powerup.cpp b/src/items/powerup.cpp index fc3f0895c..99c7b8f42 100644 --- a/src/items/powerup.cpp +++ b/src/items/powerup.cpp @@ -211,6 +211,11 @@ void Powerup::adjustSound() } } // adjustSound +//----------------------------------------------------------------------------- +void Powerup::playSound() +{ +} // playSound + //----------------------------------------------------------------------------- /** Use (fire) this powerup. */ diff --git a/src/items/powerup.hpp b/src/items/powerup.hpp index 9077495da..4e4965f80 100644 --- a/src/items/powerup.hpp +++ b/src/items/powerup.hpp @@ -36,9 +36,6 @@ class SFXBase; class Powerup : public NoCopy { private: - /** A synchronised random number generator for network games. */ - RandomGenerator m_random; - /** Sound effect that is being played. */ SFXBase *m_sound_use; @@ -51,6 +48,7 @@ private: /** The owner (kart) of this powerup. */ AbstractKart* m_kart; + void playSound(); public: Powerup (AbstractKart* kart_); ~Powerup (); diff --git a/src/items/projectile_manager.cpp b/src/items/projectile_manager.cpp index 907c77ca4..8b088f204 100644 --- a/src/items/projectile_manager.cpp +++ b/src/items/projectile_manager.cpp @@ -27,6 +27,8 @@ #include "items/powerup.hpp" #include "items/rubber_ball.hpp" #include "karts/abstract_kart.hpp" +#include "modes/world.hpp" +#include "network/rewind_manager.hpp" ProjectileManager *projectile_manager=0; @@ -45,12 +47,6 @@ void ProjectileManager::removeTextures() //----------------------------------------------------------------------------- void ProjectileManager::cleanup() { - for(Projectiles::iterator i = m_active_projectiles.begin(); - i != m_active_projectiles.end(); ++i) - { - delete *i; - } - m_active_projectiles.clear(); for(HitEffects::iterator i = m_active_hit_effects.begin(); i != m_active_hit_effects.end(); ++i) @@ -68,12 +64,8 @@ void ProjectileManager::cleanup() */ void ProjectileManager::updateGraphics(float dt) { - for (auto p = m_active_projectiles.begin(); - p != m_active_projectiles.end(); ++p) - { - (*p)->updateGraphics(dt); - } - + for (auto& p : m_active_projectiles) + p.second->updateGraphics(dt); } // updateGraphics // ----------------------------------------------------------------------------- @@ -107,24 +99,21 @@ void ProjectileManager::update(int ticks) /** Updates all rockets on the server (or no networking). */ void ProjectileManager::updateServer(int ticks) { - Projectiles::iterator p = m_active_projectiles.begin(); - while(p!=m_active_projectiles.end()) + auto p = m_active_projectiles.begin(); + while (p != m_active_projectiles.end()) { - bool can_be_deleted = (*p)->updateAndDelete(ticks); - if(can_be_deleted) + bool can_be_deleted = p->second->updateAndDelete(ticks); + if (can_be_deleted) { - HitEffect *he = (*p)->getHitEffect(); - if(he) + HitEffect *he = p->second->getHitEffect(); + if (he) addHitEffect(he); - Flyable *f=*p; - Projectiles::iterator p_next=m_active_projectiles.erase(p); - delete f; - p=p_next; + p = m_active_projectiles.erase(p); } else p++; } // while p!=m_active_projectiles.end() - + } // updateServer // ----------------------------------------------------------------------------- @@ -132,20 +121,30 @@ void ProjectileManager::updateServer(int ticks) * \param kart The kart which shoots the projectile. * \param type Type of projectile. */ -Flyable *ProjectileManager::newProjectile(AbstractKart *kart, - PowerupManager::PowerupType type) +std::shared_ptr + ProjectileManager::newProjectile(AbstractKart *kart, + PowerupManager::PowerupType type) { - Flyable *f; + std::shared_ptr f; switch(type) { - case PowerupManager::POWERUP_BOWLING: f = new Bowling(kart); break; - case PowerupManager::POWERUP_PLUNGER: f = new Plunger(kart); break; - case PowerupManager::POWERUP_CAKE: f = new Cake(kart); break; - case PowerupManager::POWERUP_RUBBERBALL: f = new RubberBall(kart); - break; - default: return NULL; + case PowerupManager::POWERUP_BOWLING: + f = std::make_shared(kart); + break; + case PowerupManager::POWERUP_PLUNGER: + f = std::make_shared(kart); + break; + case PowerupManager::POWERUP_CAKE: + f = std::make_shared(kart); + break; + case PowerupManager::POWERUP_RUBBERBALL: + f = std::make_shared(kart); + break; + default: + return nullptr; } - m_active_projectiles.push_back(f); + const std::string& uid = getUniqueIdentity(kart, type); + m_active_projectiles[uid] = f; return f; } // newProjectile @@ -158,13 +157,13 @@ Flyable *ProjectileManager::newProjectile(AbstractKart *kart, bool ProjectileManager::projectileIsClose(const AbstractKart * const kart, float radius) { - float r2 = radius*radius; - - for(Projectiles::iterator i = m_active_projectiles.begin(); - i != m_active_projectiles.end(); i++) + float r2 = radius * radius; + for (auto i = m_active_projectiles.begin(); i != m_active_projectiles.end(); + i++) { - float dist2 = (*i)->getXYZ().distance2(kart->getXYZ()); - if(dist2second->getXYZ().distance2(kart->getXYZ()); + if (dist2 < r2) + return true; } return false; } // projectileIsClose @@ -179,21 +178,99 @@ bool ProjectileManager::projectileIsClose(const AbstractKart * const kart, int ProjectileManager::getNearbyProjectileCount(const AbstractKart * const kart, float radius, PowerupManager::PowerupType type) { - float r2 = radius*radius; - int projectileCount = 0; - - for(Projectiles::iterator i = m_active_projectiles.begin(); - i != m_active_projectiles.end(); i++) + float r2 = radius * radius; + int projectile_count = 0; + for (auto i = m_active_projectiles.begin(); i != m_active_projectiles.end(); + i++) { - if ((*i)->getType() == type) + if (i->second->getType() == type) { - float dist2 = (*i)->getXYZ().distance2(kart->getXYZ()); - if(dist2second->getXYZ().distance2(kart->getXYZ()); + if (dist2 < r2) { - - projectileCount++; + projectile_count++; } } } - return projectileCount; + return projectile_count; } // getNearbyProjectileCount + +// ----------------------------------------------------------------------------- +std::string ProjectileManager::getUniqueIdentity(AbstractKart* kart, + PowerupManager::PowerupType t) +{ + switch (t) + { + case PowerupManager::POWERUP_BOWLING: + return std::string("B_") + + StringUtils::toString(kart->getWorldKartId()) + "_" + + StringUtils::toString(World::getWorld()->getTicksSinceStart()); + case PowerupManager::POWERUP_PLUNGER: + return std::string("P_") + + StringUtils::toString(kart->getWorldKartId()) + "_" + + StringUtils::toString(World::getWorld()->getTicksSinceStart()); + case PowerupManager::POWERUP_CAKE: + return std::string("C_") + + StringUtils::toString(kart->getWorldKartId()) + "_" + + StringUtils::toString(World::getWorld()->getTicksSinceStart()); + case PowerupManager::POWERUP_RUBBERBALL: + return std::string("R_") + + StringUtils::toString(kart->getWorldKartId()) + "_" + + StringUtils::toString(World::getWorld()->getTicksSinceStart()); + default: + assert(false); + return ""; + } +} // getUniqueIdentity + +// ----------------------------------------------------------------------------- +std::shared_ptr + ProjectileManager::addRewinderFromNetworkState(const std::string& uid) +{ + std::vector id = StringUtils::split(uid, '_'); + if (id.size() != 3) + return nullptr; + if (!(id[0] == "B" || id[0] == "P" || id[0] == "C" || id[0] == "R")) + return nullptr; + int world_id = -1; + if (!StringUtils::fromString(id[1], world_id)) + return nullptr; + AbstractKart* kart = World::getWorld()->getKart(world_id); + char first_id = id[0][0]; + Log::warn("ProjectileManager", + "Missed a firing event, add the flyable %s manually", uid.c_str()); + switch (first_id) + { + case 'B': + { + auto f = std::make_shared(kart); + f->addForRewind(uid); + m_active_projectiles[uid] = f; + return f; + } + case 'P': + { + auto f = std::make_shared(kart); + f->addForRewind(uid); + m_active_projectiles[uid] = f; + return f; + } + case 'C': + { + auto f = std::make_shared(kart); + f->addForRewind(uid); + m_active_projectiles[uid] = f; + return f; + } + case 'R': + { + auto f = std::make_shared(kart); + f->addForRewind(uid); + m_active_projectiles[uid] = f; + return f; + } + default: + assert(false); + return nullptr; + } +} // addProjectileFromNetworkState diff --git a/src/items/projectile_manager.hpp b/src/items/projectile_manager.hpp index 9518ccec2..236026570 100644 --- a/src/items/projectile_manager.hpp +++ b/src/items/projectile_manager.hpp @@ -19,6 +19,8 @@ #ifndef HEADER_PROJECTILEMANAGER_HPP #define HEADER_PROJECTILEMANAGER_HPP +#include +#include #include namespace irr @@ -32,6 +34,7 @@ namespace irr class AbstractKart; class Flyable; class HitEffect; +class Rewinder; class Track; class Vec3; @@ -41,17 +44,18 @@ class Vec3; class ProjectileManager : public NoCopy { private: - typedef std::vector Projectiles; typedef std::vector HitEffects; /** The list of all active projectiles, i.e. projectiles which are * currently moving on the track. */ - Projectiles m_active_projectiles; + std::map > m_active_projectiles; /** All active hit effects, i.e. hit effects which are currently * being shown or have a sfx playing. */ HitEffects m_active_hit_effects; + std::string getUniqueIdentity(AbstractKart* kart, + PowerupManager::PowerupType type); void updateServer(int ticks); public: ProjectileManager() {} @@ -60,9 +64,6 @@ public: void cleanup (); void update (int ticks); void updateGraphics (float dt); - Flyable* newProjectile (AbstractKart *kart, - PowerupManager::PowerupType type); - void Deactivate (Flyable *p) {} void removeTextures (); bool projectileIsClose(const AbstractKart * const kart, float radius); @@ -74,6 +75,13 @@ public: * \param hit_effect The hit effect to be added. */ void addHitEffect(HitEffect *hit_effect) { m_active_hit_effects.push_back(hit_effect); } + // ------------------------------------------------------------------------ + std::shared_ptr + addRewinderFromNetworkState(const std::string& uid); + // ------------------------------------------------------------------------ + std::shared_ptr newProjectile(AbstractKart *kart, + PowerupManager::PowerupType type); + }; extern ProjectileManager *projectile_manager; diff --git a/src/karts/kart_rewinder.cpp b/src/karts/kart_rewinder.cpp index 1d4de3f1a..8b80c30b7 100644 --- a/src/karts/kart_rewinder.cpp +++ b/src/karts/kart_rewinder.cpp @@ -222,11 +222,6 @@ void KartRewinder::update(int ticks) Kart::update(ticks); } // update -// ---------------------------------------------------------------------------- -void KartRewinder::rewindToEvent(BareNetworkString *buffer) -{ -} // rewindToEvent - // ---------------------------------------------------------------------------- std::function KartRewinder::getLocalStateRestoreFunction() { diff --git a/src/karts/kart_rewinder.hpp b/src/karts/kart_rewinder.hpp index ebdd39b35..1c9beb254 100644 --- a/src/karts/kart_rewinder.hpp +++ b/src/karts/kart_rewinder.hpp @@ -48,7 +48,7 @@ public: OVERRIDE; void reset() OVERRIDE; virtual void restoreState(BareNetworkString *p, int count) OVERRIDE; - virtual void rewindToEvent(BareNetworkString *p) OVERRIDE; + virtual void rewindToEvent(BareNetworkString *p) OVERRIDE {} virtual void update(int ticks) OVERRIDE; // ------------------------------------------------------------------------- virtual float getSteerPercent() const OVERRIDE diff --git a/src/karts/moveable.cpp b/src/karts/moveable.cpp index cf16491fe..492315f36 100644 --- a/src/karts/moveable.cpp +++ b/src/karts/moveable.cpp @@ -64,7 +64,7 @@ void Moveable::updateSmoothedGraphics(float dt) { Vec3 velocity; if (m_body) - velocity = m_body->getLinearVelocity(); + velocity = getVelocity(); SmoothNetworkBody::updateSmoothedGraphics(m_transform, velocity, dt); #undef DEBUG_SMOOTHING #ifdef DEBUG_SMOOTHING diff --git a/src/modes/world.cpp b/src/modes/world.cpp index 7685bc81b..94381a06a 100644 --- a/src/modes/world.cpp +++ b/src/modes/world.cpp @@ -1055,13 +1055,13 @@ void World::update(int ticks) } PROFILER_POP_CPU_MARKER(); - if(race_manager->isRecordingRace()) ReplayRecorder::get()->update(ticks); - Physics::getInstance()->update(ticks); - PROFILER_PUSH_CPU_MARKER("World::update (projectiles)", 0xa0, 0x7F, 0x00); projectile_manager->update(ticks); PROFILER_POP_CPU_MARKER(); + if(race_manager->isRecordingRace()) ReplayRecorder::get()->update(ticks); + Physics::getInstance()->update(ticks); + PROFILER_POP_CPU_MARKER(); #ifdef DEBUG diff --git a/src/network/rewinder.hpp b/src/network/rewinder.hpp index 045eb7413..e314152dd 100644 --- a/src/network/rewinder.hpp +++ b/src/network/rewinder.hpp @@ -31,7 +31,6 @@ class Rewinder : public std::enable_shared_from_this { protected: void setUniqueIdentity(const std::string& uid) { m_unique_identity = uid; } - private: std::string m_unique_identity; @@ -92,6 +91,9 @@ public: } // ------------------------------------------------------------------------- bool rewinderAdd(); + // ------------------------------------------------------------------------- + template std::shared_ptr getShared() + { return std::dynamic_pointer_cast(shared_from_this()); } }; // Rewinder #endif From c8a50d2f49f054140ed1393aed82017417b5894c Mon Sep 17 00:00:00 2001 From: Benau Date: Tue, 24 Jul 2018 15:44:31 +0800 Subject: [PATCH 28/36] Temporarily fix rewind queue for undo --- src/network/rewind_queue.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/network/rewind_queue.cpp b/src/network/rewind_queue.cpp index 4e8bca753..b9475c4fb 100644 --- a/src/network/rewind_queue.cpp +++ b/src/network/rewind_queue.cpp @@ -354,8 +354,10 @@ int RewindQueue::undoUntil(int undo_ticks) { // A rewind is done after a state in the past is inserted. This function // makes sure that m_current is not end() - assert(m_current != m_all_rewind_info.end()); - + //assert(m_current != m_all_rewind_info.end()); + assert(!m_all_rewind_info.empty()); + m_current = m_all_rewind_info.end(); + m_current--; while((*m_current)->getTicks() > undo_ticks || (*m_current)->isEvent() || !(*m_current)->isConfirmed()) { From 1e53349f52af3b40a07ee6d893e3d56dacdf783d Mon Sep 17 00:00:00 2001 From: Benau Date: Wed, 25 Jul 2018 15:33:49 +0800 Subject: [PATCH 29/36] Rewind bowling and cake in network game --- src/items/bowling.hpp | 6 +- src/items/cake.cpp | 6 +- src/items/cake.hpp | 20 +++- src/items/flyable.cpp | 136 +++++++++++++++++++++++++- src/items/flyable.hpp | 27 ++++- src/items/plunger.cpp | 2 +- src/items/plunger.hpp | 12 ++- src/items/powerup.cpp | 15 +-- src/items/projectile_manager.cpp | 37 +++++-- src/items/projectile_manager.hpp | 6 ++ src/karts/abstract_kart_animation.cpp | 2 +- src/karts/kart.cpp | 6 +- src/karts/kart.hpp | 13 +-- src/karts/kart_rewinder.cpp | 42 ++++---- src/karts/moveable.cpp | 2 +- src/modes/soccer_world.cpp | 4 +- src/modes/world.cpp | 5 +- src/network/rewind_info.cpp | 7 ++ src/network/rewind_info.hpp | 12 ++- src/network/rewind_manager.cpp | 13 +++ src/network/rewind_manager.hpp | 11 ++- 21 files changed, 306 insertions(+), 78 deletions(-) diff --git a/src/items/bowling.hpp b/src/items/bowling.hpp index a75d82414..0309b0081 100644 --- a/src/items/bowling.hpp +++ b/src/items/bowling.hpp @@ -53,9 +53,9 @@ public: Bowling(AbstractKart* kart); virtual ~Bowling(); static void init(const XMLNode &node, scene::IMesh *bowling); - virtual bool updateAndDelete(int ticks); - virtual bool hit(AbstractKart* kart, PhysicalObject* obj=NULL); - virtual HitEffect *getHitEffect() const; + virtual bool updateAndDelete(int ticks) OVERRIDE; + virtual bool hit(AbstractKart* kart, PhysicalObject* obj=NULL) OVERRIDE; + virtual HitEffect *getHitEffect() const OVERRIDE; }; // Bowling diff --git a/src/items/cake.cpp b/src/items/cake.cpp index 5b302a753..a7f7c0128 100644 --- a/src/items/cake.cpp +++ b/src/items/cake.cpp @@ -119,11 +119,7 @@ Cake::Cake (AbstractKart *kart) : Flyable(kart, PowerupManager::POWERUP_CAKE) //do not adjust height according to terrain setAdjustUpVelocity(false); - - m_body->setActivationState(DISABLE_DEACTIVATION); - - m_body->applyTorque( btVector3(5,-3,7) ); - + additionalPhysicsProperties(); } // Cake // ----------------------------------------------------------------------------- diff --git a/src/items/cake.hpp b/src/items/cake.hpp index d22b71679..4d6184248 100644 --- a/src/items/cake.hpp +++ b/src/items/cake.hpp @@ -46,24 +46,36 @@ private: /** Which kart is targeted by this projectile (NULL if none). */ Moveable* m_target; + + // ------------------------------------------------------------------------ + virtual void additionalPhysicsProperties() OVERRIDE + { + m_body->setActivationState(DISABLE_DEACTIVATION); + m_body->clearForces(); + m_body->applyTorque(btVector3(5.0f, -3.0f, 7.0f)); + } + public: Cake (AbstractKart *kart); static void init (const XMLNode &node, scene::IMesh *cake_model); - virtual bool hit(AbstractKart* kart, PhysicalObject* obj=NULL); + virtual bool hit(AbstractKart* kart, PhysicalObject* obj=NULL) OVERRIDE; // ------------------------------------------------------------------------ - virtual void hitTrack () { hit(NULL); } + virtual void hitTrack () OVERRIDE { hit(NULL); } // ------------------------------------------------------------------------ /** Kinematic objects are not allowed to have a velocity (assertion in * bullet), so we have to do our own velocity handling here. This * function returns the velocity of this object. */ - virtual const btVector3 &getVelocity() const {return m_initial_velocity;} + virtual const btVector3 &getVelocity() const OVERRIDE + { return m_initial_velocity; } // ------------------------------------------------------------------------ /** Kinematic objects are not allowed to have a velocity (assertion in * bullet), so we have to do our own velocity handling here. This * function sets the velocity of this object. * \param v Linear velocity of this object. */ - virtual void setVelocity(const btVector3& v) {m_initial_velocity=v; } + virtual void setVelocity(const btVector3& v) OVERRIDE + { m_initial_velocity = v; } + }; // Cake #endif diff --git a/src/items/flyable.cpp b/src/items/flyable.cpp index 474e3a384..1037fd974 100644 --- a/src/items/flyable.cpp +++ b/src/items/flyable.cpp @@ -37,7 +37,11 @@ #include "karts/explosion_animation.hpp" #include "modes/linear_world.hpp" #include "modes/soccer_world.hpp" +#include "network/compress_network_body.hpp" +#include "network/network_config.hpp" #include "network/network_string.hpp" +#include "network/rewind_info.hpp" +#include "network/rewind_manager.hpp" #include "physics/physics.hpp" #include "tracks/track.hpp" #include "utils/constants.hpp" @@ -76,6 +80,10 @@ Flyable::Flyable(AbstractKart *kart, PowerupManager::PowerupType type, m_owner_has_temporary_immunity = true; m_do_terrain_info = true; m_max_lifespan = -1; + m_undo_creation = false; + m_has_undone_destruction = false; + m_has_server_state = false; + m_check_created_ticks = -1; // Add the graphical model #ifndef SERVER_ONLY @@ -161,6 +169,10 @@ void Flyable::createPhysics(float forw_offset, const Vec3 &velocity, m_body->setCollisionFlags(m_body->getCollisionFlags() | btCollisionObject::CF_NO_CONTACT_RESPONSE); + m_saved_transform = getTrans(); + m_saved_lv = m_body->getLinearVelocity(); + m_saved_av = m_body->getAngularVelocity(); + m_saved_gravity = gravity; } // createPhysics // ----------------------------------------------------------------------------- @@ -391,6 +403,9 @@ void Flyable::updateGraphics(float dt) */ bool Flyable::updateAndDelete(int ticks) { + if (m_undo_creation) + return false; + if (hasAnimation()) { m_animation->update(stk_config->ticks2Time(ticks)); @@ -503,6 +518,8 @@ bool Flyable::isOwnerImmunity(const AbstractKart* kart_hit) const */ bool Flyable::hit(AbstractKart *kart_hit, PhysicalObject* object) { + if (m_undo_creation) + return false; // the owner of this flyable should not be hit by his own flyable if(isOwnerImmunity(kart_hit)) return false; m_has_hit_something=true; @@ -579,17 +596,36 @@ unsigned int Flyable::getOwnerId() // ---------------------------------------------------------------------------- BareNetworkString* Flyable::saveState(std::vector* ru) { + ru->push_back(getUniqueIdentity()); + BareNetworkString *buffer = new BareNetworkString(); + CompressNetworkBody::compress(m_body->getWorldTransform(), + m_body->getLinearVelocity(), m_body->getAngularVelocity(), buffer); + uint16_t hit_and_ticks = (m_has_hit_something ? 1 << 15 : 0) | + m_ticks_since_thrown; + buffer->addUInt16(hit_and_ticks); + return buffer; } // saveState // ---------------------------------------------------------------------------- void Flyable::restoreState(BareNetworkString *buffer, int count) { -} // restoreState + btTransform t; + Vec3 lv, av; + CompressNetworkBody::decompress(buffer, &t, &lv, &av); -// ---------------------------------------------------------------------------- -std::function Flyable::getLocalStateRestoreFunction() -{ -} // getLocalStateRestoreFunction + m_body->setWorldTransform(t); + m_motion_state->setWorldTransform(t); + m_body->setInterpolationWorldTransform(t); + m_body->setLinearVelocity(lv); + m_body->setAngularVelocity(av); + m_body->setInterpolationLinearVelocity(lv); + m_body->setInterpolationAngularVelocity(av); + uint16_t hit_and_ticks = buffer->getUInt16(); + m_has_hit_something = (hit_and_ticks >> 15) == 1; + m_ticks_since_thrown = hit_and_ticks & ~(1 << 15); + if (!m_has_server_state) + m_has_server_state = true; +} // restoreState // ---------------------------------------------------------------------------- void Flyable::addForRewind(const std::string& uid) @@ -601,4 +637,94 @@ void Flyable::addForRewind(const std::string& uid) Rewinder::rewinderAdd(); } // addForRewind +// ---------------------------------------------------------------------------- +void Flyable::addRewindInfoEventFunctionAfterFiring() +{ + if (!NetworkConfig::get()->isNetworking() || + NetworkConfig::get()->isServer()) + return; + + std::shared_ptr f = getShared(); + RewindManager::get()->addRewindInfoEventFunction(new + RewindInfoEventFunction(World::getWorld()->getTicksSinceStart(), + /*undo_function*/[f]() + { + f->m_undo_creation = true; + const Vec3 *min, *max; + Track::getCurrentTrack()->getAABB(&min, &max); + btTransform t = f->m_body->getWorldTransform(); + // Move it to (almost infinity), avoiding affecting current + // rewinding + t.setOrigin(*max * 2.0f); + f->m_body->setWorldTransform(t); + f->m_motion_state->setWorldTransform(t); + f->m_body->setInterpolationWorldTransform(t); + f->m_body->setGravity(Vec3(0.0f)); + }, + /*replay_function*/[f]() + { + f->m_undo_creation = false; + f->m_body->setWorldTransform(f->m_saved_transform); + f->m_motion_state->setWorldTransform(f->m_saved_transform); + f->m_body->setInterpolationWorldTransform(f->m_saved_transform); + f->m_body->setLinearVelocity(f->m_saved_lv); + f->m_body->setAngularVelocity(f->m_saved_av); + f->m_body->setInterpolationLinearVelocity(f->m_saved_lv); + f->m_body->setInterpolationAngularVelocity(f->m_saved_av); + f->m_body->setGravity(f->m_saved_gravity); + f->m_ticks_since_thrown = 0; + f->m_has_hit_something = false; + f->additionalPhysicsProperties(); + }, + /*delete_function*/[f]() + { + f->m_check_created_ticks = World::getWorld()->getTicksSinceStart(); + })); +} // addRewindInfoEventFunctionAfterFiring + +// ---------------------------------------------------------------------------- +void Flyable::handleUndoDestruction() +{ + if (!NetworkConfig::get()->isNetworking() || + NetworkConfig::get()->isServer() || + m_has_undone_destruction) + return; + + m_has_undone_destruction = true; + + // If destroyed during rewind, than in theroy it should be safe to delete + // without undo + if (RewindManager::get()->isRewinding()) + return; + + // We don't bother seeing the mesh during rewinding + m_node->setVisible(false); + std::shared_ptr f = getShared(); + std::string uid = f->getUniqueIdentity(); + RewindManager::get()->addRewindInfoEventFunction(new + RewindInfoEventFunction(World::getWorld()->getTicksSinceStart(), + /*undo_function*/[f, uid]() + { + projectile_manager->addByUID(uid, f); + }, + /*replay_function*/[uid]() + { + projectile_manager->removeByUID(uid); + })); +} // handleUndoDestruction + +// ---------------------------------------------------------------------------- +void Flyable::computeError() +{ + Moveable::checkSmoothing(); + if (!m_has_server_state && m_check_created_ticks != -1 && + World::getWorld()->getTicksSinceStart() > m_check_created_ticks) + { + const std::string& uid = getUniqueIdentity(); + Log::warn("Flyable", "Item %s failed to be created on server, " + "remove it locally", uid.c_str()); + projectile_manager->removeByUID(uid); + } +} // computeError + /* EOF */ diff --git a/src/items/flyable.hpp b/src/items/flyable.hpp index c9e22a951..7d19159ba 100644 --- a/src/items/flyable.hpp +++ b/src/items/flyable.hpp @@ -105,6 +105,11 @@ protected: /** Size of this flyable. */ Vec3 m_extend; + bool m_undo_creation; + bool m_has_undone_destruction; + bool m_has_server_state; + int m_check_created_ticks; + // The flyable class stores the values for each flyable type, e.g. // speed, min_height, max_height. These variables must be static, // so we need arrays of these variables to have different values @@ -130,11 +135,11 @@ protected: /** Time since thrown. used so a kart can't hit himself when trying * something, and also to put some time limit to some collectibles */ - int16_t m_ticks_since_thrown; + int16_t m_ticks_since_thrown; /** Set to something > -1 if this flyable should auto-destrcut after * that may ticks. */ - int m_max_lifespan; + int m_max_lifespan; /** If set to true, the kart that throwns this flyable can't collide * with it for a short time. */ @@ -162,6 +167,13 @@ protected: const bool rotates=false, const bool turn_around=false, const btTransform* customDirection=NULL); + + /** Used when undoing creation or destruction. */ + btTransform m_saved_transform; + Vec3 m_saved_lv, m_saved_av, m_saved_gravity; + + virtual void additionalPhysicsProperties() {} + public: Flyable (AbstractKart* kart, @@ -229,14 +241,21 @@ public: // ------------------------------------------------------------------------ virtual void saveTransform() OVERRIDE { Moveable::prepareSmoothing(); } // ------------------------------------------------------------------------ - virtual void computeError() OVERRIDE { Moveable::checkSmoothing(); } + virtual void computeError() OVERRIDE; // ------------------------------------------------------------------------ virtual BareNetworkString* saveState(std::vector* ru) OVERRIDE; // ------------------------------------------------------------------------ virtual void restoreState(BareNetworkString *buffer, int count) OVERRIDE; // ------------------------------------------------------------------------ - virtual std::function getLocalStateRestoreFunction() OVERRIDE; + virtual void addRewindInfoEventFunctionAfterFiring(); + // ------------------------------------------------------------------------ + bool isUndoCreation() const { return m_undo_creation; } + // ------------------------------------------------------------------------ + bool hasUndoneDestruction() const { return m_has_undone_destruction; } + // ------------------------------------------------------------------------ + void handleUndoDestruction(); + }; // Flyable #endif diff --git a/src/items/plunger.cpp b/src/items/plunger.cpp index 65501a6d8..9cbafa6c3 100644 --- a/src/items/plunger.cpp +++ b/src/items/plunger.cpp @@ -100,7 +100,7 @@ Plunger::Plunger(AbstractKart *kart) { m_rubber_band = new RubberBand(this, kart); } - m_keep_alive = -1; + additionalPhysicsProperties(); } // Plunger // ---------------------------------------------------------------------------- diff --git a/src/items/plunger.hpp b/src/items/plunger.hpp index 91283a3c2..a74e9ed09 100644 --- a/src/items/plunger.hpp +++ b/src/items/plunger.hpp @@ -47,13 +47,17 @@ private: btVector3 m_initial_velocity; bool m_reverse_mode; + + virtual void additionalPhysicsProperties() OVERRIDE { m_keep_alive = -1; } + public: Plunger(AbstractKart *kart); ~Plunger(); static void init(const XMLNode &node, scene::IMesh* missile); - virtual bool updateAndDelete(int ticks); - virtual void hitTrack (); - virtual bool hit (AbstractKart *kart, PhysicalObject *obj=NULL); + virtual bool updateAndDelete(int ticks) OVERRIDE; + virtual void hitTrack () OVERRIDE; + virtual bool hit (AbstractKart *kart, PhysicalObject *obj=NULL) + OVERRIDE; // ------------------------------------------------------------------------ /** Sets the keep-alive value. Setting it to 0 will remove the plunger @@ -62,7 +66,7 @@ public: void setKeepAlive(int ticks) {m_keep_alive = ticks;} // ------------------------------------------------------------------------ /** No hit effect when it ends. */ - virtual HitEffect *getHitEffect() const {return NULL; } + virtual HitEffect *getHitEffect() const OVERRIDE { return NULL; } // ------------------------------------------------------------------------ }; // Plunger diff --git a/src/items/powerup.cpp b/src/items/powerup.cpp index 99c7b8f42..70f08dff3 100644 --- a/src/items/powerup.cpp +++ b/src/items/powerup.cpp @@ -32,6 +32,7 @@ #include "karts/controller/controller.hpp" #include "karts/kart_properties.hpp" #include "modes/world.hpp" +#include "network/rewind_manager.hpp" #include "physics/triangle_mesh.hpp" #include "tracks/track.hpp" #include "utils/string_utils.hpp" @@ -214,6 +215,8 @@ void Powerup::adjustSound() //----------------------------------------------------------------------------- void Powerup::playSound() { + if (!RewindManager::get()->isRewinding()) + m_sound_use->play(); } // playSound //----------------------------------------------------------------------------- @@ -253,7 +256,7 @@ void Powerup::use() { ItemManager::get()->switchItems(); m_sound_use->setPosition(m_kart->getXYZ()); - m_sound_use->play(); + playSound(); break; } case PowerupManager::POWERUP_CAKE: @@ -263,7 +266,7 @@ void Powerup::use() if(stk_config->m_shield_restrict_weapons) m_kart->setShieldTime(0.0f); // make weapon usage destroy the shield Powerup::adjustSound(); - m_sound_use->play(); + playSound(); projectile_manager->newProjectile(m_kart, m_type); break ; @@ -285,7 +288,7 @@ void Powerup::use() if(!new_item) return; Powerup::adjustSound(); - m_sound_use->play(); + playSound(); } else // if the kart is looking forward, use the bubblegum as a shield { @@ -335,7 +338,7 @@ void Powerup::use() //In this case this is a workaround, since the bubblegum item has two different sounds. Powerup::adjustSound(); - m_sound_use->play(); + playSound(); } // end of PowerupManager::POWERUP_BUBBLEGUM break; @@ -364,7 +367,7 @@ void Powerup::use() else m_sound_use->setPosition(m_kart->getXYZ()); - m_sound_use->play(); + playSound(); break; } } @@ -423,7 +426,7 @@ void Powerup::use() m_sound_use->setPosition(m_kart->getXYZ()); else if(player_kart) m_sound_use->setPosition(player_kart->getXYZ()); - m_sound_use->play(); + playSound(); } break; diff --git a/src/items/projectile_manager.cpp b/src/items/projectile_manager.cpp index 8b088f204..b72724cd2 100644 --- a/src/items/projectile_manager.cpp +++ b/src/items/projectile_manager.cpp @@ -74,6 +74,8 @@ void ProjectileManager::update(int ticks) { updateServer(ticks); + if (RewindManager::get()->isRewinding()) + return; HitEffects::iterator he = m_active_hit_effects.begin(); while(he!=m_active_hit_effects.end()) { @@ -102,12 +104,21 @@ void ProjectileManager::updateServer(int ticks) auto p = m_active_projectiles.begin(); while (p != m_active_projectiles.end()) { + if (p->second->isUndoCreation()) + { + p++; + continue; + } bool can_be_deleted = p->second->updateAndDelete(ticks); if (can_be_deleted) { - HitEffect *he = p->second->getHitEffect(); - if (he) - addHitEffect(he); + if (!p->second->hasUndoneDestruction()) + { + HitEffect *he = p->second->getHitEffect(); + if (he) + addHitEffect(he); + } + p->second->handleUndoDestruction(); p = m_active_projectiles.erase(p); } else @@ -125,6 +136,12 @@ std::shared_ptr ProjectileManager::newProjectile(AbstractKart *kart, PowerupManager::PowerupType type) { + const std::string& uid = getUniqueIdentity(kart, type); + auto it = m_active_projectiles.find(uid); + // Flyable already created during rewind + if (it != m_active_projectiles.end()) + return it->second; + std::shared_ptr f; switch(type) { @@ -143,8 +160,12 @@ std::shared_ptr default: return nullptr; } - const std::string& uid = getUniqueIdentity(kart, type); m_active_projectiles[uid] = f; + if (RewindManager::get()->isEnabled()) + { + f->addForRewind(uid); + f->addRewindInfoEventFunctionAfterFiring(); + } return f; } // newProjectile @@ -161,6 +182,8 @@ bool ProjectileManager::projectileIsClose(const AbstractKart * const kart, for (auto i = m_active_projectiles.begin(); i != m_active_projectiles.end(); i++) { + if (i->second->isUndoCreation()) + continue; float dist2 = i->second->getXYZ().distance2(kart->getXYZ()); if (dist2 < r2) return true; @@ -183,6 +206,8 @@ int ProjectileManager::getNearbyProjectileCount(const AbstractKart * const kart, for (auto i = m_active_projectiles.begin(); i != m_active_projectiles.end(); i++) { + if (i->second->isUndoCreation()) + continue; if (i->second->getType() == type) { float dist2 = i->second->getXYZ().distance2(kart->getXYZ()); @@ -237,8 +262,8 @@ std::shared_ptr return nullptr; AbstractKart* kart = World::getWorld()->getKart(world_id); char first_id = id[0][0]; - Log::warn("ProjectileManager", - "Missed a firing event, add the flyable %s manually", uid.c_str()); + Log::debug("ProjectileManager", "Missed a firing event or locally deleted," + " add the flyable %s manually", uid.c_str()); switch (first_id) { case 'B': diff --git a/src/items/projectile_manager.hpp b/src/items/projectile_manager.hpp index 236026570..bfae1cdd6 100644 --- a/src/items/projectile_manager.hpp +++ b/src/items/projectile_manager.hpp @@ -81,6 +81,12 @@ public: // ------------------------------------------------------------------------ std::shared_ptr newProjectile(AbstractKart *kart, PowerupManager::PowerupType type); + // ------------------------------------------------------------------------ + void addByUID(const std::string& uid, std::shared_ptr f) + { m_active_projectiles[uid] = f; } + // ------------------------------------------------------------------------ + void removeByUID(const std::string& uid) + { m_active_projectiles.erase(uid); } }; diff --git a/src/karts/abstract_kart_animation.cpp b/src/karts/abstract_kart_animation.cpp index d4424a656..539ac7412 100644 --- a/src/karts/abstract_kart_animation.cpp +++ b/src/karts/abstract_kart_animation.cpp @@ -89,7 +89,7 @@ AbstractKartAnimation::~AbstractKartAnimation() Vec3 linear_velocity = kart->getBody()->getLinearVelocity(); Vec3 angular_velocity = kart->getBody()->getAngularVelocity(); btTransform transform = kart->getBody()->getWorldTransform(); - RewindManager::get()->getRewindQueue().insertRewindInfo(new + RewindManager::get()->addRewindInfoEventFunction(new RewindInfoEventFunction( World::getWorld()->getTicksSinceStart(), [kart]() diff --git a/src/karts/kart.cpp b/src/karts/kart.cpp index 3d3d68b20..976b64ab8 100644 --- a/src/karts/kart.cpp +++ b/src/karts/kart.cpp @@ -1297,12 +1297,12 @@ void Kart::update(int ticks) } } // if squashed - if (m_bubblegum_ticks > 0.0f) + if (m_bubblegum_ticks > 0) { m_bubblegum_ticks -= ticks; - if (m_bubblegum_ticks <= 0.0f) + if (m_bubblegum_ticks <= 0) { - m_bubblegum_torque = 0.0f; + m_bubblegum_torque = 0; } } diff --git a/src/karts/kart.hpp b/src/karts/kart.hpp index 9e78fe8d0..4f3430942 100644 --- a/src/karts/kart.hpp +++ b/src/karts/kart.hpp @@ -160,17 +160,17 @@ protected: int m_bounce_back_ticks; /** Time a kart is invulnerable. */ - int m_invulnerable_ticks; + int16_t m_invulnerable_ticks; /** How long a kart is being squashed. If this is >0 * the kart is squashed. */ - int m_squash_ticks; + int16_t m_squash_ticks; /** Current leaning of the kart. */ float m_current_lean; /** If > 0 then bubble gum effect is on. This is the sliding when hitting a gum on the floor, not the shield. */ - int m_bubblegum_ticks; + int16_t m_bubblegum_ticks; /** The torque to apply after hitting a bubble gum. */ float m_bubblegum_torque; @@ -218,13 +218,10 @@ protected: /** When a kart has its view blocked by the plunger, this variable will be * > 0 the number it contains is the time left before removing plunger. */ - int m_view_blocked_by_plunger; + int16_t m_view_blocked_by_plunger; /** The current speed (i.e. length of velocity vector) of this kart. */ float m_speed; - /** For camera handling an exponentially smoothened value is used, which - * reduces stuttering of the camera. */ - float m_smoothed_speed; - + /** For smoothing engine sound**/ float m_last_factor_engine_sound; diff --git a/src/karts/kart_rewinder.cpp b/src/karts/kart_rewinder.cpp index 8b80c30b7..735f34615 100644 --- a/src/karts/kart_rewinder.cpp +++ b/src/karts/kart_rewinder.cpp @@ -143,6 +143,16 @@ BareNetworkString* KartRewinder::saveState(std::vector* ru) // ----------- m_skidding->saveState(buffer); + // 6) Firing and related handling + // ----------- + buffer->addUInt16(m_bubblegum_ticks); + buffer->addUInt16(m_squash_ticks); + buffer->addUInt16(m_view_blocked_by_plunger); + // m_invulnerable_ticks will not be negative + uint16_t fire_and_invulnerable = (m_fire_clicked ? 1 << 15 : 0) | + m_invulnerable_ticks; + buffer->addUInt16(fire_and_invulnerable); + return buffer; } // saveState @@ -202,15 +212,22 @@ void KartRewinder::restoreState(BareNetworkString *buffer, int count) float nitro = buffer->getFloat(); setEnergy(nitro); - // 5) Max speed info + // 4) Max speed info // ------------------ m_max_speed->rewindTo(buffer); - // 6) Skidding + // 5) Skidding // ----------- m_skidding->rewindTo(buffer); - return; + // 6) Firing and related handling + // ----------- + m_bubblegum_ticks = buffer->getUInt16(); + m_squash_ticks = buffer->getUInt16(); + m_view_blocked_by_plunger = buffer->getUInt16(); + uint16_t fire_and_invulnerable = buffer->getUInt16(); + m_fire_clicked = (fire_and_invulnerable >> 15) == 1; + m_invulnerable_ticks = fire_and_invulnerable & ~(1 << 15); } // restoreState // ---------------------------------------------------------------------------- @@ -228,14 +245,10 @@ std::function KartRewinder::getLocalStateRestoreFunction() if (m_eliminated) return nullptr; - // In theory all ticks / boolean related stuff can be saved locally + // Variable can be saved locally if its adjustment only depends on the kart + // itself bool has_started = m_has_started; - int bubblegum_ticks = m_bubblegum_ticks; int bounce_back_ticks = m_bounce_back_ticks; - int invulnerable_ticks = m_invulnerable_ticks; - int squash_ticks = m_squash_ticks; - bool fire_clicked = m_fire_clicked; - int view_blocked_by_plunger = m_view_blocked_by_plunger; int brake_ticks = m_brake_ticks; int8_t min_nitro_ticks = m_min_nitro_ticks; @@ -253,18 +266,11 @@ std::function KartRewinder::getLocalStateRestoreFunction() steer_val_r = pc->m_steer_val_r; } - return [has_started, bubblegum_ticks, bounce_back_ticks, - invulnerable_ticks, squash_ticks, fire_clicked, - view_blocked_by_plunger, brake_ticks, min_nitro_ticks, initial_speed, - node_scale, steer_val_l, steer_val_r, this]() + return [has_started, bounce_back_ticks, brake_ticks, min_nitro_ticks, + initial_speed, node_scale, steer_val_l, steer_val_r, this]() { m_has_started = has_started; - m_bubblegum_ticks = bubblegum_ticks; m_bounce_back_ticks = bounce_back_ticks; - m_invulnerable_ticks = invulnerable_ticks; - m_squash_ticks = squash_ticks; - m_fire_clicked = fire_clicked; - m_view_blocked_by_plunger = view_blocked_by_plunger; m_brake_ticks = brake_ticks; m_min_nitro_ticks = min_nitro_ticks; getAttachment()->setInitialSpeed(initial_speed); diff --git a/src/karts/moveable.cpp b/src/karts/moveable.cpp index 492315f36..cf16491fe 100644 --- a/src/karts/moveable.cpp +++ b/src/karts/moveable.cpp @@ -64,7 +64,7 @@ void Moveable::updateSmoothedGraphics(float dt) { Vec3 velocity; if (m_body) - velocity = getVelocity(); + velocity = m_body->getLinearVelocity(); SmoothNetworkBody::updateSmoothedGraphics(m_transform, velocity, dt); #undef DEBUG_SMOOTHING #ifdef DEBUG_SMOOTHING diff --git a/src/modes/soccer_world.cpp b/src/modes/soccer_world.cpp index afbd193d8..fbb4db5e7 100644 --- a/src/modes/soccer_world.cpp +++ b/src/modes/soccer_world.cpp @@ -356,7 +356,7 @@ void SoccerWorld::handleResetBallFromServer(const NetworkString& ns) "%d when reset player", ticks_back_to_own_goal, ticks_now); return; } - RewindManager::get()->getRewindQueue().insertRewindInfo(new + RewindManager::get()->addRewindInfoEventFunction(new RewindInfoEventFunction(ticks_back_to_own_goal, [](){}, std::bind(&SoccerWorld::resetKartsToSelfGoals, this))); @@ -416,7 +416,7 @@ void SoccerWorld::handlePlayerGoalFromServer(const NetworkString& ns) kart->setTrans(transform_now); m_goal_transforms[i] = transform_now; } - RewindManager::get()->getRewindQueue().insertRewindInfo(new + RewindManager::get()->addRewindInfoEventFunction(new RewindInfoEventFunction(ticks_back_to_own_goal, [](){}, std::bind(&SoccerWorld::resetKartsToSelfGoals, this))); diff --git a/src/modes/world.cpp b/src/modes/world.cpp index 94381a06a..bb2b0c54c 100644 --- a/src/modes/world.cpp +++ b/src/modes/world.cpp @@ -300,6 +300,7 @@ void World::reset() SFXManager::get()->resumeAll(); projectile_manager->cleanup(); + RewindManager::get()->reset(); race_manager->reset(); // Make sure to overwrite the data from the previous race. if(!history->replayHistory()) history->initRecording(); @@ -1054,13 +1055,15 @@ void World::update(int ticks) m_karts[i]->update(ticks); } PROFILER_POP_CPU_MARKER(); + if(race_manager->isRecordingRace()) ReplayRecorder::get()->update(ticks); PROFILER_PUSH_CPU_MARKER("World::update (projectiles)", 0xa0, 0x7F, 0x00); projectile_manager->update(ticks); PROFILER_POP_CPU_MARKER(); - if(race_manager->isRecordingRace()) ReplayRecorder::get()->update(ticks); + PROFILER_PUSH_CPU_MARKER("World::update (physics)", 0xa0, 0x7F, 0x00); Physics::getInstance()->update(ticks); + PROFILER_POP_CPU_MARKER(); PROFILER_POP_CPU_MARKER(); diff --git a/src/network/rewind_info.cpp b/src/network/rewind_info.cpp index 6dd9d841a..abf6b7460 100644 --- a/src/network/rewind_info.cpp +++ b/src/network/rewind_info.cpp @@ -21,6 +21,7 @@ #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. @@ -67,6 +68,12 @@ void RewindInfoState::restore() std::shared_ptr 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()); diff --git a/src/network/rewind_info.hpp b/src/network/rewind_info.hpp index 8d55ff387..26310ea74 100644 --- a/src/network/rewind_info.hpp +++ b/src/network/rewind_info.hpp @@ -172,14 +172,18 @@ public: class RewindInfoEventFunction : public RewindInfo { private: - const std::function m_undo_function, m_replay_function; + const std::function m_undo_function, m_replay_function, + m_destroy_function; public: RewindInfoEventFunction(int ticks, std::function undo_function = [](){}, std::function replay_function = [](){}, - bool is_confirmed = true) - : RewindInfo(ticks, is_confirmed), - m_undo_function(undo_function), m_replay_function(replay_function) {} + std::function destroy_function = [](){}) + : RewindInfo(ticks, true/*is_confirmed*/), + m_undo_function(undo_function), m_replay_function(replay_function), + m_destroy_function(destroy_function) {} + // ------------------------------------------------------------------------ + ~RewindInfoEventFunction() { m_destroy_function(); } // ------------------------------------------------------------------------ /** An event is never 'restored', it is only rewound. */ void restore() {} diff --git a/src/network/rewind_manager.cpp b/src/network/rewind_manager.cpp index 88eff9409..c881f99b9 100644 --- a/src/network/rewind_manager.cpp +++ b/src/network/rewind_manager.cpp @@ -217,6 +217,10 @@ void RewindManager::update(int ticks_not_used) */ void RewindManager::playEventsTill(int world_ticks, int *ticks) { + // We add the RewindInfoEventFunction to rewind queue before and after + // possible rewind, some RewindInfoEventFunction can be created during + // rewind + mergeRewindInfoEventFunction(); bool needs_rewind; int rewind_ticks; @@ -367,6 +371,7 @@ void RewindManager::rewindTo(int rewind_ticks, int now_ticks) history->setReplayHistory(is_history); m_is_rewinding = false; + mergeRewindInfoEventFunction(); } // rewindTo // ---------------------------------------------------------------------------- @@ -375,3 +380,11 @@ bool RewindManager::useLocalEvent() const return NetworkConfig::get()->isNetworking() && NetworkConfig::get()->isClient() && !m_is_rewinding; } // useLocalEvent + +// ---------------------------------------------------------------------------- +void RewindManager::mergeRewindInfoEventFunction() +{ + for (RewindInfoEventFunction* rief : m_pending_rief) + m_rewind_queue.insertRewindInfo(rief); + m_pending_rief.clear(); +} // mergeRewindInfoEventFunction diff --git a/src/network/rewind_manager.hpp b/src/network/rewind_manager.hpp index a8aa929a8..3a6ff4be1 100644 --- a/src/network/rewind_manager.hpp +++ b/src/network/rewind_manager.hpp @@ -28,10 +28,12 @@ #include #include #include +#include #include class Rewinder; class RewindInfo; +class RewindInfoEventFunction; class EventRewinder; /** \ingroup network @@ -116,6 +118,8 @@ private: * rewinds. */ std::atomic m_not_rewound_ticks; + std::vector m_pending_rief; + RewindManager(); ~RewindManager(); // ------------------------------------------------------------------------ @@ -131,6 +135,8 @@ private: it++; } } + // ------------------------------------------------------------------------ + void mergeRewindInfoEventFunction(); public: // First static functions to manage rewinding. @@ -187,8 +193,6 @@ public: return m_not_rewound_ticks.load(std::memory_order_relaxed); } // getNotRewoundWorldTicks // ------------------------------------------------------------------------ - RewindQueue& getRewindQueue() { return m_rewind_queue; } - // ------------------------------------------------------------------------ /** Returns the time of the latest confirmed state. */ int getLatestConfirmedState() const { @@ -205,6 +209,9 @@ public: { return m_current_rewinder_using; } // ------------------------------------------------------------------------ bool useLocalEvent() const; + // ------------------------------------------------------------------------ + void addRewindInfoEventFunction(RewindInfoEventFunction* rief) + { m_pending_rief.push_back(rief); } }; // RewindManager From deb6d7650493e79c288b5bdda8ad3b8cbe6265c5 Mon Sep 17 00:00:00 2001 From: hiker Date: Wed, 25 Jul 2018 17:33:01 +1000 Subject: [PATCH 30/36] Fixed compiler warning. --- src/guiengine/widgets/ribbon_widget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/guiengine/widgets/ribbon_widget.cpp b/src/guiengine/widgets/ribbon_widget.cpp index 28a7bbc36..2392925b3 100644 --- a/src/guiengine/widgets/ribbon_widget.cpp +++ b/src/guiengine/widgets/ribbon_widget.cpp @@ -684,7 +684,7 @@ void RibbonWidget::selectNextActiveWidget(const bool horizontally, const bool re } loop_counter++; - if (loop_counter > m_active_children.size()) + if (loop_counter > (int)m_active_children.size()) { Log::warn("RibbonWidget", "All the buttons of the focused ribbon" " are deactivated !"); From 7cca534273c28241a3220ae62dec1b4448fe9348 Mon Sep 17 00:00:00 2001 From: hiker Date: Wed, 25 Jul 2018 18:09:05 +1000 Subject: [PATCH 31/36] Added option to reduce steering of remote karts automatically each frame. This can help in case of high latency connections and quick steering changes: because of the high latency the steering is applied too long locally, reducing in the other kart driving left/right way too much. It's disabled for now (i.e. steering is multiplied by 1.0), but can be enabled in stk_config. --- data/stk_config.xml | 5 ++++- src/config/stk_config.cpp | 3 +++ src/config/stk_config.hpp | 5 +++++ src/karts/controller/controller.cpp | 3 ++- src/karts/controller/network_player_controller.hpp | 14 ++++++++++++++ 5 files changed, 28 insertions(+), 2 deletions(-) diff --git a/data/stk_config.xml b/data/stk_config.xml index acb22f19f..20318f080 100644 --- a/data/stk_config.xml +++ b/data/stk_config.xml @@ -180,8 +180,11 @@ - +