Initial working of starting game if no physical object exists

This commit is contained in:
Benau 2020-02-28 19:51:40 +08:00
parent 6b08a873a2
commit d41594ea5b
13 changed files with 218 additions and 35 deletions

View File

@ -202,7 +202,7 @@ Item::Item(ItemType type, const Vec3& xyz, const Vec3& normal,
m_graphical_type = getGrahpicalType();
m_node = NULL;
if (!GUIEngine::isNoGraphics())
if (mesh && !GUIEngine::isNoGraphics())
{
LODNode* lodnode =
new LODNode("item", irr_driver->getSceneManager()->getRootSceneNode(),

View File

@ -119,7 +119,6 @@ protected:
int m_switch_ticks;
void deleteItem(ItemState *item);
virtual unsigned int insertItem(Item *item);
void switchItemsInternal(std::vector < ItemState*> &all_items);
void setSwitchItems(const std::vector<int> &switch_items);
void insertItemInQuad(Item *item);
@ -198,6 +197,8 @@ public:
? NULL
: dynamic_cast<Item*>((*m_items_in_quads)[n].front());
} // getFirstItemInQuad
// ------------------------------------------------------------------------
unsigned int insertItem(Item *item);
}; // ItemManager
#endif

View File

@ -52,9 +52,11 @@
#include "karts/kart_rewinder.hpp"
#include "main_loop.hpp"
#include "modes/overworld.hpp"
#include "network/child_loop.hpp"
#include "network/protocols/client_lobby.hpp"
#include "network/network_config.hpp"
#include "network/rewind_manager.hpp"
#include "network/stk_host.hpp"
#include "physics/btKart.hpp"
#include "physics/physics.hpp"
#include "physics/triangle_mesh.hpp"
@ -200,7 +202,20 @@ void World::init()
// Load the track models - this must be done before the karts so that the
// karts can be positioned properly on (and not in) the tracks.
// This also defines the static Track::getCurrentTrack function.
track->loadTrackModel(RaceManager::get()->getReverseTrack());
if (m_process_type == PT_MAIN)
track->loadTrackModel(RaceManager::get()->getReverseTrack());
else
{
Track* child_track = Track::getCurrentTrack();
ChildLoop* child_loop = STKHost::getByType(PT_MAIN)->getChildLoop();
while (!child_loop->isAborted() && child_track == NULL)
{
StkTime::sleep(1);
child_track = Track::getCurrentTrack();
}
if (!child_loop->isAborted())
child_track->initChildTrack();
}
// Shuffles the start transforms with playing 3-strikes or free for all battles.
if ((RaceManager::get()->getMinorMode() == RaceManager::MINOR_MODE_3_STRIKES ||
@ -597,8 +612,13 @@ World::~World()
ProjectileManager::get()->cleanup();
// In case that a race is aborted (e.g. track not found) track is 0.
if(Track::getCurrentTrack())
Track::getCurrentTrack()->cleanup();
if (m_process_type == PT_MAIN)
{
if(Track::getCurrentTrack())
Track::getCurrentTrack()->cleanup();
}
else
Track::cleanChildTrack();
// Delete the in-race-gui:
if(m_saved_race_gui)

View File

@ -19,9 +19,11 @@
#include "config/user_config.hpp"
#include "guiengine/engine.hpp"
#include "items/projectile_manager.hpp"
#include "modes/world.hpp"
#include "network/network_config.hpp"
#include "network/protocol_manager.hpp"
#include "network/protocols/server_lobby.hpp"
#include "network/race_event_manager.hpp"
#include "network/server_config.hpp"
#include "network/stk_host.hpp"
#include "race/race_manager.hpp"
@ -104,13 +106,8 @@ void ChildLoop::run()
float left_over_time = 0;
while (!m_abort)
{
if ((STKHost::existHost() && STKHost::get()->requestedShutdown()) ||
m_request_abort)
{
if (STKHost::existHost())
STKHost::get()->shutdown();
m_abort = true;
}
if (STKHost::existHost() && STKHost::get()->requestedShutdown())
break;
// Tell the main process port and server id
if (m_port == 0 && STKHost::existHost())
@ -134,11 +131,33 @@ void ChildLoop::run()
if (auto pm = ProtocolManager::lock())
pm->update(1);
if (m_abort || m_request_abort)
World* w = World::getWorld();
if (w && w->getPhase() == WorldStatus::SETUP_PHASE)
{
// Skip the large num steps contributed by loading time
w->updateTime(1);
break;
}
if (w)
{
auto rem = RaceEventManager::get();
if (rem && rem->isRunning())
RaceEventManager::get()->update(1, false/*fast_forward*/);
else
w->updateWorld(1);
w->updateTime(1);
}
if (m_abort)
break;
}
}
if (STKHost::existHost())
STKHost::get()->shutdown();
if (World::getWorld())
RaceManager::get()->exitRace();
RaceManager::destroy();
ProjectileManager::destroy();
NetworkConfig::destroy();

View File

@ -37,8 +37,6 @@ private:
std::atomic_bool m_abort;
std::atomic_bool m_request_abort;
std::atomic<uint16_t> m_port;
std::atomic<uint32_t> m_server_online_id;
@ -51,7 +49,6 @@ public:
: m_cl_config(new ChildLoopConfig(clc))
{
m_abort = false;
m_request_abort = false;
m_prev_time = m_curr_time = 0;
m_port = 0;
m_server_online_id = 0;
@ -59,7 +56,7 @@ public:
void run();
/** Set the abort flag, causing the mainloop to be left. */
void abort() { m_abort = true; }
void requestAbort() { m_request_abort = true; }
bool isAborted() const { return m_abort; }
uint16_t getPort() const { return m_port; }
uint32_t getServerOnlineId() const { return m_server_online_id; }
}; // ChildLoop

View File

@ -962,16 +962,18 @@ void ClientLobby::startGame(Event* event)
nim->restoreCompleteState(event->data());
core::stringw err_msg = _("Failed to start the network game.");
// Different stk process thread may have different stk host
STKHost* stk_host = STKHost::get();
joinStartGameThread();
m_start_game_thread = std::thread([start_time, this, err_msg]()
m_start_game_thread = std::thread([start_time, stk_host, this, err_msg]()
{
const uint64_t cur_time = STKHost::get()->getNetworkTimer();
const uint64_t cur_time = stk_host->getNetworkTimer();
if (!(start_time > cur_time))
{
Log::error("ClientLobby", "Network timer is too slow to catch "
"up, you must have a poor network.");
STKHost::get()->setErrorMessage(err_msg);
STKHost::get()->requestShutdown();
stk_host->setErrorMessage(err_msg);
stk_host->requestShutdown();
return;
}
int sleep_time = (int)(start_time - cur_time);

View File

@ -179,6 +179,19 @@ public:
return nullptr;
} // get
// ------------------------------------------------------------------------
/** Returns specific singleton client or server lobby protocol. */
template<class T> static std::shared_ptr<T> getByType(ProcessType pt)
{
if (std::shared_ptr<LobbyProtocol> lp = m_lobby[pt].lock())
{
std::shared_ptr<T> new_type = std::dynamic_pointer_cast<T>(lp);
if (new_type)
return new_type;
}
return nullptr;
} // get
// ------------------------------------------------------------------------
LobbyProtocol();

View File

@ -4403,10 +4403,12 @@ void ServerLobby::configPeersStartTime()
m_state = WAIT_FOR_RACE_STARTED;
World::getWorld()->setPhase(WorldStatus::SERVER_READY_PHASE);
// Different stk process thread may have different stk host
STKHost* stk_host = STKHost::get();
joinStartGameThread();
m_start_game_thread = std::thread([start_time, this]()
m_start_game_thread = std::thread([start_time, stk_host, this]()
{
const uint64_t cur_time = STKHost::get()->getNetworkTimer();
const uint64_t cur_time = stk_host->getNetworkTimer();
assert(start_time > cur_time);
int sleep_time = (int)(start_time - cur_time);
//Log::info("ServerLobby", "Start game after %dms", sleep_time);

View File

@ -352,7 +352,7 @@ STKHost::~STKHost()
// Abort the server loop earlier so it can be stopped in background as
// soon as possible
if (m_client_loop)
m_client_loop->requestAbort();
m_client_loop->abort();
NetworkConfig::get()->clearActivePlayersForClient();
requestShutdown();

View File

@ -189,6 +189,12 @@ public:
return m_stk_host[pt];
} // get
// ------------------------------------------------------------------------
static STKHost *getByType(ProcessType pt)
{
assert(m_stk_host[pt] != NULL);
return m_stk_host[pt];
} // get
// ------------------------------------------------------------------------
static void destroy()
{
ProcessType pt = STKProcess::getType();

View File

@ -146,6 +146,18 @@ public:
assert(indx < m_p1p2p3.size());
return m_p1p2p3[indx];
}
// ------------------------------------------------------------------------
void copyFrom(const TriangleMesh& tm)
{
for (int i = 0; i < tm.m_mesh.getNumTriangles(); i++)
{
btVector3 v[6];
tm.getTriangle(i, v, v + 1, v + 2);
tm.getNormals(i, v + 3, v + 4, v + 5);
const Material* m = tm.getMaterial(i);
addTriangle(v[0], v[1], v[2], v[3], v[4], v[5], m);
}
}
};
#endif
/* EOF */

View File

@ -70,6 +70,7 @@
#include "tracks/arena_graph.hpp"
#include "tracks/bezier_curve.hpp"
#include "tracks/check_manager.hpp"
#include "tracks/check_structure.hpp"
#include "tracks/drive_graph.hpp"
#include "tracks/drive_node.hpp"
#include "tracks/model_definition_loader.hpp"
@ -99,7 +100,7 @@ using namespace irr;
const float Track::NOHIT = -99999.9f;
bool Track::m_dont_load_navmesh = false;
Track *Track::m_current_track = NULL;
std::atomic<Track*> Track::m_current_track[PT_COUNT];
// ----------------------------------------------------------------------------
Track::Track(const std::string &filename)
@ -347,8 +348,6 @@ void Track::cleanup()
}
m_static_physics_only_nodes.clear();
m_all_emitters.clearAndDeleteAll();
delete m_check_manager;
m_check_manager = NULL;
@ -507,7 +506,7 @@ void Track::cleanup()
m_meta_library.clear();
Scripting::ScriptEngine::getInstance()->cleanupCache();
m_current_track = NULL;
m_current_track[PT_MAIN] = NULL;
} // cleanup
//-----------------------------------------------------------------------------
@ -1620,10 +1619,18 @@ void Track::updateGraphics(float dt)
*/
void Track::update(int ticks)
{
if (!m_startup_run) // first time running update = good point to run startup script
ProcessType type = STKProcess::getType();
if (type == PT_MAIN && !m_startup_run) // first time running update = good point to run startup script
{
Scripting::ScriptEngine::getInstance()->runFunction(false, "void onStart()");
m_startup_run = true;
// After onStart all track objects will be hidden as needed
// we only copy track objects with physical body which affects network
if (LobbyProtocol::getByType<LobbyProtocol>(PT_CHILD))
{
Track* child_track = clone();
m_current_track[PT_CHILD] = child_track;
}
}
float dt = stk_config->ticks2Time(ticks);
m_check_manager->update(dt);
@ -1781,7 +1788,7 @@ static void recursiveUpdatePhysics(std::vector<TrackObject*>& tos)
*/
void Track::loadTrackModel(bool reverse_track, unsigned int mode_id)
{
assert(!m_current_track);
assert(m_current_track[PT_MAIN].load() == NULL);
// Use m_filename to also get the path, not only the identifier
STKTexManager::getInstance()
@ -1876,7 +1883,8 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id)
throw std::runtime_error(msg.str());
}
m_current_track = this;
m_current_track[PT_MAIN] = this;
m_current_track[PT_CHILD] = NULL;
// Load the graph only now: this function is called from world, after
// the race gui was created. The race gui is needed since it stores
@ -2865,3 +2873,90 @@ void Track::uploadNodeVertexBuffer(scene::ISceneNode *node)
}
#endif
} // uploadNodeVertexBuffer
//-----------------------------------------------------------------------------
void Track::copyFromMainProcess()
{
// Clear all unneeded objects copied in main process track
m_physical_object_uid = 0;
m_animated_textures.clear();
m_animated_textures.shrink_to_fit();
m_all_nodes.clear();
m_all_nodes.shrink_to_fit();
m_static_physics_only_nodes.clear();
m_static_physics_only_nodes.shrink_to_fit();
m_object_physics_only_nodes.clear();
m_object_physics_only_nodes.shrink_to_fit();
m_sun = NULL;
m_all_cached_meshes.clear();
m_all_cached_meshes.shrink_to_fit();
m_detached_cached_meshes.clear();
m_detached_cached_meshes.shrink_to_fit();
m_sky_textures.clear();
m_sky_textures.shrink_to_fit();
m_spherical_harmonics_textures.clear();
m_spherical_harmonics_textures.shrink_to_fit();
m_meta_library.clear();
m_meta_library.shrink_to_fit();
// Clone the needed object now in main process
Track* main_track = m_current_track[PT_MAIN];
CheckManager* main_cm = main_track->m_check_manager;
m_check_manager = new CheckManager();
for (unsigned i = 0; i < main_cm->getCheckStructureCount(); i++)
{
CheckStructure* cs = main_cm->getCheckStructure(i);
m_check_manager->add(cs->clone());
}
m_track_object_manager = new TrackObjectManager();
m_track_mesh = new TriangleMesh(/*can_be_transformed*/false);
m_gfx_effect_mesh = new TriangleMesh(/*can_be_transformed*/false);
m_track_mesh->copyFrom(*main_track->m_track_mesh);
m_gfx_effect_mesh->copyFrom(*main_track->m_gfx_effect_mesh);
// At the moment we only use network for child track
auto nim = std::make_shared<NetworkItemManager>();
for (unsigned i = 0; i < m_item_manager->getNumberOfItems(); i++)
{
ItemState* it = m_item_manager->getItem(i);
nim->insertItem(new Item(it->getType(), it->getXYZ(), it->getNormal(),
NULL/*mesh*/, NULL/*lowres_mesh*/, NULL/*owner*/));
}
m_item_manager = nim;
} // copyFromMainProcess
//-----------------------------------------------------------------------------
void Track::initChildTrack()
{
// This will be called in child process after main one copied to it
assert(STKProcess::getType() == PT_CHILD);
// Add in child process for rewind manager
std::dynamic_pointer_cast<NetworkItemManager>
(m_item_manager)->rewinderAdd();
// We call physics init in child process too
Physics::get()->init(m_aabb_min, m_aabb_max);
m_track_mesh->createPhysicalBody(m_friction);
m_gfx_effect_mesh->createCollisionShape();
if (auto sl = LobbyProtocol::get<ServerLobby>())
{
sl->saveInitialItems(
std::dynamic_pointer_cast<NetworkItemManager>(m_item_manager));
}
} // initChildTrack
//-----------------------------------------------------------------------------
void Track::cleanChildTrack()
{
assert(STKProcess::getType() == PT_CHILD);
Track* child_track = m_current_track[PT_CHILD];
child_track->m_item_manager = nullptr;
delete child_track->m_check_manager;
delete child_track->m_track_object_manager;
delete child_track->m_track_mesh;
delete child_track->m_gfx_effect_mesh;
delete child_track;
m_current_track[PT_CHILD] = NULL;
} // cleanChildTrack

View File

@ -27,6 +27,7 @@
*/
#include <algorithm>
#include <atomic>
#include <memory>
#include <string>
#include <vector>
@ -40,7 +41,7 @@ using namespace irr;
#include "utils/aligned_array.hpp"
#include "utils/log.hpp"
#include "utils/vec3.hpp"
#include "utils/ptr_vector.hpp"
#include "utils/stk_process.hpp"
class AbstractKart;
class AnimationManager;
@ -101,7 +102,7 @@ private:
/** If a race is in progress, this stores the active track object.
* NULL otherwise. */
static Track *m_current_track;
static std::atomic<Track*> m_current_track[PT_COUNT];
#ifdef DEBUG
unsigned int m_magic_number;
@ -189,7 +190,6 @@ private:
std::vector<std::string> m_old_mesh_buffers;
#endif
PtrVector<ParticleEmitter> m_all_emitters;
scene::ISceneNode *m_sun;
/** Used to collect the triangles for the bullet mesh. */
TriangleMesh* m_track_mesh;
@ -406,11 +406,27 @@ private:
void loadCurves(const XMLNode &node);
void handleSky(const XMLNode &root, const std::string &filename);
void freeCachedMeshVertexBuffer();
void copyFromMainProcess();
public:
/** Static function to get the current track. NULL if no current
* track is defined (i.e. no race is active atm) */
static Track* getCurrentTrack() { return m_current_track; }
static Track* getCurrentTrack()
{
ProcessType type = STKProcess::getType();
return m_current_track[type];
}
// ------------------------------------------------------------------------
Track* clone()
{
Track* child_track = new Track(*this);
child_track->copyFromMainProcess();
return child_track;
}
// ------------------------------------------------------------------------
void initChildTrack();
// ------------------------------------------------------------------------
static void cleanChildTrack();
// ------------------------------------------------------------------------
void handleAnimatedTextures(scene::ISceneNode *node, const XMLNode &xml);