static void v_networkQueueUpdateNextWakeup( v_networkQueue queue, c_bool *hasChanged) { c_time now; c_time soon; c_time newWakeup; c_ulonglong msecsTime; c_ulonglong msecsResult; c_ulonglong msecsLeftOver; static c_time minSleepTime = MIN_SLEEPTIME; *hasChanged = FALSE; if (queue->periodic) { now = v_timeGet(); soon = c_timeAdd(now, minSleepTime); TIME_TO_MSEC(soon, msecsTime); /* Do a ++ because we are doing a ceil and TIME_TO_MSEC is doing a trunc. * Only if time was an exact multiple of milliseconds, this approach is * not completely correct. But it saves us the hassle and this works fine */ msecsTime++; msecsLeftOver = (msecsTime - queue->phaseMilliSeconds) % queue->msecsResolution; msecsResult = msecsTime - msecsLeftOver + queue->msecsResolution; MSEC_TO_TIME(msecsResult, newWakeup); if (c_timeCompare(newWakeup,queue->nextWakeup) == C_GT) { queue->nextWakeup = newWakeup; *hasChanged = TRUE; } } }
static int __money_interval_rand_time ( void ) { const int min = set.money_interval_rand_min; const int max = set.money_interval_rand_max + 1; return MSEC_TO_TIME( (min + (rand() % (max - min))) * 1000 ); }
void cheat_handle_vehicle_recording ( struct vehicle_info *info, float time_diff ) { char buffer[512]; float set_speed[3]; float set_spin[3]; if ( info == NULL || !set.recording_activated ) return; traceLastFunc( "cheat_handle_vehicle_recording()" ); // recording key if ( KEY_PRESSED(set.key_recording_record) ) { if ( rec_state == RECORDING_RECORD ) { rec_maxNum = rec_index; rec_state = RECORDING_OFF; return; } else if ( rec_state == RECORDING_OFF ) { rec_state = RECORDING_RECORD; rec_maxNum = 0; rec_index = 0; rec_playNext = 0.0f; } } if ( KEY_PRESSED(set.key_recording_continueAfterFinish) ) rec_continueAfterFin ^= 1; // play keys if ( (KEY_PRESSED(set.key_recording_play) || KEY_PRESSED(set.key_recording_customSpeed) || KEY_PRESSED(set.key_recording_rev) || KEY_PRESSED(set.key_recording_rev_customSpeed)) ) { // if record playing if ( rec_state >= RECORDING_PLAY ) { rec_state = RECORDING_OFF; return; } else if ( rec_state == RECORDING_OFF ) { // something to play? if ( rec_maxNum <= 0 ) { rec_state = RECORDING_OFF; return; } rec_index = 0; rec_playNext = 0.0f; if ( KEY_PRESSED(set.key_recording_play) ) rec_state = RECORDING_PLAY; else if ( KEY_PRESSED(set.key_recording_customSpeed) ) rec_state = RECORDING_PLAY_CUSTOMSPEED; else if ( KEY_PRESSED(set.key_recording_rev) ) { rec_index = (rec_maxNum-1); rec_state = RECORDING_PLAY_REV; } else if ( KEY_PRESSED(set.key_recording_rev_customSpeed) ) { rec_index = (rec_maxNum-1); rec_state = RECORDING_PLAY_REV_CUSTOMSPEED; } // user set a maximum distance to entry point? if ( set.recording_maxDistToEntryPoint > 0.0f ) { // check if current selected index is in maxRange, else look for a point closest // to the selected beginning, which is in the maxRange if ( vect3_dist(rec_pos[rec_index], &info->base.matrix[4*3]) > set.recording_maxDistToEntryPoint ) { int i = rec_index; int rec_index_new = -1; // not a entry point we want (too far), lets find a better one while ( i >= 0 && i < rec_maxNum ) { if ( vect3_dist(rec_pos[i], &info->base.matrix[4*3]) <= set.recording_maxDistToEntryPoint ) { rec_index_new = i; break; } if ( rec_state == RECORDING_PLAY_REV || rec_state == RECORDING_PLAY_REV_CUSTOMSPEED ) i--; else i++; } // nothing close enough found if ( rec_index_new == -1 ) { rec_state = RECORDING_OFF; cheat_state_text( "Too far from route - maxDist: %0.2f", set.recording_maxDistToEntryPoint ); } else rec_index = rec_index_new; } } } } if ( rec_state == RECORDING_RECORD ) { pD3DFont->PrintShadow( 99, 250, D3DCOLOR_ARGB(255, 255, 0, 0), "Vehicle Recording" ); if ( (TIME_TO_FLOAT(time_get()) - rec_playNext) < 0.0f ) return; vect3_copy( &info->base.matrix[4*3+0], rec_pos[rec_index] ); vect3_copy( &info->base.matrix[4*0+0], &rec_angle[rec_index][0] ); vect3_copy( &info->base.matrix[4*1+0], &rec_angle[rec_index][3] ); vect3_copy( info->spin, rec_spin[rec_index] ); vect3_copy( info->speed, rec_speed[rec_index] ); rec_index++; rec_playNext = TIME_TO_FLOAT(time_get()) + TIME_TO_FLOAT((float)MSEC_TO_TIME(REC_DEFAULT_WAITTIME)); if ( rec_index == (REC_ARRAYSIZE-1) ) { rec_maxNum = rec_index; rec_state = RECORDING_OFF; } } // >= because only play states should follow after RECORDING_PLAY else if ( rec_state >= RECORDING_PLAY ) { // deactivate playing records while air brakeing/sticking if ( cheat_state->vehicle.air_brake || cheat_state->vehicle.stick ) { rec_state = RECORDING_OFF; return; } // move into some better place (maybe hud?) _snprintf_s( buffer, sizeof(buffer)-1, "Vehicle Play Record%s%s", (rec_state == RECORDING_PLAY_REV || rec_state == RECORDING_PLAY_REV_CUSTOMSPEED) ? " (Rev)" : "", rec_continueAfterFin ? " (Continuously)" : "" ); _snprintf_s( buffer, sizeof(buffer)-1, "%s%s", buffer, (rec_state == RECORDING_PLAY_REV_CUSTOMSPEED || rec_state == RECORDING_PLAY_CUSTOMSPEED) ? " (Custom Speed)" : "" ); pD3DFont->PrintShadow( 99, 250, D3DCOLOR_ARGB(255, 0, 255, 0), buffer ); // will need overtime variable for data row skipping float overtime = (TIME_TO_FLOAT(time_get()) - rec_playNext); // do nothing, if the planned next-frame time wasn't reached yet if ( overtime < 0.0f ) return; vect3_copy( rec_pos[rec_index], &info->base.matrix[4*3+0] ); vect3_copy( &rec_angle[rec_index][0], &info->base.matrix[4*0+0] ); vect3_copy( &rec_angle[rec_index][3], &info->base.matrix[4*1+0] ); vect3_copy( rec_spin[rec_index], set_spin ); vect3_copy( rec_speed[rec_index], set_speed ); // multiply speed/spin (for ff mode) and set the playNextTick if ( rec_state == RECORDING_PLAY_CUSTOMSPEED || rec_state == RECORDING_PLAY_REV_CUSTOMSPEED ) { vect3_mult( set_spin, set.recording_play_customSpeed, set_spin ); vect3_mult( set_speed, set.recording_play_customSpeed, set_speed ); // custom speed multiplier faster/higher than possible to play one by one? // if its not the first point (rec_playNext still default) skip a few if ( overtime > 0.0f && rec_playNext != 0.0f ) { // (now-plannedArrival) = overtime -> plannedArrival is way back in the past [so we gotta skip // some of the rows to keep up with the recording/show it 'fluent' (or at least somehow timed correct)] // determine how many data rows we gotta skip ((now-plannedArrival)/timePerRow) float skipAble = overtime / (float)(TIME_TO_FLOAT((float)MSEC_TO_TIME(REC_DEFAULT_WAITTIME))/set.recording_play_customSpeed); if ( skipAble > 1.0f ) { int skipAFew = ceil(skipAble); if ( skipAFew > 0 && rec_state >= RECORDING_PLAY_REV ) rec_index -= skipAFew; else if ( skipAFew > 0 ) rec_index += skipAFew; } } // calculate the time for the next data row rec_playNext = TIME_TO_FLOAT(time_get()) + (TIME_TO_FLOAT((float)MSEC_TO_TIME(REC_DEFAULT_WAITTIME))/set.recording_play_customSpeed ); } else { // in case REC_DEFAULT_WAITTIME is too low, or this code is running on a slow computer // (or player tabbed/paused the game and refocuses the gta window) if ( overtime > 0.0f && rec_playNext != 0.0f ) { // determine how many data rows we gotta skip float skipAble = overtime / (float)(TIME_TO_FLOAT(MSEC_TO_TIME(REC_DEFAULT_WAITTIME))); if ( skipAble > 1.0f ) { int skipAFew = ceil(skipAble); if ( skipAFew > 0 && rec_state >= RECORDING_PLAY_REV ) rec_index -= skipAFew; else if ( skipAFew > 0 ) rec_index += skipAFew; } } rec_playNext = TIME_TO_FLOAT(time_get()) + TIME_TO_FLOAT(MSEC_TO_TIME(REC_DEFAULT_WAITTIME)); } // inverse speed/spin (for rev mode) and set rec_index if ( rec_state >= RECORDING_PLAY_REV ) { vect3_mult( set_spin, -1.0f, set_spin ); vect3_mult( set_speed, -1.0f, set_speed ); rec_index--; // reached end of recording if ( rec_index <= 0 ) { if ( !rec_continueAfterFin ) rec_state = RECORDING_OFF; else { if ( set.recording_maxDistToEntryPoint > 0.0f ) { // deactivate, if new starting position is too far from this point if ( vect3_dist(rec_pos[rec_index], rec_pos[(rec_maxNum-1)]) > set.recording_maxDistToEntryPoint ) rec_state = RECORDING_OFF; } rec_index = (rec_maxNum-1); } } } else { rec_index++; // reached end of recording if ( (rec_index >= (REC_ARRAYSIZE-1) || rec_index >= rec_maxNum) ) { if ( !rec_continueAfterFin ) rec_state = RECORDING_OFF; else { if ( set.recording_maxDistToEntryPoint > 0.0f ) { // deactivate, if new starting position is too far from this point if ( vect3_dist(rec_pos[rec_index], rec_pos[0]) > set.recording_maxDistToEntryPoint ) rec_state = RECORDING_OFF; } rec_index = 0; } } } // copy new speed/spin after it has been adjusted for ff/rev mode vect3_copy( set_spin, info->spin ); vect3_copy( set_speed, info->speed ); } else { rec_state = RECORDING_OFF; } }
c_bool v_networkQueueWrite( v_networkQueue queue, v_message msg, v_networkReaderEntry entry, c_long sequenceNumber, v_gid sender, c_bool sendTo, /* for p2p writing */ v_gid receiver) { c_bool result = TRUE; c_bool wasEmpty; c_bool found; v_networkStatusMarker *currentMarkerPtr; v_networkStatusMarker currentMarker; v_networkStatusMarker marker; v_networkQueueSample newHolder; c_ulonglong msecsTime; c_ulonglong msecsResult; c_ulonglong msecsLeftOver; c_time sendBeforeNoTrunc; c_time sendBefore; c_time now; c_ulong priorityLookingFor; c_equality eq; c_bool newMarkerCreated = FALSE; c_bool sendNow = FALSE; V_MESSAGE_STAMP(msg,readerInsertTime); c_mutexLock(&queue->mutex); /* numberOfSamplesArrived statistics */ v_networkQueueStatisticsAdd(numberOfSamplesArrived,queue->statistics); if (queue->currentMsgCount == queue->maxMsgCount) { c_mutexUnlock(&queue->mutex); /* numberOfSamplesRejected stat */ v_networkQueueStatisticsAdd(numberOfSamplesRejected,queue->statistics); return FALSE; } currentMarkerPtr = &(queue->firstStatusMarker); currentMarker = *currentMarkerPtr; if (queue->threadWaiting) { wasEmpty = !v_networkQueueHasExpiringData(queue); } else { wasEmpty = FALSE; } marker = NULL; found = FALSE; priorityLookingFor = v_messageQos_getTransportPriority(msg->qos); if (queue->periodic) { if (v_messageQos_isZeroLatency(msg->qos)) { sendBefore = C_TIME_ZERO; sendNow = TRUE; } else { #ifdef _NAT_ now = v_timeGet(); #else now = msg->allocTime; #endif sendBeforeNoTrunc = c_timeAdd(now, v_messageQos_getLatencyPeriod(msg->qos)); TIME_TO_MSEC(sendBeforeNoTrunc, msecsTime); msecsLeftOver = (c_ulonglong)((msecsTime - queue->phaseMilliSeconds) % queue->msecsResolution); msecsResult = (c_ulonglong)(msecsTime - msecsLeftOver); MSEC_TO_TIME(msecsResult, sendBefore); } while ((currentMarker != NULL) && (!found)) { eq = c_timeCompare(sendBefore, currentMarker->sendBefore); switch (eq) { case C_GT: currentMarkerPtr = ¤tMarker->next; currentMarker = *currentMarkerPtr; break; case C_EQ: if (priorityLookingFor < currentMarker->priority) { currentMarkerPtr = ¤tMarker->next; currentMarker = *currentMarkerPtr; } else { found = TRUE; if (priorityLookingFor == currentMarker->priority) { marker = currentMarker; } } break; case C_LT: found = TRUE; break; default: assert(FALSE); break; } } } else { if (currentMarker) { sendBefore = C_TIME_ZERO; if (c_timeIsZero(currentMarker->sendBefore)) { marker = currentMarker; } } } /* Insert after end of list */ if (marker == NULL) { newMarkerCreated = TRUE; if (queue->freeStatusMarkers == NULL) { marker = v_networkStatusMarker(c_new(queue->statusMarkerType)); } else { marker = queue->freeStatusMarkers; queue->freeStatusMarkers = marker->next; } if (marker != NULL) { marker->sendBefore = sendBefore; marker->priority = priorityLookingFor; marker->firstSample = NULL; marker->lastSample = NULL; marker->next = *currentMarkerPtr; /* no keep, transfer refCount */ if (marker->next == NULL) { queue->lastStatusMarker = marker; /* no keep, not reference counted */ } *currentMarkerPtr = marker; /* no keep, transfer refCount */ } else { OS_REPORT(OS_ERROR, "v_networkQueueWrite",0, "Failed to send message."); c_mutexUnlock(&queue->mutex); return FALSE; } } V_MESSAGE_STAMP(msg,readerLookupTime); assert(marker != NULL); if (queue->freeSamples == NULL) { newHolder = c_new(queue->sampleType); } else { newHolder = queue->freeSamples; queue->freeSamples = newHolder->next; } if (newHolder) { queue->currentMsgCount++; /* numberOfSamplesInserted & numberOfSamplesWaiting + stats*/ v_networkQueueStatisticsAdd(numberOfSamplesInserted,queue->statistics); v_networkQueueStatisticsCounterInc(numberOfSamplesWaiting,queue->statistics); newHolder->message = c_keep(msg); newHolder->entry = c_keep(entry); newHolder->sequenceNumber = sequenceNumber; newHolder->sender = sender; newHolder->sendTo = sendTo; newHolder->receiver = receiver; if (marker->lastSample != NULL) { newHolder->next = v_networkQueueSample(marker->lastSample)->next; /* no keep, transfer refCount */ v_networkQueueSample(marker->lastSample)->next = newHolder; /* no keep, transfer refCount */ } else { newHolder->next = marker->firstSample; /* no keep, transfer refCount */ marker->firstSample = newHolder; /* no keep, transfer refCount */ } marker->lastSample = newHolder; /* Write done, wake up waiters if needed */ if (wasEmpty && queue->threadWaiting) { if (sendNow || v_networkQueueHasExpiringData(queue)) { c_condBroadcast(&queue->cv); } } } else { OS_REPORT(OS_ERROR, "v_networkQueueWrite",0, "Failed to send message."); result = FALSE; } c_mutexUnlock(&queue->mutex); return result; }