Initial working of starting game if no physical object exists
This commit is contained in:
parent
6b08a873a2
commit
d41594ea5b
@ -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(),
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user