This commit is contained in:
Alayan
2018-09-20 22:22:56 +02:00
9 changed files with 155 additions and 158 deletions

View File

@@ -34,8 +34,6 @@
#include "input/input_manager.hpp"
#include "modes/demo_world.hpp"
#include "modes/world.hpp"
#include "network/network_config.hpp"
#include "network/stk_host.hpp"
#include "states_screens/state_manager.hpp"
#include "utils/debug.hpp"
#include "utils/profiler.hpp"
@@ -186,21 +184,6 @@ bool EventHandler::OnEvent (const SEvent &event)
SFXManager::get()->resumeAll();
}
}
else if (cmd == APP_CMD_TERM_WINDOW)
{
if (STKHost::existHost() && NetworkConfig::get()->isWAN())
{
STKHost::get()->requestShutdownDelayed(10000);
}
}
else if (cmd == APP_CMD_INIT_WINDOW)
{
if (STKHost::existHost() && NetworkConfig::get()->isWAN() &&
!STKHost::get()->requestedShutdown())
{
STKHost::get()->cancelShutdown();
}
}
else if (cmd == APP_CMD_LOW_MEMORY)
{
Log::warn("EventHandler", "Low memory event received");

View File

@@ -388,25 +388,26 @@ void MultitouchDevice::updateAxisY(float value)
*/
void MultitouchDevice::handleControls(MultitouchButton* button)
{
if (m_controller == NULL)
if (!isGameRunning())
return;
if (button->type == MultitouchButtonType::BUTTON_STEERING)
{
updateAxisX(button->axis_x);
updateAxisY(button->axis_y);
}
else if (button->type == MultitouchButtonType::BUTTON_UP_DOWN)
{
updateAxisY(button->axis_y);
}
else if (button->type == MultitouchButtonType::BUTTON_ESCAPE)
if (button->type == MultitouchButtonType::BUTTON_ESCAPE)
{
StateManager::get()->escapePressed();
}
else
if (m_controller != NULL && !race_manager->isWatchingReplay())
{
if (button->action != PA_BEFORE_FIRST)
if (button->type == MultitouchButtonType::BUTTON_STEERING)
{
updateAxisX(button->axis_x);
updateAxisY(button->axis_y);
}
else if (button->type == MultitouchButtonType::BUTTON_UP_DOWN)
{
updateAxisY(button->axis_y);
}
else if (button->action != PA_BEFORE_FIRST)
{
int value = button->pressed ? Input::MAX_VALUE : 0;
m_controller->action(button->action, value);
@@ -416,6 +417,15 @@ void MultitouchDevice::handleControls(MultitouchButton* button)
// ----------------------------------------------------------------------------
bool MultitouchDevice::isGameRunning()
{
return StateManager::get()->getGameState() == GUIEngine::GAME &&
!GUIEngine::ModalDialog::isADialogActive() &&
!GUIEngine::ScreenKeyboard::isActive();
}
// ----------------------------------------------------------------------------
void MultitouchDevice::updateController()
{
if (m_player == NULL)
@@ -427,10 +437,7 @@ void MultitouchDevice::updateController()
// Handle multitouch events only when race is running. It avoids to process
// it when pause dialog is active during the race. And there is no reason
// to use it for GUI navigation.
if (StateManager::get()->getGameState() != GUIEngine::GAME ||
GUIEngine::ModalDialog::isADialogActive() ||
GUIEngine::ScreenKeyboard::isActive() ||
race_manager->isWatchingReplay())
if (!isGameRunning())
{
m_controller = NULL;
return;

View File

@@ -94,6 +94,7 @@ private:
float getSteeringFactor(float value);
void handleControls(MultitouchButton* button);
bool isGameRunning();
public:
/** The array that contains data for all multitouch input events */

View File

@@ -93,6 +93,7 @@
*/
ServerLobby::ServerLobby() : LobbyProtocol(NULL)
{
m_last_success_poll_time.store(StkTime::getRealTimeMs() + 30000);
m_waiting_players_counts.store(0);
m_server_owner_id.store(-1);
m_registered_for_once_only = false;
@@ -110,7 +111,7 @@ ServerLobby::ServerLobby() : LobbyProtocol(NULL)
m_result_ns = getNetworkString();
m_result_ns->setSynchronous(true);
m_waiting_for_reset = false;
m_server_id_online = 0;
m_server_id_online.store(0);
} // ServerLobby
//-----------------------------------------------------------------------------
@@ -356,7 +357,7 @@ void ServerLobby::createServerIdFile()
if (!sid.empty() && !m_has_created_server_id_file)
{
std::fstream fs;
sid += StringUtils::toString(m_server_id_online) + "_" +
sid += StringUtils::toString(m_server_id_online.load()) + "_" +
StringUtils::toString(STKHost::get()->getPrivatePort());
fs.open(sid, std::ios::out);
fs.close();
@@ -384,6 +385,13 @@ void ServerLobby::asynchronousUpdate()
handlePendingConnection();
}
if (allowJoinedPlayersWaiting() && m_server_recovering.expired() &&
StkTime::getRealTimeMs() > m_last_success_poll_time.load() + 30000)
{
Log::warn("ServerLobby", "Trying auto server recovery.");
registerServer(false/*now*/);
}
switch (m_state.load())
{
case SET_PUBLIC_ADDRESS:
@@ -420,7 +428,7 @@ void ServerLobby::asynchronousUpdate()
// Register this server with the STK server. This will block
// this thread, because there is no need for the protocol manager
// to react to any requests before the server is registered.
if (registerServer())
if (registerServer(true/*now*/))
{
if (allowJoinedPlayersWaiting())
m_registered_for_once_only = true;
@@ -690,12 +698,56 @@ void ServerLobby::update(int ticks)
* ProtocolManager thread). The information about this client is added
* to the table 'server'.
*/
bool ServerLobby::registerServer()
bool ServerLobby::registerServer(bool now)
{
while (!m_server_unregistered.expired())
while (now && !m_server_unregistered.expired())
StkTime::sleep(1);
Online::XMLRequest *request = new Online::XMLRequest();
// ========================================================================
class RegisterServerRequest : public Online::XMLRequest
{
private:
std::weak_ptr<ServerLobby> m_server_lobby;
protected:
virtual void afterOperation()
{
Online::XMLRequest::afterOperation();
const XMLNode* result = getXMLData();
std::string rec_success;
auto sl = m_server_lobby.lock();
if (!sl)
return;
if (result->get("success", &rec_success) &&
rec_success == "yes")
{
const XMLNode* server = result->getNode("server");
assert(server);
const XMLNode* server_info = server->getNode("server-info");
assert(server_info);
unsigned server_id_online = 0;
server_info->get("id", &server_id_online);
assert(server_id_online != 0);
Log::info("ServerLobby",
"Server %d is now online.", server_id_online);
sl->m_server_id_online.store(server_id_online);
sl->m_last_success_poll_time.store(StkTime::getRealTimeMs());
return;
}
Log::error("ServerLobby", "%s",
StringUtils::wideToUtf8(getInfo()).c_str());
// For auto server recovery wait 3 seconds for next try
// This sleep only the request manager thread
if (manageMemory())
StkTime::sleep(3000);
}
public:
RegisterServerRequest(bool now, std::shared_ptr<ServerLobby> sl)
: XMLRequest(!now/*manage memory*/), m_server_lobby(sl) {}
}; // RegisterServerRequest
RegisterServerRequest *request = new RegisterServerRequest(now,
std::dynamic_pointer_cast<ServerLobby>(shared_from_this()));
NetworkConfig::get()->setServerDetails(request, "create");
request->addParameter("address", m_server_address.getIP() );
request->addParameter("port", m_server_address.getPort() );
@@ -715,29 +767,19 @@ bool ServerLobby::registerServer()
Log::info("ServerLobby", "Public server address %s",
m_server_address.toString().c_str());
request->executeNow();
const XMLNode* result = request->getXMLData();
std::string rec_success;
if (result->get("success", &rec_success) && rec_success == "yes")
if (now)
{
const XMLNode* server = result->getNode("server");
assert(server);
const XMLNode* server_info = server->getNode("server-info");
assert(server_info);
server_info->get("id", &m_server_id_online);
assert(m_server_id_online != 0);
Log::info("ServerLobby",
"Server %d is now online.", m_server_id_online);
request->executeNow();
delete request;
return true;
if (m_server_id_online.load() == 0)
return false;
}
irr::core::stringc error(request->getInfo().c_str());
Log::error("ServerLobby", "%s", error.c_str());
delete request;
return false;
else
{
request->queue();
m_server_recovering = request->observeExistence();
}
return true;
} // registerServer
//-----------------------------------------------------------------------------
@@ -811,7 +853,7 @@ void ServerLobby::startSelection(const Event *event)
if (!allowJoinedPlayersWaiting())
{
ProtocolManager::lock()->findAndTerminate(PROTOCOL_CONNECTION);
if (NetworkConfig::get()->isWAN() )
if (NetworkConfig::get()->isWAN())
{
unregisterServer(false/*now*/);
}
@@ -903,7 +945,9 @@ void ServerLobby::checkIncomingConnectionRequests()
// First poll every 5 seconds. Return if no polling needs to be done.
const uint64_t POLL_INTERVAL = 5000;
static uint64_t last_poll_time = 0;
if (StkTime::getRealTimeMs() < last_poll_time + POLL_INTERVAL)
if (StkTime::getRealTimeMs() < last_poll_time + POLL_INTERVAL ||
StkTime::getRealTimeMs() > m_last_success_poll_time.load() + 30000 ||
m_server_id_online.load() == 0)
return;
// Keep the port open, it can be sent to anywhere as we will send to the
@@ -927,12 +971,13 @@ void ServerLobby::checkIncomingConnectionRequests()
virtual void afterOperation()
{
Online::XMLRequest::afterOperation();
const XMLNode *result = getXMLData();
const XMLNode* result = getXMLData();
std::string success;
if (!result->get("success", &success) || success != "yes")
{
Log::error("ServerLobby", "Cannot retrieve the list.");
Log::error("ServerLobby", "Poll server request failed: %s",
StringUtils::wideToUtf8(getInfo()).c_str());
return;
}
@@ -942,6 +987,7 @@ void ServerLobby::checkIncomingConnectionRequests()
auto sl = m_server_lobby.lock();
if (!sl)
return;
sl->m_last_success_poll_time.store(StkTime::getRealTimeMs());
if (sl->m_state.load() != WAITING_FOR_START_GAME &&
!sl->allowJoinedPlayersWaiting())
{

View File

@@ -95,6 +95,8 @@ private:
/** It indicates if this server is unregistered with the stk server. */
std::weak_ptr<bool> m_server_unregistered;
std::weak_ptr<bool> m_server_recovering;
/** Timeout counter for various state. */
std::atomic<int64_t> m_timeout;
@@ -148,9 +150,11 @@ private:
std::atomic<uint32_t> m_waiting_players_counts;
std::atomic<uint64_t> m_last_success_poll_time;
uint64_t m_server_started_at, m_server_delay;
unsigned m_server_id_online;
std::atomic<uint32_t> m_server_id_online;
bool m_registered_for_once_only;
@@ -164,7 +168,7 @@ private:
// Track(s) votes
void playerVote(Event *event);
void playerFinishedResult(Event *event);
bool registerServer();
bool registerServer(bool now);
void finishedLoadingWorldClient(Event *event);
void kickHost(Event* event);
void changeTeam(Event* event);

View File

@@ -308,7 +308,6 @@ void STKHost::init()
{
m_network_timer.store(StkTime::getRealTimeMs());
m_shutdown = false;
m_shutdown_delay = 0;
m_authorised = false;
m_network = NULL;
m_exit_timeout.store(std::numeric_limits<uint64_t>::max());

View File

@@ -117,9 +117,6 @@ private:
* triggers a shutdown of the STKHost (and the Protocolmanager). */
std::atomic_bool m_shutdown;
/** Used as a timeout for shedule shutdown. */
std::atomic<uint64_t> m_shutdown_delay;
/** True if this local host is authorised to control a server. */
std::atomic_bool m_authorised;
@@ -211,21 +208,8 @@ public:
void requestShutdown()
{
m_shutdown.store(true);
m_shutdown_delay.store(0);
} // requestExit
//-------------------------------------------------------------------------
void requestShutdownDelayed(int delay)
{
m_shutdown.store(true);
m_shutdown_delay.store(StkTime::getRealTimeMs() + delay);
}
//-------------------------------------------------------------------------
void cancelShutdown()
{
m_shutdown.store(false);
m_shutdown_delay.store(0);
}
//-------------------------------------------------------------------------
void shutdown();
//-------------------------------------------------------------------------
void sendPacketToAllPeersInServer(NetworkString *data,
@@ -282,11 +266,7 @@ public:
// ------------------------------------------------------------------------
/** Returns true if a shutdown of the network infrastructure was
* requested. */
bool requestedShutdown() const
{
return m_shutdown.load() &&
m_shutdown_delay.load() < StkTime::getRealTimeMs();
}
bool requestedShutdown() const { return m_shutdown.load(); }
// ------------------------------------------------------------------------
int receiveRawPacket(char *buffer, int buffer_len,
TransportAddress* sender, int max_tries = -1)

View File

@@ -354,13 +354,6 @@ void PhysicalObject::init(const PhysicalObject::Settings& settings)
case MP_EXACT:
{
extend.setY(0);
// In case of readonly materials we have to get the material from
// the mesh, otherwise from the node. This is esp. important for
// water nodes, which only have the material defined in the node,
// but not in the mesh at all!
bool is_readonly_material = false;
scene::IMesh* mesh = NULL;
switch (presentation->getNode()->getType())
{
@@ -371,7 +364,6 @@ void PhysicalObject::init(const PhysicalObject::Settings& settings)
scene::IMeshSceneNode *node =
(scene::IMeshSceneNode*)presentation->getNode();
mesh = node->getMesh();
is_readonly_material = node->isReadOnlyMaterials();
break;
}
case scene::ESNT_ANIMATED_MESH :
@@ -380,7 +372,6 @@ void PhysicalObject::init(const PhysicalObject::Settings& settings)
scene::IAnimatedMeshSceneNode *node =
(scene::IAnimatedMeshSceneNode*)presentation->getNode();
mesh = node->getMesh()->getMesh(0);
is_readonly_material = node->isReadOnlyMaterials();
break;
}
default:
@@ -436,27 +427,27 @@ void PhysicalObject::init(const PhysicalObject::Settings& settings)
mb->getVertexType());
continue;
}
// Handle readonly materials correctly: mb->getMaterial can return
// NULL if the node is not using readonly materials. E.g. in case
// of a water scene node, the mesh (which is the animated copy of
// the original mesh) does not contain any material information,
// the material is only available in the node.
const video::SMaterial &irrMaterial =
is_readonly_material ? mb->getMaterial()
: presentation->getNode()->getMaterial(i);
video::ITexture* t=irrMaterial.getTexture(0);
const Material* material=0;
if(t)
const video::SMaterial& irrMaterial = mb->getMaterial();
std::string t1_full_path, t2_full_path;
video::ITexture* t1 = irrMaterial.getTexture(0);
if (t1)
{
std::string image =
std::string(core::stringc(t->getName()).c_str());
material = material_manager
->getMaterial(StringUtils::getBasename(image));
if(material->isIgnore())
continue;
t1_full_path = t1->getName().getPtr();
t1_full_path = file_manager->getFileSystem()->getAbsolutePath(
t1_full_path.c_str()).c_str();
}
video::ITexture* t2 = irrMaterial.getTexture(1);
if (t2)
{
t2_full_path = t2->getName().getPtr();
t2_full_path = file_manager->getFileSystem()->getAbsolutePath(
t2_full_path.c_str()).c_str();
}
const Material* material = material_manager->getMaterialSPM(
t1_full_path, t2_full_path);
if (material->isIgnore())
continue;
if (mb->getVertexType() == video::EVT_STANDARD)
{
irr::video::S3DVertex* mbVertices =

View File

@@ -918,26 +918,15 @@ void Track::convertTrackToBullet(scene::ISceneNode *node)
matrices.push_back(node->getAbsoluteTransformation());
scene::IMesh *mesh;
// In case of readonly materials we have to get the material from
// the mesh, otherwise from the node. This is esp. important for
// water nodes, which only have the material defined in the node,
// but not in the mesh at all!
bool is_readonly_material=false;
switch(node->getType())
{
case scene::ESNT_MESH :
case scene::ESNT_WATER_SURFACE :
case scene::ESNT_OCTREE :
mesh = ((scene::IMeshSceneNode*)node)->getMesh();
is_readonly_material =
((scene::IMeshSceneNode*)node)->isReadOnlyMaterials();
break;
case scene::ESNT_ANIMATED_MESH :
mesh = ((scene::IAnimatedMeshSceneNode*)node)->getMesh();
is_readonly_material =
((scene::IAnimatedMeshSceneNode*)node)->isReadOnlyMaterials();
break;
case scene::ESNT_SKY_BOX :
case scene::ESNT_SKY_DOME:
@@ -1021,38 +1010,35 @@ void Track::convertTrackToBullet(scene::ISceneNode *node)
else
#endif
{
// Handle readonly materials correctly: mb->getMaterial can return
// NULL if the node is not using readonly materials. E.g. in case
// of a water scene node, the mesh (which is the animated copy of
// the original mesh) does not contain any material information,
// the material is only available in the node.
const video::SMaterial &irrMaterial =
is_readonly_material ? mb->getMaterial()
: node->getMaterial(i);
video::ITexture* t=irrMaterial.getTexture(0);
const Material* material=0;
TriangleMesh *tmesh = m_track_mesh;
if(t)
const video::SMaterial& irrMaterial = mb->getMaterial();
std::string t1_full_path, t2_full_path;
video::ITexture* t1 = irrMaterial.getTexture(0);
if (t1)
{
std::string image = t->getName().getPtr();
// the third boolean argument is false because at this point we're
// dealing physics, so it's useless to warn about missing textures,
// we'd just get duplicate/useless warnings
material=material_manager->getMaterial(StringUtils::getBasename(image),
false, false, false);
// Special gfx meshes will not be stored as a normal physics body,
// but converted to a collision body only, so that ray tests
// against them can be done.
if(material->isSurface())
tmesh = m_gfx_effect_mesh;
// A material which is a surface must be converted,
// even if it's marked as ignore. So only ignore
// non-surface materials.
else if(material->isIgnore())
continue;
t1_full_path = t1->getName().getPtr();
t1_full_path = file_manager->getFileSystem()->getAbsolutePath(
t1_full_path.c_str()).c_str();
}
video::ITexture* t2 = irrMaterial.getTexture(1);
if (t2)
{
t2_full_path = t2->getName().getPtr();
t2_full_path = file_manager->getFileSystem()->getAbsolutePath(
t2_full_path.c_str()).c_str();
}
const Material* material = material_manager->getMaterialSPM(
t1_full_path, t2_full_path);
TriangleMesh *tmesh = m_track_mesh;
// Special gfx meshes will not be stored as a normal physics body,
// but converted to a collision body only, so that ray tests
// against them can be done.
if (material->isSurface())
tmesh = m_gfx_effect_mesh;
// A material which is a surface must be converted,
// even if it's marked as ignore. So only ignore
// non-surface materials.
else if(material->isIgnore())
continue;
if (mb->getVertexType() == video::EVT_STANDARD)
{