static void onHostPlayerReady(tCheckBoxInfo* pInfo) { tRmInfo* reInfo = LmRaceEngine().inData(); char dname[256]; int nCars = GfParmGetEltNb(reInfo->params, RM_SECT_DRIVERS); NetServerMutexData *pSData = NetGetServer()->LockServerData(); for (int i=1; i <= nCars; i++) { sprintf(dname, "%s/%d", RM_SECT_DRIVERS, i); GfLogInfo("Setting driver %d to %d\n", i, pInfo->bChecked); if(strcmp(NETWORKROBOT, GfParmGetStr(reInfo->params, dname, RM_ATTR_MODULE, "")) == 0) { // Human drive, check if local int index = GfParmGetNum(reInfo->params, dname, RM_ATTR_IDX, NULL, 1.0) - 1; GfLogInfo("Index %d\n", index); if (pSData->m_vecNetworkPlayers[index].client == false) NetGetServer()->OverrideDriverReady(i, pInfo->bChecked); } else { // Robot driver, all are local NetGetServer()->OverrideDriverReady(i, pInfo->bChecked); } bRobotsReady = pInfo->bChecked; } NetGetServer()->UnlockServerData(); EnableMenuHostButtons(pInfo->bChecked); GfLogInfo("menu ready\n"); }
static void rmNetworkServerDisconnect(void * /* dummy */) { GfLogInfo("Disconnecting all clients\n"); if (NetGetServer()) NetGetServer()->Disconnect(); GfuiScreenActivate(RmRaceSelectMenuHandle); }
static void ServerPrepareStartNetworkRace(void * /* dummy */) { NetGetServer()->SetLocalDrivers(); //Tell all clients to prepare to race and wait for response from all clients NetGetServer()->SendPrepareToRacePacket(); //restore the idle function GfuiApp().eventLoop().setRecomputeCB(GfuiIdle); LmRaceEngine().startNewRace(); }
static void HostServerIdle(void) { GfuiIdle(); if (NetIsServer()) { if (NetGetServer()->GetRaceInfoChanged()) { CheckDriversCategory(); //Send to clients all of the xml files we modified and client needs to reload NetGetServer()->SendFilePacket("drivers/networkhuman/networkhuman.xml"); NetGetServer()->SendFilePacket("config/raceman/networkrace.xml"); NetGetServer()->SendRaceSetupPacket(); NetGetServer()->SendDriversReadyPacket(); NetGetServer()->SetRaceInfoChanged(false); } else { if (NetGetServer()->GetRefreshDisplay()) { UpdateNetworkPlayers(); } } GfuiApp().eventLoop().postRedisplay(); } /* Let CPU take breath (and fans stay at low and quiet speed) */ GfSleep(0.001); }
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); }
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(); }
void ReCarsManageCar(tCarElt *car, bool& bestLapChanged) { char msg[64]; int i; int xx; tTrackSeg *sseg; tdble wseg; static const float ctrlMsgColor[] = {0.0, 0.0, 1.0, 1.0}; tSituation *s = ReInfo->s; tReCarInfo *info = &(ReInfo->_reCarInfo[car->index]); // Update top speeds. if (car->_speed_x > car->_topSpeed) car->_topSpeed = car->_speed_x; // (practice and qualification only). if (car->_speed_x > info->topSpd) info->topSpd = car->_speed_x; if (car->_speed_x < info->botSpd) info->botSpd = car->_speed_x; // Pitstop management. if (car->_pit) { // If the driver can ask for a pit, update control messages whether slot occupied or not. if (car->ctrl.raceCmd & RM_CMD_PIT_ASKED) { // Pit already occupied? if (car->_pit->pitCarIndex == TR_PIT_STATE_FREE) snprintf(car->ctrl.msg[2], RM_CMD_MAX_MSG_SIZE, "Can Pit"); else snprintf(car->ctrl.msg[2], RM_CMD_MAX_MSG_SIZE, "Pit Occupied"); car->ctrl.msg[2][RM_CMD_MAX_MSG_SIZE-1] = 0; // Some snprintf implementations fail to do so. memcpy(car->ctrl.msgColor, ctrlMsgColor, sizeof(car->ctrl.msgColor)); } // If pitting, check if pitting delay over, and end up with pitting process if so. if (car->_state & RM_CAR_STATE_PIT) { car->ctrl.raceCmd &= ~RM_CMD_PIT_ASKED; // clear the flag. // Note: Due to asynchronous behaviour of the main updater and the situation updater, // we have to wait for car->_scheduledEventTime being set to smthg > 0. if (car->_scheduledEventTime > 0.0) { if (car->_scheduledEventTime < s->currentTime) { car->_state &= ~RM_CAR_STATE_PIT; car->_pit->pitCarIndex = TR_PIT_STATE_FREE; snprintf(msg, sizeof(msg), "%s pit stop %.1f s", car->_name, info->totalPitTime); msg[sizeof(msg)-1] = 0; // Some snprintf implementations fail to do so. ReSituation::self().setRaceMessage(msg, 5); GfLogInfo("%s exiting pit (%.1f s elapsed).\n", car->_name, info->totalPitTime); } else { snprintf(car->ctrl.msg[2], RM_CMD_MAX_MSG_SIZE, "In pits %.1f s", s->currentTime - info->startPitTime); car->ctrl.msg[2][RM_CMD_MAX_MSG_SIZE-1] = 0; // Some snprintf implementations fail to do so. } } // If the driver asks for a pit, check if the car is in the right conditions // (position, speed, ...) and start up pitting process if so. } else if ((car->ctrl.raceCmd & RM_CMD_PIT_ASKED) && car->_pit->pitCarIndex == TR_PIT_STATE_FREE && (s->_maxDammage == 0 || car->_dammage <= s->_maxDammage)) { snprintf(car->ctrl.msg[2], RM_CMD_MAX_MSG_SIZE, "Pit request"); car->ctrl.msg[2][RM_CMD_MAX_MSG_SIZE-1] = 0; // Some snprintf implementations fail to do so. tdble lgFromStart = car->_trkPos.seg->lgfromstart; switch (car->_trkPos.seg->type) { case TR_STR: lgFromStart += car->_trkPos.toStart; break; default: lgFromStart += car->_trkPos.toStart * car->_trkPos.seg->radius; break; } if ((lgFromStart > car->_pit->lmin) && (lgFromStart < car->_pit->lmax)) { int side; tdble toBorder; if (ReInfo->track->pits.side == TR_RGT) { side = TR_SIDE_RGT; toBorder = car->_trkPos.toRight; } else { side = TR_SIDE_LFT; toBorder = car->_trkPos.toLeft; } sseg = car->_trkPos.seg->side[side]; wseg = RtTrackGetWidth(sseg, car->_trkPos.toStart); if (sseg->side[side]) { sseg = sseg->side[side]; wseg += RtTrackGetWidth(sseg, car->_trkPos.toStart); } if (((toBorder + wseg) < (ReInfo->track->pits.width - car->_dimension_y / 2.0)) && (fabs(car->_speed_x) < 1.0) && (fabs(car->_speed_y) < 1.0)) { // All conditions fullfilled => enter pitting process car->_state |= RM_CAR_STATE_PIT; car->_scheduledEventTime = 0.0; // Pit will really start when set to smthg > 0. car->_nbPitStops++; for (i = 0; i < car->_pit->freeCarIndex; i++) { if (car->_pit->car[i] == car) { car->_pit->pitCarIndex = i; break; } } info->startPitTime = s->currentTime; snprintf(msg, sizeof(msg), "%s in pits", car->_name); msg[sizeof(msg)-1] = 0; // Some snprintf implementations fail to do so. ReSituation::self().setRaceMessage(msg, 5); GfLogInfo("%s entering in pit slot.\n", car->_name); if (car->robot->rbPitCmd(car->robot->index, car, s) == ROB_PIT_MENU) { // the pit cmd is modified by menu. reCarsSchedulePitMenu(car); } else { ReCarsUpdateCarPitTime(car); } } else { // The cars speed or offset is out of accepted range // Show the user/developer/robot the reason of the issue tTeamDriver* TeamDriver = RtTeamDriverByCar(car); if (TeamDriver) { TeamDriver->StillToGo = 0.0; TeamDriver->MoreOffset = 0.0; TeamDriver->TooFastBy = 0.0; } float Offset = (float) ((toBorder + wseg) - (ReInfo->track->pits.width - car->_dimension_y / 2.0)); if (Offset >= 0.0) { // The car's position across the track is out of accepted range snprintf(car->ctrl.msg[2], RM_CMD_MAX_MSG_SIZE, "Offset: %.02f",Offset); car->ctrl.msg[2][RM_CMD_MAX_MSG_SIZE-1] = 0; // Some snprintf implementations fail to do so. if (TeamDriver) TeamDriver->MoreOffset = Offset; } float TooFastBy = MAX(fabs(car->_speed_x),fabs(car->_speed_y)); if (TooFastBy >= 1.0) { // The car's speed is out of accepted range snprintf(car->ctrl.msg[2], RM_CMD_MAX_MSG_SIZE, "Speed: %.02f",TooFastBy); car->ctrl.msg[2][RM_CMD_MAX_MSG_SIZE-1] = 0; // Some snprintf implementations fail to do so. if (TeamDriver) TeamDriver->TooFastBy = TooFastBy; } } } else { // The car's position along the track is out of accepted range // Show the user/developer/robot the reason of the issue tTeamDriver* TeamDriver = RtTeamDriverByCar(car); if (TeamDriver) { TeamDriver->StillToGo = 0.0; TeamDriver->MoreOffset = 0.0; TeamDriver->TooFastBy = 0.0; } if (car->_pit->lmin > lgFromStart) { float StillToGo = car->_pit->lmin - lgFromStart; snprintf(car->ctrl.msg[2], RM_CMD_MAX_MSG_SIZE, "Still to go: %0.2f m" ,StillToGo); car->ctrl.msg[2][RM_CMD_MAX_MSG_SIZE-1] = 0; // Some snprintf implementations fail to do so. if (TeamDriver) TeamDriver->StillToGo = StillToGo; } else if (car->_pit->lmax < lgFromStart) { float StillToGo = lgFromStart - car->_pit->lmax; snprintf(car->ctrl.msg[2], RM_CMD_MAX_MSG_SIZE, "Overrun: %0.2f m" ,StillToGo); car->ctrl.msg[2][RM_CMD_MAX_MSG_SIZE-1] = 0; // Some snprintf implementations fail to do so. if (TeamDriver) TeamDriver->StillToGo = -StillToGo; } } } } /* Check if it is in a new sector */ while (true) { if (car->_currentSector < ReInfo->track->numberOfSectors - 1 && car->_laps > 0 && info->lapFlag == 0) { /* Must pass at least one sector before the finish */ if (RtGetDistFromStart(car) > ReInfo->track->sectors[car->_currentSector]) { /* It is in a new sector : update split time */ car->_curSplitTime[car->_currentSector] = car->_curLapTime; ++car->_currentSector; continue; } } break; } /* Start Line Crossing */ if (info->prevTrkPos.seg != car->_trkPos.seg) { if ((info->prevTrkPos.seg->raceInfo & TR_LAST) && (car->_trkPos.seg->raceInfo & TR_START)) { if (info->lapFlag == 0) { // If the car has not yet finished the race : if (!(car->_state & RM_CAR_STATE_FINISH)) { // 1 more lap completed // (Note: lap with index 0 finishes when the car crosses the start line the 1st time, // and is thus considered a real lap, whereas it is not). car->_laps++; /*if (NetGetNetwork()) NetGetNetwork()->SendLapStatusPacket(car);*/ car->_remainingLaps--; if (car->_pos == 1 && s->currentTime < s->_totTime && s->_raceType == RM_TYPE_RACE) { /* First car passed finish time before the time ends: increase the number of laps for everyone */ for (xx = 0; xx < s->_ncars; ++xx) ++ReInfo->s->cars[xx]->_remainingLaps; ++s->_totLaps; } car->_currentSector = 0; if (car->_laps > 1) { car->_lastLapTime = s->currentTime - info->sTime; if (car->_bestLapTime != 0) { car->_deltaBestLapTime = car->_lastLapTime - car->_bestLapTime; } if ((car->_lastLapTime < car->_bestLapTime) || (car->_bestLapTime == 0)) { car->_bestLapTime = car->_lastLapTime; memcpy(car->_bestSplitTime, car->_curSplitTime, sizeof(double)*(ReInfo->track->numberOfSectors - 1) ); if (s->_raceType != RM_TYPE_RACE && s->_ncars > 1) { /* Best lap time is made better : update times behind leader */ bestLapChanged = true; car->_timeBehindLeader = car->_bestLapTime - s->cars[0]->_bestLapTime; if (car->_pos > 1) { car->_timeBehindPrev = car->_bestLapTime - s->cars[car->_pos - 1]->_bestLapTime; } else { /* New best time for the leader : update the differences */ for (xx = 1; xx < s->_ncars; ++xx) { if (s->cars[xx]->_bestLapTime > 0.0f) s->cars[xx]->_timeBehindLeader = s->cars[xx]->_bestLapTime - car->_bestLapTime; } } if (car->_pos + 1 < s->_ncars && s->cars[car->_pos+1]->_bestLapTime > 0.0f) car->_timeBeforeNext = s->cars[car->_pos + 1]->_bestLapTime - car->_bestLapTime; else car->_timeBeforeNext = 0; } } } if (car->_laps > 0) { car->_curTime += s->currentTime - info->sTime; if (car->_pos != 1 && s->_raceType == RM_TYPE_RACE) { car->_timeBehindLeader = car->_curTime - s->cars[0]->_curTime; car->_lapsBehindLeader = s->cars[0]->_laps - car->_laps; car->_timeBehindPrev = car->_curTime - s->cars[car->_pos - 2]->_curTime; s->cars[car->_pos - 2]->_timeBeforeNext = car->_timeBehindPrev; } else if (s->_raceType == RM_TYPE_RACE) { car->_timeBehindLeader = 0; car->_lapsBehindLeader = 0; car->_timeBehindPrev = 0; } info->sTime = (tdble)s->currentTime; if (ReInfo->s->_raceType == RM_TYPE_PRACTICE && (car->_laps > 1 || s->_totLaps == 0)) ReSavePracticeLap(car); } if (ReInfo->_displayMode == RM_DISP_MODE_NONE) { switch(s->_raceType) { case RM_TYPE_PRACTICE: ReUpdatePracticeCurRes(car); break; case RM_TYPE_QUALIF: ReUpdateQualifCurRes(car); break; case RM_TYPE_RACE: ReUpdateRaceCurRes(); break; default: break; } } info->topSpd = car->_speed_x; info->botSpd = car->_speed_x; if ((car->_remainingLaps < 0 && s->currentTime > s->_totTime) || (s->_raceState == RM_RACE_FINISHING)) { car->_state |= RM_CAR_STATE_FINISH; s->_raceState = RM_RACE_FINISHING; if (ReInfo->s->_raceType == RM_TYPE_RACE) { if (car->_pos == 1) { snprintf(msg, sizeof(msg), "Winner %s", car->_name); msg[sizeof(msg)-1] = 0; // Some snprintf implementations fail to do so. ReSituation::self().setRaceMessage(msg, 10, /*big=*/true); if (NetGetServer()) { NetGetServer()->SetFinishTime(s->currentTime+FINISHDELAY); } } else { const char *numSuffix = "th"; if (abs(12 - car->_pos) > 1) { /* leave suffix as 'th' for 11 to 13 */ switch (car->_pos % 10) { case 1: numSuffix = "st"; break; case 2: numSuffix = "nd"; break; case 3: numSuffix = "rd"; break; default: break; } } snprintf(msg, sizeof(msg), "%s finished %d%s", car->_name, car->_pos, numSuffix); msg[sizeof(msg)-1] = 0; // Some snprintf implementations fail to do so. ReSituation::self().setRaceMessage(msg, 5); } } } // Notify the UI when a lap is completed (by the leader) // and race results have been updated. if (car->_pos == 1) ReUI().onLapCompleted(car->_laps - 1); } else { // Prevent infinite looping of cars around track, // allowing one lap after finish for the first car, but no more for (i = 0; i < s->_ncars; i++) { s->cars[i]->_state |= RM_CAR_STATE_FINISH; } return; } } else { info->lapFlag--; } } if ((info->prevTrkPos.seg->raceInfo & TR_START) && (car->_trkPos.seg->raceInfo & TR_LAST)) { /* going backward through the start line */ info->lapFlag++; } } // Start Line Crossing // Apply race rules (penalties if enabled). reCarsApplyRaceRules(car); // Update misc car info. info->prevTrkPos = car->_trkPos; car->_curLapTime = s->currentTime - info->sTime; car->_distFromStartLine = car->_trkPos.seg->lgfromstart + (car->_trkPos.seg->type == TR_STR ? car->_trkPos.toStart : car->_trkPos.toStart * car->_trkPos.seg->radius); car->_distRaced = (car->_laps - 1) * ReInfo->track->length + car->_distFromStartLine; }
// 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); }
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, ""); }
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); } }