void ReRaceAbort() { ReShutdownUpdaters(); RePhysicsEngine().shutdown(); RaceEngine::self().unloadPhysicsEngine(); ReUI().onRaceFinishing(); ReRaceCleanDrivers(); if (NetGetNetwork()) NetGetNetwork()->Disconnect(); FREEZ(ReInfo->_reCarInfo); if (ReInfo->params != ReInfo->mainParams) { GfParmReleaseHandle(ReInfo->params); ReInfo->params = ReInfo->mainParams; } // Return to race configuration step ReStateApply((void*)RE_STATE_CONFIG); }
int ReRaceEnd(void) { int curDrvIdx; int nCars; void *params = ReInfo->params; void *results = ReInfo->results; const char *sessionName = ReInfo->_reRaceName; ReShutdownUpdaters(); ReUI().onRaceFinishing(); ReRaceCleanup(); if (NetGetNetwork()) NetGetNetwork()->RaceDone(); // If we are at the end of a qualification or practice session for a competitor, // select the next competitor : it is his turn for the same session. // If no more competitor, this is the end of the session for all the competitors. bool bEndOfSession = true; if ((ReInfo->s->_raceType == RM_TYPE_QUALIF || ReInfo->s->_raceType == RM_TYPE_PRACTICE) && ReInfo->s->_totTime < 0.0f) { // Up to the next competitor now, if not the last one. nCars = MIN(GfParmGetEltNb(params, RM_SECT_DRIVERS), (int)GfParmGetNum(params, sessionName, RM_ATTR_MAX_DRV, NULL, 100)); ReCurrDriverNr++; if (ReStartingOrderIdx != NULL) { if (ReCurrDriverNr < nCars) {curDrvIdx = ReStartingOrderIdx[ReCurrDriverNr];} else {curDrvIdx = nCars + 1;} } else { curDrvIdx = 1; } if (ReCurrDriverNr < nCars) bEndOfSession = false; else { ReCurrDriverNr = 0; // Was the last one : end of session ! curDrvIdx = 1; } GfParmSetNum(results, RE_SECT_CURRENT, RE_ATTR_CUR_DRIVER, NULL, (tdble)curDrvIdx); } // Calculate class points if we just finished a session. if (bEndOfSession) { ReCalculateClassPoints (ReInfo->_reRaceName); if (ReStartingOrderIdx != NULL) { delete[] ReStartingOrderIdx; ReStartingOrderIdx = NULL; } } // Determine the new race state automation mode. const bool bGoOn = ReUI().onRaceFinished(bEndOfSession); return (bEndOfSession ? RM_NEXT_STEP : RM_NEXT_RACE) | (bGoOn ? RM_SYNC : RM_ASYNC); }
void ReNetworkCheckEndOfRace() { // Check for end of online race. if (NetGetNetwork() && NetGetNetwork()->FinishRace(ReInfo->s->currentTime)) ReInfo->s->_raceState = RM_RACE_ENDED; }
static void onClientPlayerReady(tCheckBoxInfo* pInfo) { int nDriverIdx = NetGetNetwork()->GetDriverIdx(); // Local Human Driver if (nDriverIdx > -1) { SetReadyStatus(nDriverIdx-1, pInfo->bChecked); NetGetNetwork()->SetDriverReady(pInfo->bChecked); } EnableMenuClientButtons(pInfo->bChecked); }
static void rmCarSettingsMenu(void *pMenu) { int nDriverIdx = NetGetNetwork()->GetDriverIdx(); if (nDriverIdx > -1) { NetDriver driver; // char newName[64]; Never used char dname[256]; // check for car change GfLogInfo("Car %d changed \n", nDriverIdx); 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); // Garage menu to change clients car GfDriver* PCurrentDriver = GfDrivers::self()->getDriver(NETWORKROBOT, idx); GarageMenu.setPreviousMenuHandle(racemanMenuHdle); GarageMenu.runMenu(LmRaceEngine().race(), PCurrentDriver); bGarage = true; } }
void RmNetworkMenu(void *) { GfLogTrace("Entering Network menu.\n"); tRmInfo* reInfo = LmRaceEngine().inData(); void *params = reInfo->params; if (NetGetNetwork()) { NetGetNetwork()->ResetNetwork(); } racemanMenuHdle = GfuiScreenCreate(NULL, NULL, (tfuiCallback)NULL, NULL, (tfuiCallback)NULL, 1); void *mparam = GfuiMenuLoad("networkmenu.xml"); GfuiMenuCreateStaticControls(racemanMenuHdle, mparam); const int nTitleLabelId = GfuiMenuCreateLabelControl(racemanMenuHdle, mparam, "TitleLabel"); const char* pszTitle = GfParmGetStr(params, RM_SECT_HEADER, RM_ATTR_NAME, 0); if (pszTitle) GfuiLabelSetText(racemanMenuHdle, nTitleLabelId, pszTitle); GfuiMenuCreateButtonControl(racemanMenuHdle, mparam, "HostButton", 0, RmNetworkHostMenu); GfuiMenuCreateButtonControl(racemanMenuHdle, mparam, "JoinButton", 0, NetworkClientConnectMenu); GfuiMenuCreateButtonControl(racemanMenuHdle, mparam, "BackButton", RmRaceSelectMenuHandle, GfuiScreenActivate); GfuiMenuDefaultKeysAdd(racemanMenuHdle); GfuiAddKey(racemanMenuHdle, GFUIK_ESCAPE, "Back to previous menu", RmRaceSelectMenuHandle, 0, GfuiScreenActivate); GfParmReleaseHandle(mparam); GfuiScreenActivate(racemanMenuHdle); }
static void reNetworkSetLapStatus(LapStatus *pStatus) { int idx = NetGetNetwork()->GetCarIndex(pStatus->startRank,ReInfo->s); tCarElt *pCar = ReInfo->s->cars[idx]; pCar->race.bestLapTime = pStatus->bestLapTime; *pCar->race.bestSplitTime = (double)pStatus->bestSplitTime; pCar->race.laps = pStatus->laps; GfLogTrace("Setting network lap status\n"); }
static void OnActivateNetworkHost(void *) { tRmInfo* reInfo = LmRaceEngine().inData(); // Set everyone to the 'not-ready' state bRobotsReady = 0; NetMutexData *pNData = NetGetNetwork()->LockNetworkData(); for (unsigned int i=0;i<pNData->m_vecReadyStatus.size();i++) pNData->m_vecReadyStatus[i] = false; NetGetNetwork()->UnlockNetworkData(); NetGetServer()->SetRaceInfoChanged(true); reInfo->params = GfParmReadFileLocal("config/raceman/networkrace.xml",GFPARM_RMODE_REREAD); assert(reInfo->params); reInfo->_reName = GfParmGetStr(reInfo->params, RM_SECT_HEADER, RM_ATTR_NAME, ""); GfuiApp().eventLoop().setRecomputeCB(HostServerIdle); NetGetServer()->SetRefreshDisplay(true); }
// This member function decorates the situation updater as a normal function, // thus hiding the possible separate thread behind to the main updater. void ReSituationUpdater::computeCurrentStep() { // Nothing to do if actually threaded : // the updater thread is already doing the job on his side. if (_bThreaded) return; // Non-threaded mode. GfProfStartProfile("reOneStep*"); tRmInfo* pCurrReInfo = ReSituation::self().data(); // Stable but slowed-down frame rate mode. if (_fOutputTick > 0) { while ((pCurrReInfo->_reCurTime - _fLastOutputTime) < _fOutputTick) runOneStep(_fSimuTick); _fLastOutputTime = pCurrReInfo->_reCurTime; } // Real-time but variable frame rate mode. else { const double t = GfTimeClock(); while (pCurrReInfo->_reRunning && ((t - pCurrReInfo->_reCurTime) > RCM_MAX_DT_SIMU)) runOneStep(_fSimuTick); } GfProfStopProfile("reOneStep*"); // Send car physics to network if needed if (NetGetNetwork()) NetGetNetwork()->SendCarControlsPacket(pCurrReInfo->s); }
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; }
static void reNetworkSetCarPhysics(double timeDelta,CarControlsData *pCt) { tDynPt *pDynCG = RePhysicsEngine().getCar(pCt->startRank); // double errX = pDynCG->pos.x-pCt->DynGCg.pos.x; // double errY = pDynCG->pos.y-pCt->DynGCg.pos.y; // double errZ = pDynCG->pos.z-pCt->DynGCg.pos.z; int idx = NetGetNetwork()->GetCarIndex(pCt->startRank,ReInfo->s); //Car controls (steering,gas,brake, gear tCarElt *pCar = ReInfo->s->cars[idx]; pCar->ctrl.accelCmd = pCt->throttle; pCar->ctrl.brakeCmd = pCt->brake; pCar->ctrl.clutchCmd = pCt->clutch; pCar->ctrl.gear = pCt->gear; pCar->ctrl.steer = pCt->steering; pDynCG->pos = pCt->DynGCg.pos; pDynCG->acc = pCt->DynGCg.acc; pDynCG->vel = pCt->DynGCg.vel; double step = 0.0; if (timeDelta>0.0) { //predict car position while(timeDelta>0.0) { if (timeDelta>RCM_MAX_DT_SIMU) { step = RCM_MAX_DT_SIMU; } else step = timeDelta; timeDelta-=step; RePhysicsEngine().updateCar(ReInfo->s, step, pCt->startRank); } } //GfLogTrace("Network position error is %lf %lf %lf and delta is %lf\n",errX,errY,errZ,timeDelta); //Car physics // RePhysicsEngine().setCar(pCt->DynGCg, pCt->startRank); }
bool CarSettingsMenu::initialize(void* pMenu,const char *pszCar) { std::string strCarCat; bool bCollisions; NetGetNetwork()->GetHostSettings(strCarCat,bCollisions); pPrevMenu = pMenu; void* pMenuHandle = GfuiScreenCreate(NULL,NULL,onActivate, NULL, (tfuiCallback)NULL, 1); setMenuHandle(pMenuHandle); openXMLDescriptor(); createStaticControls(); int carCatId = createComboboxControl("modelcombo",NULL,onCarPick); createComboboxControl("skincombo",NULL,NULL); createStaticImageControl("carpreviewimage"); createProgressbarControl("topspeedprogress"); createProgressbarControl("accelerationprogress"); createProgressbarControl("handlingprogress"); createProgressbarControl("brakingprogress"); const std::vector<std::string> vecCarRealNames = GfCars::self()->getCarNamesInCategory(strCarCat); m_strCar = pszCar; int carIndex = 0; for (unsigned i=0;i<vecCarRealNames.size();i++) { GfuiComboboxAddText(pMenuHandle,carCatId,vecCarRealNames[i].c_str()); if (vecCarRealNames[i] == m_strCar) carIndex = i; } GfuiComboboxSetSelectedIndex(pMenuHandle,carCatId,carIndex); createButtonControl("accept",NULL,onAccept); createButtonControl("cancel",NULL,onCancel); closeXMLDescriptor(); return true; }
static void reNetworkSetCarStatus(CarStatus *pStatus) { int idx = NetGetNetwork()->GetCarIndex(pStatus->startRank,ReInfo->s); tCarElt *pCar = ReInfo->s->cars[idx]; if (pStatus->dammage > 0.0) pCar->priv.dammage = pStatus->dammage; if (pStatus->fuel >0.0) pCar->priv.fuel = pStatus->fuel; if (pStatus->topSpeed >0.0) pCar->race.topSpeed = pStatus->topSpeed; pCar->pub.state = pStatus->state; }
int ReNetworkWaitReady() { // No wait if not an online race. if (!NetGetNetwork()) return RM_SYNC | RM_NEXT_STEP; // If network race, wait for other players and start when the server tells to bool bWaitFinished = false; if (NetGetClient()) { NetGetClient()->SendReadyToStartPacket(); ReInfo->s->currentTime = NetGetClient()->WaitForRaceStart(); GfLogInfo("Client beginning race in %lf seconds!\n", - ReInfo->s->currentTime); bWaitFinished = true; } else if (NetGetServer()) { if (NetGetServer()->ClientsReadyToRace()) { ReInfo->s->currentTime = NetGetServer()->WaitForRaceStart(); GfLogInfo("Server beginning race in %lf seconds!\n", - ReInfo->s->currentTime); bWaitFinished = true; } } if (bWaitFinished) { ReSituation::self().setRaceMessage("", -1/*always*/, /*big=*/true); return RM_SYNC | RM_NEXT_STEP; } else { ReSituation::self().setRaceMessage("Waiting for online players", -1/*always*/, /*big=*/true); return RM_ASYNC; } }
static void CheckDriversCategory() { bool bDriversChange = false; std::string strCarCat; bool bCollisions; NetGetNetwork()->GetHostSettings(strCarCat,bCollisions); if (strCarCat =="All") return; const std::vector<std::string> vecCars = GfCars::self()->getCarIdsInCategory(strCarCat); //Make sure all cars are in the correct category or force change of car unsigned int count = 0; NetServerMutexData *pSData = NetGetServer()->LockServerData(); count = pSData->m_vecNetworkPlayers.size(); for (unsigned int i=0;i<count;i++) { const GfCar* pCar = GfCars::self()->getCar(pSData->m_vecNetworkPlayers[i].car); if (pCar->getCategoryId() != strCarCat) { //Pick first car in categroy //strncpy(pSData->m_vecNetworkPlayers[i].car,vecCars[0].c_str(),64); bDriversChange = true; NetGetServer()->OverrideDriverReady(pSData->m_vecNetworkPlayers[i].idx,false); } } if(bDriversChange) { NetGetServer()->CreateNetworkRobotFile(); } //NetGetServer()->UnlockDrivers(); NetGetServer()->UnlockServerData(); }
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); } }
void ReNetworkOneStep() { tSituation *s = ReInfo->s; //Do network updates if needed //CarControlsData *pControls = NULL; int numCars = 0; NetMutexData *pNData = NetGetNetwork()->LockNetworkData(); numCars = pNData->m_vecCarCtrls.size(); if (numCars>0) { for (int i=0;i<numCars;i++) { double timeDelta = s->currentTime-pNData->m_vecCarCtrls[i].time; if (timeDelta >= 0) { reNetworkSetCarPhysics(timeDelta,&pNData->m_vecCarCtrls[i]); } else if (timeDelta <= -1.0) { GfLogTrace("Ignoring physics packet (delta is %lf)\n", timeDelta); } } } NetGetNetwork()->SetCurrentTime(s->currentTime); pNData->m_vecCarCtrls.clear(); //do car status updates if needed numCars = pNData->m_vecCarStatus.size(); if (numCars>0) { for (int i=0;i<numCars;i++) { double delta = s->currentTime-pNData->m_vecCarStatus[i].time; if (delta>=0) reNetworkSetCarStatus(&pNData->m_vecCarStatus[i]); } } std::vector<CarControlsData>::iterator p = pNData->m_vecCarCtrls.begin(); while(p!=pNData->m_vecCarCtrls.end()) { if(p->time<s->currentTime) p = pNData->m_vecCarCtrls.erase(p); else p++; } //do lap status updates if needed numCars = 0; numCars = pNData->m_vecLapStatus.size(); if (numCars>0) { for (int i=0;i<numCars;i++) { reNetworkSetLapStatus(&pNData->m_vecLapStatus[i]); } } pNData->m_vecLapStatus.clear(); NetGetNetwork()->UnlockNetworkData(); }
/* return state mode */ int ReRaceRealStart(void) { int i, j; tRobotItf *robot; tReCarInfo *carInfo; char buf[128]; int foundHuman; void *params = ReInfo->params; tSituation *s = ReInfo->s; tMemoryPool oldPool = NULL; void* carHdle; // Load the physics engine if (!RaceEngine::self().loadPhysicsEngine()) return RM_ERROR; // Get the session display mode (default to "All sessions" ones, or else "normal"). std::string strDispMode = GfParmGetStr(params, ReInfo->_reRaceName, RM_ATTR_DISPMODE, ""); if (strDispMode.empty()) strDispMode = GfParmGetStr(params, RM_VAL_ANYRACE, RM_ATTR_DISPMODE, RM_VAL_VISIBLE); if (strDispMode == RM_VAL_INVISIBLE) ReInfo->_displayMode = RM_DISP_MODE_NONE; else if (strDispMode == RM_VAL_VISIBLE) ReInfo->_displayMode = RM_DISP_MODE_NORMAL; else if (strDispMode == RM_VAL_SIMUSIMU) ReInfo->_displayMode = RM_DISP_MODE_SIMU_SIMU; else { GfLogError("Unsupported display mode '%s' loaded from race file ; " "assuming 'normal'\n", strDispMode.c_str()); ReInfo->_displayMode = RM_DISP_MODE_NORMAL; } //GfLogDebug("ReRaceRealStart: Loaded dispMode=0x%x\n", ReInfo->_displayMode); // Check if there is a human in the driver list foundHuman = ReHumanInGroup() ? 2 : 0; // Reset SimuSimu bit if any human in the race. // Note: Done here in order to make SimuSimu faster. if ((ReInfo->_displayMode & RM_DISP_MODE_SIMU_SIMU) && foundHuman) { ReInfo->_displayMode &= ~RM_DISP_MODE_SIMU_SIMU; } // Initialize & place cars // Note: if SimuSimu display mode, robot->rbNewTrack isn't called. This is a lot faster. if (ReInitCars()) return RM_ERROR; // Check if there is a human in the current race // Warning: Don't move this before ReInitCars (initializes s->cars). for (i = 0; i < s->_ncars; i++) { if (s->cars[i]->_driverType == RM_DRV_HUMAN) { foundHuman = 1; break; }//if human }//for i // Force "normal" display mode if any human in the session if (foundHuman == 1) { ReInfo->_displayMode = RM_DISP_MODE_NORMAL; } // Force "result only" mode in Practice / Qualif. sessions without any human, // but at least 1 in another session (why this ?), and SimuSimu bit on. else if (foundHuman == 2 && (ReInfo->_displayMode & RM_DISP_MODE_SIMU_SIMU) && (ReInfo->s->_raceType == RM_TYPE_QUALIF || ReInfo->s->_raceType == RM_TYPE_PRACTICE)) { ReInfo->_displayMode = RM_DISP_MODE_NONE; } GfLogInfo("Display mode : %s\n", (ReInfo->_displayMode & RM_DISP_MODE_SIMU_SIMU) ? "SimuSimu" : ((ReInfo->_displayMode & RM_DISP_MODE_NORMAL) ? "Normal" : "Results-only")); // Notify the UI that it's "race loading time". ReUI().onRaceLoadingDrivers(); // Load drivers for the race for (i = 0; i < s->_ncars; i++) { snprintf(buf, sizeof(buf), "cars/%s/%s.xml", s->cars[i]->_carName, s->cars[i]->_carName); carHdle = GfParmReadFile(buf, GFPARM_RMODE_STD); snprintf(buf, sizeof(buf), "Loading %s driver (%s) ...", s->cars[i]->_name, GfParmGetName(carHdle)); ReUI().addLoadingMessage(buf); if (!(ReInfo->_displayMode & RM_DISP_MODE_SIMU_SIMU)) { //Tell robots they are to start a new race robot = s->cars[i]->robot; GfPoolMove( &s->cars[i]->_newRaceMemPool, &oldPool ); robot->rbNewRace(robot->index, s->cars[i], s); GfPoolFreePool( &oldPool ); }//if ! simusimu }//for i RtTeamManagerStart(); // Notify the UI that the drivers have been loaded now. ReUI().onRaceDriversLoaded(); // Initialize the physics engine RePhysicsEngine().updateSituation(s, RCM_MAX_DT_SIMU); carInfo = ReInfo->_reCarInfo; for (i = 0; i < s->_ncars; i++) { carInfo[i].prevTrkPos = s->cars[i]->_trkPos; } // All cars start with max brakes on ReUI().addLoadingMessage("Running Prestart ..."); for (i = 0; i < s->_ncars; i++) { memset(&(s->cars[i]->ctrl), 0, sizeof(tCarCtrl)); s->cars[i]->ctrl.brakeCmd = 1.0; } for (j = 0; j < (int)(1.0 / RCM_MAX_DT_SIMU); j++) RePhysicsEngine().updateSituation(s, RCM_MAX_DT_SIMU); // Initialize current result manager. ReInitCurRes(); // More initializations. ReInfo->_reTimeMult = 1.0; ReInfo->_reLastRobTime = -1.0; if (NetGetNetwork()) ReInfo->s->currentTime = GfTimeClock() - NetGetNetwork()->GetRaceStartTime(); else ReInfo->s->currentTime = -2.0; // We start 2 seconds before the real race start ReInfo->s->deltaTime = RCM_MAX_DT_SIMU; ReInfo->s->_raceState = RM_RACE_STARTING; ReInfo->_rePitRequester = 0; ReInfo->_reMessage = 0; ReInfo->_reMessageEnd = 0.0; ReInfo->_reBigMessage = 0; ReInfo->_reBigMessageEnd = 0.0; ReInitUpdaters(); // Notify the UI that the race simulation is ready now. ReUI().onRaceSimulationReady(); // Initialize the network if needed. if (NetGetNetwork()) { ReUI().addLoadingMessage("Preparing online race ..."); NetGetNetwork()->RaceInit(ReOutputSituation()->s); NetGetNetwork()->SetRaceActive(true); } // Notify the UI that the race is now started. ReUI().addLoadingMessage("Ready."); ReUI().onRaceStarted(); // And go on looping the race state automaton. return RM_SYNC | RM_NEXT_STEP; }//ReRaceRealStart
static void NetworkRaceInfo() { NetDriver driver; int i = 1; NetGetServer()->SetRaceXMLFile("config/raceman/networkrace.xml"); //Look up race info tRmInfo* reInfo = LmRaceEngine().inData(); reInfo->params = GfParmReadFileLocal("config/raceman/networkrace.xml",GFPARM_RMODE_STD); int nCars = GfParmGetEltNb(reInfo->params, RM_SECT_DRIVERS); if (nCars == 0) { // Add all local humans if there are no drivers already specified while (GetHumanDriver(driver,i++)) { driver.client = false; driver.active = true; NetGetServer()->UpdateDriver(driver); NetGetServer()->SetDriverName(driver.name); GfLogInfo("NetworkRaceInfo: Adding default driver %s\n",driver.name); } // ensure changes writen to 'networkrace.xml' NetGetServer()->GenerateDriversForXML(); // add drivers so they show up in race config dialogue GfDrivers::self()->reload(); LmRaceEngine().race()->load(LmRaceEngine().race()->getManager(), true); } else { // Add the humans which are already in the race char dname[256]; for (i = 1; i < nCars+1; i++) { sprintf(dname, "%s/%d", RM_SECT_DRIVERS, i); if(strcmp(NETWORKROBOT, GfParmGetStr(reInfo->params, dname, RM_ATTR_MODULE, "")) == 0) { if (GetHumanDriver(driver,i) > -1) { driver.client = false; driver.active = true; NetGetServer()->UpdateDriver(driver); NetGetServer()->SetDriverName(driver.name); GfLogInfo("NetworkRaceInfo: Adding default driver %s\n",driver.name); } } } } // make sure nobody is 'ready to race' NetMutexData *pNData = NetGetNetwork()->LockNetworkData(); for (unsigned int i=0; i < pNData->m_vecReadyStatus.size(); i++) pNData->m_vecReadyStatus[i] = false; NetGetNetwork()->UnlockNetworkData(); bRobotsReady = false; // ensure the system knows about 'new' network drivers reInfo->params = GfParmReadFileLocal("config/raceman/networkrace.xml",GFPARM_RMODE_REREAD); reInfo->_reName = GfParmGetStr(reInfo->params, RM_SECT_HEADER, RM_ATTR_NAME, ""); }
void CarSettingsMenu::onAccept(void *p) { GfCar *pCar = GfCars::self()->getCarWithName(m_strCar); NetGetNetwork()->SetCarInfo(pCar->getId().c_str()); GfuiScreenActivate(pPrevMenu); }
int ReSituationUpdater::threadLoop() { // Wait delay for each loop, from bRunning value (index 0 = false, 1 = true). static const unsigned KWaitDelayMS[2] = { 1, (unsigned)(RCM_MAX_DT_SIMU * 1000 / 10) }; // Termination flag. bool bEnd = false; // Local state (false = paused, true = simulating). bool bRunning = false; // Current real time. double realTime; // Apply thread affinity to the current = situation updater thread if specified. // Note: No need to reset the affinity, as the thread is just born. if (_bThreadAffinity) GfSetThreadAffinity(NSituationUpdaterCPUId); tRmInfo* pCurrReInfo = ReSituation::self().data(); GfLogInfo("SituationUpdater thread is started.\n"); do { // Let's make current step the next one (update). // 1) Lock the race engine data. ReSituation::self().lock("ReSituationUpdater::threadLoop"); // 2) Check if time to terminate has come. if (_bTerminate) bEnd = true; // 3) If not time to terminate, and running, do the update job. else if (pCurrReInfo->_reRunning) { if (!bRunning) { bRunning = true; GfLogInfo("SituationUpdater thread is running.\n"); } realTime = GfTimeClock(); GfProfStartProfile("reOneStep*"); while (pCurrReInfo->_reRunning && ((realTime - pCurrReInfo->_reCurTime) > RCM_MAX_DT_SIMU)) { // One simu + robots (if any) step runOneStep(RCM_MAX_DT_SIMU); } GfProfStopProfile("reOneStep*"); // Send car physics to network if needed if (NetGetNetwork()) NetGetNetwork()->SendCarControlsPacket(pCurrReInfo->s); } // 3) If not time to terminate, and not running, do nothing. else { if (bRunning) { bRunning = false; GfLogInfo("SituationUpdater thread is paused.\n"); } } // 4) Unlock the race engine data. ReSituation::self().unlock("ReSituationUpdater::threadLoop"); // 5) Let the CPU take breath if possible (but after unlocking data !). SDL_Delay(KWaitDelayMS[(int)bRunning]); } while (!bEnd); GfLogInfo("SituationUpdater thread has been terminated.\n"); return 0; }
void ReSituationUpdater::runOneStep(double deltaTimeIncrement) { tRmInfo* pCurrReInfo = ReSituation::self().data(); tSituation *s = pCurrReInfo->s; // Race messages life cycle management. ReRaceMsgManage(pCurrReInfo); if (NetGetNetwork()) { // Resync clock in case computer falls behind if (s->currentTime < 0.0) { s->currentTime = GfTimeClock() - NetGetNetwork()->GetRaceStartTime(); } if (s->currentTime < -2.0) { std::ostringstream ossMsg; ossMsg << "Race will start in " << -(int)s->currentTime << " seconds"; ReRaceMsgSetBig(pCurrReInfo, ossMsg.str().c_str()); } } //GfLogDebug("ReSituationUpdater::runOneStep: currTime=%.3f\n", s->currentTime); if (s->currentTime >= -2.0 && s->currentTime < deltaTimeIncrement - 2.0) { ReRaceMsgSetBig(pCurrReInfo, "Ready", 1.0); GfLogInfo("Ready.\n"); } else if (s->currentTime >= -1.0 && s->currentTime < deltaTimeIncrement - 1.0) { ReRaceMsgSetBig(pCurrReInfo, "Set", 1.0); GfLogInfo("Set.\n"); } else if (s->currentTime >= 0.0 && s->currentTime < deltaTimeIncrement) { ReRaceMsgSetBig(pCurrReInfo, "Go", 1.0); GfLogInfo("Go.\n"); } // Update times. pCurrReInfo->_reCurTime += deltaTimeIncrement * pCurrReInfo->_reTimeMult; /* "Real" time */ s->currentTime += deltaTimeIncrement; /* Simulated time */ if (s->currentTime < 0) { /* no simu yet */ pCurrReInfo->s->_raceState = RM_RACE_PRESTART; } else if (pCurrReInfo->s->_raceState == RM_RACE_PRESTART) { pCurrReInfo->s->_raceState = RM_RACE_RUNNING; s->currentTime = 0.0; /* resynchronize */ pCurrReInfo->_reLastRobTime = 0.0; } tTrackLocalInfo *trackLocal = &ReInfo->track->local; if (s->currentTime > 0 && trackLocal->timeofdayindex == 9) { //RM_VAL_TIME_24HR if (s->_totTime > 0) { // Scaled on Total Time s->accelTime = 24 * 3600 * s->currentTime / s->_totTime; } else { // Scaled on Number of Laps that the lead driver has completed if (s->cars[0]->_laps > 0 && s->cars[0]->_laps <= s->_totLaps) { // prevent issues if lead driver crosses line the wrong way if (pCurrReInfo->raceEngineInfo.carInfo->lapFlag) s->accelTime = s->cars[0]->_laps - 1; else s->accelTime = s->cars[0]->_laps - 1 + (s->cars[0]->_distFromStartLine / pCurrReInfo->track->length); s->accelTime = 24 * 3600 * s->accelTime / s->_totLaps; } else s->accelTime = 0; } } else s->accelTime = s->currentTime; GfProfStartProfile("rbDrive*"); GfSchedBeginEvent("raceupdate", "robots"); if ((s->currentTime - pCurrReInfo->_reLastRobTime) >= RCM_MAX_DT_ROBOTS) { s->deltaTime = s->currentTime - pCurrReInfo->_reLastRobTime; tRobotItf *robot; for (int i = 0; i < s->_ncars; i++) { if ((s->cars[i]->_state & RM_CAR_STATE_NO_SIMU) == 0) { robot = s->cars[i]->robot; robot->rbDrive(robot->index, s->cars[i], s); } else if (! (s->cars[i]->_state & RM_CAR_STATE_ENDRACE_CALLED ) && ( s->cars[i]->_state & RM_CAR_STATE_OUT ) == RM_CAR_STATE_OUT ) { // No simu, look if it is out robot = s->cars[i]->robot; if (robot->rbEndRace) robot->rbEndRace(robot->index, s->cars[i], s); s->cars[i]->_state |= RM_CAR_STATE_ENDRACE_CALLED; } } pCurrReInfo->_reLastRobTime = s->currentTime; } GfSchedEndEvent("raceupdate", "robots"); GfProfStopProfile("rbDrive*"); if (NetGetNetwork()) ReNetworkOneStep(); GfProfStartProfile("physicsEngine.update*"); GfSchedBeginEvent("raceupdate", "physics"); RePhysicsEngine().updateSituation(s, deltaTimeIncrement); bool bestLapChanged = false; for (int i = 0; i < s->_ncars; i++) ReCarsManageCar(s->cars[i], bestLapChanged); GfSchedEndEvent("raceupdate", "physics"); GfProfStopProfile("physicsEngine.update*"); ReCarsSortCars(); // Update results if a best lap changed if (pCurrReInfo->_displayMode == RM_DISP_MODE_NONE && s->_ncars > 1 && bestLapChanged) { if (pCurrReInfo->s->_raceType == RM_TYPE_PRACTICE) ReUpdatePracticeCurRes(pCurrReInfo->s->cars[0]); else if (pCurrReInfo->s->_raceType == RM_TYPE_QUALIF) ReUpdateQualifCurRes(pCurrReInfo->s->cars[0]); } }
// Host on-line race menu. void RmNetworkHostMenu(void * /* dummy */) { GfLogTrace("Entering Network Host menu.\n"); if (!NetGetNetwork()) { NetSetServer(true); NetSetClient(false); if (!NetGetServer()->Start(SPEEDDREAMSPORT)) { NetSetServer(false); return; } } if (racemanMenuHdle) GfuiScreenRelease(racemanMenuHdle); racemanMenuHdle = GfuiScreenCreate(NULL, NULL, (tfuiCallback)OnActivateNetworkHost, NULL, (tfuiCallback)NULL, 1); void *mparam = GfuiMenuLoad("networkhostmenu.xml"); GfuiMenuCreateStaticControls(racemanMenuHdle, mparam); RmSetRacemanMenuHandle(racemanMenuHdle); NetworkRaceInfo(); g_trackHd = GfuiMenuCreateLabelControl(racemanMenuHdle,mparam,"trackname"); g_lapsHd = GfuiMenuCreateLabelControl(racemanMenuHdle,mparam,"lapcountname"); g_catHd = GfuiMenuCreateLabelControl(racemanMenuHdle,mparam,"carcatname"); g_OutlineId = GfuiMenuCreateStaticImageControl(racemanMenuHdle,mparam,"outlineimage"); //Show players for (int i = 0; i < MAXNETWORKPLAYERS; i++) { char buf[1024]; sprintf(buf,"ready%i",i); g_readystatus[i] = GfuiMenuCreateStaticImageControl(racemanMenuHdle,mparam,buf); GfuiVisibilitySet(racemanMenuHdle,g_readystatus[i],false); sprintf(buf,"driver%i",i); g_playerNames[i] = GfuiMenuCreateLabelControl(racemanMenuHdle,mparam,buf); GfuiLabelSetText(racemanMenuHdle,g_playerNames[i],""); sprintf(buf,"car%i",i); g_carNames[i] = GfuiMenuCreateLabelControl(racemanMenuHdle,mparam,buf); GfuiLabelSetText(racemanMenuHdle,g_carNames[i],""); } g_ReadyCheckboxId = GfuiMenuCreateCheckboxControl(racemanMenuHdle, mparam, "playerreadycheckbox", NULL, onHostPlayerReady); g_HostSettingsButtonId = GfuiMenuCreateButtonControl(racemanMenuHdle, mparam, "networkhostsettings", racemanMenuHdle, rmNetworkHostSettingsMenu); GfuiEnable(racemanMenuHdle, g_HostSettingsButtonId, GFUI_DISABLE); g_RaceSetupId = GfuiMenuCreateButtonControl(racemanMenuHdle, mparam, "racesetup", racemanMenuHdle, RmConfigureRace); GfuiMenuCreateButtonControl(racemanMenuHdle, mparam, "start race", NULL, ServerPrepareStartNetworkRace); g_CancelButtonId = GfuiMenuCreateButtonControl(racemanMenuHdle, mparam, "cancel", NULL, rmNetworkServerDisconnect); GfParmReleaseHandle(mparam); GfuiMenuDefaultKeysAdd(racemanMenuHdle); GfuiAddKey(racemanMenuHdle, GFUIK_ESCAPE, "Back to previous menu", 0, 0, rmNetworkServerDisconnect); UpdateNetworkPlayers(); GfuiScreenActivate(racemanMenuHdle); }