static void OnActivateNetworkClient(void *) { int nDriverIdx = NetGetNetwork()->GetDriverIdx(); if(NetGetNetwork()->IsConnected() && nDriverIdx > -1) { // Menu reactivated after garage menu is done NetDriver driver; char newName[64]; char dname[256]; // check for car change if (bGarage == true ) { bGarage = false; tRmInfo* reInfo = LmRaceEngine().inData(); reInfo->params = GfParmReadFileLocal("config/raceman/networkrace.xml",GFPARM_RMODE_REREAD); reInfo->_reName = GfParmGetStr(reInfo->params, RM_SECT_HEADER, RM_ATTR_NAME, ""); sprintf(dname, "%s/%d", RM_SECT_DRIVERS, nDriverIdx); int idx = GfParmGetNum(reInfo->params, dname, RM_ATTR_IDX, "",0); GfDriver* PCurrentDriver = GfDrivers::self()->getDriver(NETWORKROBOT, idx); strncpy(newName, PCurrentDriver->getCar()->getId().c_str(), sizeof(newName)); GfLogInfo("Client: Index %d changed to %s\n", idx, newName); NetGetNetwork()->SetCarInfo(newName); } else { // Ensure menu system knows about all cars GfDrivers::self()->reload(); // tRmInfo* reInfo = LmRaceEngine().inData(); // Never used LmRaceEngine().race()->load(LmRaceEngine().race()->getManager(), true); } } GfuiApp().eventLoop().setRecomputeCB(ClientIdle); bGarage = false; }
void GfDrivers::reload() { // Clear all. clear(); // (Re)Load robot modules from the "drivers" installed folder. std::string strDriversDirName(GfLibDir()); strDriversDirName += "drivers"; tModList* lstDriverModules = 0; const int nDriverModules = GfModInfoDir(CAR_IDENT, strDriversDirName.c_str(), 1, &lstDriverModules); if (nDriverModules <= 0 || !lstDriverModules) { GfLogFatal("Could not load any driver module from %s", strDriversDirName.c_str()); return; } // For each module found, load drivers information. tModList *pCurModule = lstDriverModules; do { pCurModule = pCurModule->next; // Determine the module name. std::string strModName(pCurModule->sopath); strModName.erase(strlen(pCurModule->sopath) - strlen(DLLEXT) - 1); // Truncate file ext. const size_t nLastSlashInd = strModName.rfind('/'); if (nLastSlashInd != std::string::npos) strModName = strModName.substr(nLastSlashInd+1); // Remove heading folder path. // Load the module XML descriptor file (try user settings first, and then installed one) std::ostringstream ossRobotFileName; ossRobotFileName << GfLocalDir() << "drivers/" << strModName << '/' << strModName << PARAMEXT; void *hparmRobot = GfParmReadFile(ossRobotFileName.str().c_str(), GFPARM_RMODE_STD | GFPARM_RMODE_REREAD); if (!hparmRobot) { ossRobotFileName.str(""); ossRobotFileName << "drivers/" << strModName << '/' << strModName << PARAMEXT; hparmRobot = GfParmReadFile(ossRobotFileName.str().c_str(), GFPARM_RMODE_STD | GFPARM_RMODE_REREAD); } if (!hparmRobot) { // Do not waste log with drivers that do not exists or do not have to exist! if (strncmp("dandroid",strModName.c_str(),8) == 0) continue; else if (strncmp("usr",strModName.c_str(),3) == 0) continue; else if (strncmp("replay",strModName.c_str(),6) == 0) continue; GfLogError("No usable '%s' driver (%s.xml not found or not readable)\n", strModName.c_str(), strModName.c_str()); continue; } // For each driver (= interface) "in" the module for (int nItfInd = 0; nItfInd < pCurModule->modInfoSize; nItfInd++) { // Ignore undefined drivers or showing an empty name if (!pCurModule->modInfo[nItfInd].name || pCurModule->modInfo[nItfInd].name[0] == '\0') { GfLogInfo("Ignoring '%s' driver #%d (not defined or empty name)\n", strModName.c_str(), nItfInd); continue; } // Create the driver and load info from the XML file. GfDriver* pDriver = new GfDriver(strModName, pCurModule->modInfo[nItfInd].index, pCurModule->modInfo[nItfInd].name, hparmRobot); // For human drivers, if the car was not found, select the 1st possible one. if (!pDriver->getCar() && pDriver->isHuman()) { GfCar* pSubstCar = GfCars::self()->getCarsInCategory()[0]; // Should never fail. if (pSubstCar) { std::ostringstream ossDrvSecPath; ossDrvSecPath << ROB_SECT_ROBOTS << '/' << ROB_LIST_INDEX << '/' << pCurModule->modInfo[nItfInd].index; const char* pszCarId = GfParmGetStr(hparmRobot, ossDrvSecPath.str().c_str(), ROB_ATTR_CAR, ""); GfLogWarning("Changing '%s' driver '%s' (#%d) 's car to %s (default one '%s' not available)\n", strModName.c_str(), pCurModule->modInfo[nItfInd].name, pCurModule->modInfo[nItfInd].index, pSubstCar->getId().c_str(), pszCarId); pDriver->setCar(pSubstCar); } } // Keep the driver only if he drives an existing car. if (pDriver->getCar()) { // Update the GfDrivers singleton. _pPrivate->vecDrivers.push_back(pDriver); const std::pair<std::string, int> driverKey(pDriver->getModuleName(), pDriver->getInterfaceIndex()); _pPrivate->mapDriversByKey[driverKey] = pDriver; if (std::find(_pPrivate->vecTypes.begin(), _pPrivate->vecTypes.end(), pDriver->getType()) == _pPrivate->vecTypes.end()) _pPrivate->vecTypes.push_back(pDriver->getType()); if (std::find(_pPrivate->vecCarCategoryIds.begin(), _pPrivate->vecCarCategoryIds.end(), pDriver->getCar()->getCategoryId()) == _pPrivate->vecCarCategoryIds.end()) _pPrivate->vecCarCategoryIds.push_back(pDriver->getCar()->getCategoryId()); } else { delete pDriver; std::ostringstream ossDrvSecPath; ossDrvSecPath << ROB_SECT_ROBOTS << '/' << ROB_LIST_INDEX << '/' << pCurModule->modInfo[nItfInd].index; const char* pszCarId = GfParmGetStr(hparmRobot, ossDrvSecPath.str().c_str(), ROB_ATTR_CAR, ""); GfLogInfo("Ignoring '%s' driver '%s' (#%d) (not defined or default car '%s' not available)\n", strModName.c_str(), pCurModule->modInfo[nItfInd].name, pCurModule->modInfo[nItfInd].index, pszCarId); } } // Close driver module descriptor file if open GfParmReleaseHandle(hparmRobot); } while (pCurModule != lstDriverModules); // Free the module list. GfModFreeInfoList(&lstDriverModules); // Sort the car category ids and driver types vectors. std::sort(_pPrivate->vecCarCategoryIds.begin(), _pPrivate->vecCarCategoryIds.end()); std::sort(_pPrivate->vecTypes.begin(), _pPrivate->vecTypes.end()); // Trace what we got. print(); }
static void UpdateNetworkPlayers() { GfDriver* newDriver; NetNetwork *pNetwork = NetGetNetwork(); if (pNetwork->GetRefreshDisplay() == false) return; tRmInfo* reInfo = LmRaceEngine().inData(); //Set current driver that camera will look at pNetwork->SetCurrentDriver(); //reload xml file NetGetNetwork()->SetRaceXMLFile("config/raceman/networkrace.xml"); reInfo->params = GfParmReadFileLocal("config/raceman/networkrace.xml",GFPARM_RMODE_REREAD); assert(reInfo->params); reInfo->_reName = GfParmGetStr(reInfo->params, RM_SECT_HEADER, RM_ATTR_NAME, ""); assert(reInfo->_reName); // Scan each of the human drivers to see if they're active in this race if (NetIsServer()) { NetServerMutexData *pSData = NetGetServer()->LockServerData(); assert(pSData); // Ensure that garage menu knows about driver for (unsigned int i=0; i < pSData->m_vecNetworkPlayers.size(); i++) { newDriver = GfDrivers::self()->getDriver(NETWORKROBOT, pSData->m_vecNetworkPlayers[i].idx); if (!newDriver) { GfLogInfo("Driver %s not found, reloading drivers\n", pSData->m_vecNetworkPlayers[i].name); GfDrivers::self()->reload(); LmRaceEngine().race()->load(LmRaceEngine().race()->getManager(), true); break; } } for (unsigned int i=0; i < pSData->m_vecNetworkPlayers.size(); i++) { int k = 1; char path2[256]; pSData->m_vecNetworkPlayers[i].active = false; newDriver = GfDrivers::self()->getDriver(NETWORKROBOT, pSData->m_vecNetworkPlayers[i].idx); // Scan through drivers listed in 'networkrace.xml' while (pSData->m_vecNetworkPlayers[i].active == false) { sprintf(path2, "%s/%d", RM_SECT_DRIVERS, k++); if (GfParmExistsSection(reInfo->params, path2) == 0) { GfLogInfo("UpdateNetworkPlayers: Removing driver %s\n", pSData->m_vecNetworkPlayers[i].name); if (pSData->m_vecNetworkPlayers[i].client) { //need to tell/force client to disconnect } break; } if ((tdble)pSData->m_vecNetworkPlayers[i].idx == GfParmGetNum(reInfo->params, path2, RM_ATTR_IDX, NULL, 1.0) && strcmp(NETWORKROBOT, GfParmGetStr(reInfo->params, path2, RM_ATTR_MODULE, "")) == 0) { pSData->m_vecNetworkPlayers[i].active = true; } } // add or remove from competitor list (for garage menu) GfDriver* activeDriver = LmRaceEngine().race()->getCompetitor(NETWORKROBOT, pSData->m_vecNetworkPlayers[i].idx); if (pSData->m_vecNetworkPlayers[i].active) { if (!activeDriver) LmRaceEngine().race()->appendCompetitor(newDriver); } else { if (activeDriver) LmRaceEngine().race()->removeCompetitor(newDriver); } } NetGetServer()->UnlockServerData(); } else { #if 1 // Client XML files already written to disk - this works but is not the best solution.... GfDrivers::self()->reload(); LmRaceEngine().race()->load(LmRaceEngine().race()->getManager(), true); #endif } //Update track info std::string strTrackPath = GfParmGetStr(reInfo->params, "Tracks/1", RM_ATTR_NAME, ""); std::string strCategory = GfParmGetStr(reInfo->params, "Tracks/1", RM_ATTR_CATEGORY, ""); std::string strTrackName = GetTrackName(strCategory.c_str(),strTrackPath.c_str()); sprintf(buf, "%s", strTrackName.c_str()); GfuiLabelSetText(racemanMenuHdle,g_trackHd,buf); //Store current track - client needs this GfTrack* PCurTrack = GfTracks::self()->getTrackWithName(buf); LmRaceEngine().race()->getManager()->setEventTrack(0, PCurTrack); int laps = (int)GfParmGetNum(reInfo->params, reInfo->_reName,"laps", "", 1); sprintf(buf, "%i", laps); GfuiLabelSetText(racemanMenuHdle,g_lapsHd,buf); GfuiScreenAddBgImg(racemanMenuHdle, GetTrackPreviewFileName(strCategory.c_str(),strTrackPath.c_str()).c_str()); GfuiStaticImageSet(racemanMenuHdle, g_OutlineId, GetTrackOutlineFileName(strCategory.c_str(),strTrackPath.c_str()).c_str()); // Update category info std::string strCarCat; bool bCollisions; NetGetNetwork()->GetHostSettings(strCarCat,bCollisions); GfuiLabelSetText(racemanMenuHdle,g_catHd,strCarCat.c_str()); //fill in player data int nCars = GfParmGetEltNb(reInfo->params, RM_SECT_DRIVERS); char dname[256]; char robpath[256]; float *pColor = &green[0]; bool bEveryoneReadyToRace = true; for (int i = 1; i < nCars+1; i++) { sprintf(dname, "%s/%d", RM_SECT_DRIVERS, i); const char* robot = GfParmGetStr(reInfo->params, dname, RM_ATTR_MODULE, ""); //lookup playerName and car name sprintf(robpath,"drivers/%s/%s.xml",robot,robot); void *pMod = GfParmReadFileLocal(robpath,GFPARM_RMODE_REREAD); if (pMod == NULL) { //try again in other path sprintf(robpath,"drivers/%s/%s.xml",robot,robot); pMod = GfParmReadFile(robpath,GFPARM_RMODE_REREAD); if (pMod == NULL) continue; } assert(pMod); char ppname[256]; int idx = GfParmGetNum(reInfo->params, dname, RM_ATTR_IDX, "",0); sprintf(ppname,"Robots/index/%d",idx); const char* name = GfParmGetStr(pMod, ppname, RM_ATTR_NAME, ""); const char* car = GfParmGetStr(pMod, ppname, "car name", ""); std::string strRealCar = GfCars::self()->getCar(car)->getName(); // WAIT : pNData->m_vecReadyStatus[i-1] ?! // This can only work when _only_ networkhuman drivers in the race // (that is _no_robot_driver_) ; because m_vecReadyStatus is indexed // by the networkhuman drivers list. // TO fix this, 2 solutions: // 1) make the networking module take care of the robot drivers too // (in m_vecReadyStatus, m_vecNetworkPlayers, ...) // 2) make the networking _menu_ only take care of the networkhuman drivers. bool bReady = bRobotsReady; if(strcmp(NETWORKROBOT, GfParmGetStr(reInfo->params, dname, RM_ATTR_MODULE, "")) == 0) { // Write car model, as it may have changed via garage menu if (NetIsServer()) { NetServerMutexData *pSData = NetGetServer()->LockServerData(); strncpy(pSData->m_vecNetworkPlayers[idx-1].car, car, 64); GfLogInfo("idx %d car set to %s\n", idx, car); // also need to write back for garage menu const GfCar* newCar = GfCars::self()->getCar(car); newDriver = GfDrivers::self()->getDriver(NETWORKROBOT, pSData->m_vecNetworkPlayers[idx-1].idx); newDriver->setCar(newCar); NetGetServer()->UnlockServerData(); } //GfLogInfo("idx %d, m_vecReadyStatus.size() %d\n", idx, pNData->m_vecReadyStatus.size()); NetMutexData *pNData = NetGetNetwork()->LockNetworkData(); bReady = pNData->m_vecReadyStatus[idx-1]; NetGetNetwork()->UnlockNetworkData(); } int readyindex = 0; if (bReady) readyindex = 1; else bEveryoneReadyToRace = false; if (strcmp(NetGetNetwork()->GetDriverName(),name)==0) { pColor = &green[0]; g_strCar = strRealCar; //Make sure checkbox matches ready state GfuiCheckboxSetChecked(racemanMenuHdle, g_ReadyCheckboxId, bReady); if (NetGetClient()) EnableMenuClientButtons(bReady); else EnableMenuHostButtons(bReady); } else pColor = &white[0]; GfuiVisibilitySet(racemanMenuHdle,g_readystatus[i-1],true); GfuiStaticImageSetActive(racemanMenuHdle,g_readystatus[i-1],readyindex); GfuiLabelSetColor(racemanMenuHdle, g_playerNames[i-1], pColor); GfuiLabelSetText(racemanMenuHdle,g_playerNames[i-1],name); GfuiLabelSetColor(racemanMenuHdle, g_carNames[i-1], pColor); GfuiLabelSetText(racemanMenuHdle,g_carNames[i-1],strRealCar.c_str()); GfParmReleaseHandle(pMod); } //Clear out rest of table for (int i=nCars;i<MAXNETWORKPLAYERS;i++) { GfuiVisibilitySet(racemanMenuHdle,g_readystatus[i],false); GfuiLabelSetText(racemanMenuHdle,g_playerNames[i],""); GfuiLabelSetText(racemanMenuHdle,g_carNames[i],""); } pNetwork->SetRefreshDisplay(false); GfuiApp().eventLoop().postRedisplay(); if (NetIsClient()) { NetGetClient()->ConnectToClients(); if (!NetGetClient()->TimeSynced()) { NetGetClient()->SendServerTimeRequest(); } } if (NetIsServer()) { if (bEveryoneReadyToRace && nCars > 1) ServerPrepareStartNetworkRace(NULL); } }