/** * Check whether we need to call the callback, i.e. whether we * have connected or aborted and call the appropriate callback * for that. It's done this way to ease on the locking that * would otherwise be needed everywhere. */ /* static */ void TCPConnecter::CheckCallbacks() { for (TCPConnecter **iter = _tcp_connecters.Begin(); iter < _tcp_connecters.End(); /* nothing */) { TCPConnecter *cur = *iter; if ((cur->connected || cur->aborted) && cur->killed) { _tcp_connecters.Erase(iter); if (cur->sock != INVALID_SOCKET) closesocket(cur->sock); delete cur; continue; } if (cur->connected) { _tcp_connecters.Erase(iter); cur->OnConnect(cur->sock); delete cur; continue; } if (cur->aborted) { _tcp_connecters.Erase(iter); cur->OnFailure(); delete cur; continue; } iter++; } }
static void Ptrs_WAYP() { for (OldWaypoint *wp = _old_waypoints.Begin(); wp != _old_waypoints.End(); wp++) { SlObject(wp, _old_waypoint_desc); if (IsSavegameVersionBefore(12)) { wp->town_cn = (wp->string_id & 0xC000) == 0xC000 ? (wp->string_id >> 8) & 0x3F : 0; wp->town = ClosestTownFromTile(wp->xy, UINT_MAX); } else if (IsSavegameVersionBefore(122)) {
/** * Update the waypoint orders to get the new waypoint ID. * @param o the order 'list' to check. */ static void UpdateWaypointOrder(Order *o) { if (!o->IsType(OT_GOTO_WAYPOINT)) return; for (OldWaypoint *wp = _old_waypoints.Begin(); wp != _old_waypoints.End(); wp++) { if (wp->index != o->GetDestination()) continue; o->SetDestination((DestinationID)wp->new_index); return; } }
/* static */ void NetworkHTTPSocketHandler::HTTPReceive() { /* No connections, just bail out. */ if (_http_connections.Length() == 0) return; fd_set read_fd; struct timeval tv; FD_ZERO(&read_fd); for (NetworkHTTPSocketHandler **iter = _http_connections.Begin(); iter < _http_connections.End(); iter++) { FD_SET((*iter)->sock, &read_fd); } tv.tv_sec = tv.tv_usec = 0; // don't block at all. #if !defined(__MORPHOS__) && !defined(__AMIGA__) int n = select(FD_SETSIZE, &read_fd, NULL, NULL, &tv); #else int n = WaitSelect(FD_SETSIZE, &read_fd, NULL, NULL, &tv, NULL); #endif if (n == -1) return; for (NetworkHTTPSocketHandler **iter = _http_connections.Begin(); iter < _http_connections.End(); /* nothing */) { NetworkHTTPSocketHandler *cur = *iter; if (FD_ISSET(cur->sock, &read_fd)) { int ret = cur->Receive(); /* First send the failure. */ if (ret < 0) cur->callback->OnFailure(); if (ret <= 0) { /* Then... the connection can be closed */ cur->CloseConnection(); _http_connections.Erase(iter); delete cur; continue; } } iter++; } }
void DrawTextEffects(DrawPixelInfo *dpi) { /* Don't draw the text effects when zoomed out a lot */ if (dpi->zoom > ZOOM_LVL_OUT_8X) return; const TextEffect *end = _text_effects.End(); for (TextEffect *te = _text_effects.Begin(); te != end; te++) { if (te->string_id == INVALID_STRING_ID) continue; if (te->mode == TE_RISING || (_settings_client.gui.loading_indicators && !IsTransparencySet(TO_LOADING))) { ViewportAddString(dpi, ZOOM_LVL_OUT_8X, te, te->string_id, te->string_id - 1, 0, te->params_1, te->params_2); } } }
/** * Set the start date of the timetable. * @param tile Not used. * @param flags Operation to perform. * @param p2 Various bitstuffed elements * - p2 = (bit 0-19) - Vehicle ID. * - p2 = (bit 20) - Set to 1 to set timetable start for all vehicles sharing this order * @param p2 The timetable start date. * @param text Not used. * @return The error or cost of the operation. */ CommandCost CmdSetTimetableStart(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { bool timetable_all = HasBit(p1, 20); Vehicle *v = Vehicle::GetIfValid(GB(p1, 0, 20)); if (v == NULL || !v->IsPrimaryVehicle() || v->orders.list == NULL) return CMD_ERROR; CommandCost ret = CheckOwnership(v->owner); if (ret.Failed()) return ret; /* Don't let a timetable start more than 15 years into the future or 1 year in the past. */ Date start_date = (Date)p2; if (start_date < 0 || start_date > MAX_DAY) return CMD_ERROR; if (start_date - _date > 15 * DAYS_IN_LEAP_YEAR) return CMD_ERROR; if (_date - start_date > DAYS_IN_LEAP_YEAR) return CMD_ERROR; if (timetable_all && !v->orders.list->IsCompleteTimetable()) return CMD_ERROR; if (flags & DC_EXEC) { SmallVector<Vehicle *, 8> vehs; if (timetable_all) { for (Vehicle *w = v->orders.list->GetFirstSharedVehicle(); w != NULL; w = w->NextShared()) { *vehs.Append() = w; } } else { *vehs.Append() = v; } int total_duration = v->orders.list->GetTimetableTotalDuration(); int num_vehs = vehs.Length(); if (num_vehs >= 2) { QSortT(vehs.Begin(), vehs.Length(), &VehicleTimetableSorter); } int base = vehs.FindIndex(v); for (Vehicle **viter = vehs.Begin(); viter != vehs.End(); viter++) { int idx = (viter - vehs.Begin()) - base; Vehicle *w = *viter; w->lateness_counter = 0; ClrBit(w->vehicle_flags, VF_TIMETABLE_STARTED); /* Do multiplication, then division to reduce rounding errors. */ w->timetable_start = start_date + idx * total_duration / num_vehs / DAY_TICKS; SetWindowDirty(WC_VEHICLE_TIMETABLE, w->index); } } return CommandCost(); }
void MoveAllTextEffects() { const TextEffect *end = _text_effects.End(); for (TextEffect *te = _text_effects.Begin(); te != end; te++) { if (te->string_id == INVALID_STRING_ID) continue; if (te->mode != TE_RISING) continue; if (te->duration-- == 0) { te->Reset(); continue; } te->MarkDirty(ZOOM_LVL_OUT_8X); te->top -= ZOOM_LVL_BASE; te->MarkDirty(ZOOM_LVL_OUT_8X); } }
/** Kill all connection attempts. */ /* static */ void TCPConnecter::KillAll() { for (TCPConnecter **iter = _tcp_connecters.Begin(); iter != _tcp_connecters.End(); iter++) (*iter)->killed = true; }
/** * Refits a vehicle (chain). * This is the vehicle-type independent part of the CmdRefitXXX functions. * @param v The vehicle to refit. * @param only_this Whether to only refit this vehicle, or to check the rest of them. * @param num_vehicles Number of vehicles to refit (not counting articulated parts). Zero means the whole chain. * @param new_cid Cargotype to refit to * @param new_subtype Cargo subtype to refit to. 0xFF means to try keeping the same subtype according to GetBestFittingSubType(). * @param flags Command flags * @param auto_refit Refitting is done as automatic refitting outside a depot. * @return Refit cost. */ static CommandCost RefitVehicle(Vehicle *v, bool only_this, uint8 num_vehicles, CargoID new_cid, byte new_subtype, DoCommandFlag flags, bool auto_refit) { CommandCost cost(v->GetExpenseType(false)); uint total_capacity = 0; uint total_mail_capacity = 0; num_vehicles = num_vehicles == 0 ? UINT8_MAX : num_vehicles; VehicleSet vehicles_to_refit; if (!only_this) { GetVehicleSet(vehicles_to_refit, v, num_vehicles); /* In this case, we need to check the whole chain. */ v = v->First(); } static SmallVector<RefitResult, 16> refit_result; refit_result.Clear(); v->InvalidateNewGRFCacheOfChain(); byte actual_subtype = new_subtype; for (; v != NULL; v = (only_this ? NULL : v->Next())) { /* Reset actual_subtype for every new vehicle */ if (!v->IsArticulatedPart()) actual_subtype = new_subtype; if (v->type == VEH_TRAIN && !vehicles_to_refit.Contains(v->index) && !only_this) continue; const Engine *e = v->GetEngine(); if (!e->CanCarryCargo()) continue; /* If the vehicle is not refittable, or does not allow automatic refitting, * count its capacity nevertheless if the cargo matches */ bool refittable = HasBit(e->info.refit_mask, new_cid) && (!auto_refit || HasBit(e->info.misc_flags, EF_AUTO_REFIT)); if (!refittable && v->cargo_type != new_cid) continue; /* Determine best fitting subtype if requested */ if (actual_subtype == 0xFF) { actual_subtype = GetBestFittingSubType(v, v, new_cid); } /* Back up the vehicle's cargo type */ CargoID temp_cid = v->cargo_type; byte temp_subtype = v->cargo_subtype; if (refittable) { v->cargo_type = new_cid; v->cargo_subtype = actual_subtype; } uint16 mail_capacity = 0; uint amount = e->DetermineCapacity(v, &mail_capacity); total_capacity += amount; /* mail_capacity will always be zero if the vehicle is not an aircraft. */ total_mail_capacity += mail_capacity; if (!refittable) continue; /* Restore the original cargo type */ v->cargo_type = temp_cid; v->cargo_subtype = temp_subtype; bool auto_refit_allowed; CommandCost refit_cost = GetRefitCost(v, v->engine_type, new_cid, actual_subtype, &auto_refit_allowed); if (auto_refit && !auto_refit_allowed) { /* Sorry, auto-refitting not allowed, subtract the cargo amount again from the total. */ total_capacity -= amount; total_mail_capacity -= mail_capacity; if (v->cargo_type == new_cid) { /* Add the old capacity nevertheless, if the cargo matches */ total_capacity += v->cargo_cap; if (v->type == VEH_AIRCRAFT) total_mail_capacity += v->Next()->cargo_cap; } continue; } cost.AddCost(refit_cost); /* Record the refitting. * Do not execute the refitting immediately, so DetermineCapacity and GetRefitCost do the same in test and exec run. * (weird NewGRFs) * Note: * - If the capacity of vehicles depends on other vehicles in the chain, the actual capacity is * set after RefitVehicle() via ConsistChanged() and friends. The estimation via _returned_refit_capacity will be wrong. * - We have to call the refit cost callback with the pre-refit configuration of the chain because we want refit and * autorefit to behave the same, and we need its result for auto_refit_allowed. */ RefitResult *result = refit_result.Append(); result->v = v; result->capacity = amount; result->mail_capacity = mail_capacity; result->subtype = actual_subtype; } if (flags & DC_EXEC) { /* Store the result */ for (RefitResult *result = refit_result.Begin(); result != refit_result.End(); result++) { Vehicle *u = result->v; if (u->cargo_type != new_cid) { u->cargo.Truncate(u->cargo_cap); } else if (u->cargo_cap > result->capacity) { u->cargo.Truncate(u->cargo_cap - result->capacity); } u->cargo_type = new_cid; u->cargo_cap = result->capacity; u->cargo_subtype = result->subtype; if (u->type == VEH_AIRCRAFT) { Vehicle *w = u->Next(); if (w->cargo_cap > result->mail_capacity) { w->cargo.Truncate(w->cargo_cap - result->mail_capacity); } w->cargo_cap = result->mail_capacity; } } } refit_result.Clear(); _returned_refit_capacity = total_capacity; _returned_mail_refit_capacity = total_mail_capacity; return cost; }
/** * Perform all steps to upgrade from the old waypoints to the new version * that uses station. This includes some old saveload mechanics. */ void MoveWaypointsToBaseStations() { /* In version 17, ground type is moved from m2 to m4 for depots and * waypoints to make way for storing the index in m2. The custom graphics * id which was stored in m4 is now saved as a grf/id reference in the * waypoint struct. */ if (IsSavegameVersionBefore(17)) { for (OldWaypoint *wp = _old_waypoints.Begin(); wp != _old_waypoints.End(); wp++) { if (wp->delete_ctr != 0) continue; // The waypoint was deleted /* Waypoint indices were not added to the map prior to this. */ _m[wp->xy].m2 = (StationID)wp->index; if (HasBit(_m[wp->xy].m3, 4)) { wp->spec = StationClass::Get(STAT_CLASS_WAYP, _m[wp->xy].m4 + 1); } } } else { /* As of version 17, we recalculate the custom graphic ID of waypoints * from the GRF ID / station index. */ for (OldWaypoint *wp = _old_waypoints.Begin(); wp != _old_waypoints.End(); wp++) { for (uint i = 0; i < StationClass::GetCount(STAT_CLASS_WAYP); i++) { const StationSpec *statspec = StationClass::Get(STAT_CLASS_WAYP, i); if (statspec != NULL && statspec->grf_prop.grffile->grfid == wp->grfid && statspec->grf_prop.local_id == wp->localidx) { wp->spec = statspec; break; } } } } if (!Waypoint::CanAllocateItem(_old_waypoints.Length())) SlError(STR_ERROR_TOO_MANY_STATIONS_LOADING); /* All saveload conversions have been done. Create the new waypoints! */ for (OldWaypoint *wp = _old_waypoints.Begin(); wp != _old_waypoints.End(); wp++) { Waypoint *new_wp = new Waypoint(wp->xy); new_wp->town = wp->town; new_wp->town_cn = wp->town_cn; new_wp->name = wp->name; new_wp->delete_ctr = 0; // Just reset delete counter for once. new_wp->build_date = wp->build_date; new_wp->owner = wp->owner; new_wp->string_id = STR_SV_STNAME_WAYPOINT; TileIndex t = wp->xy; if (IsTileType(t, MP_RAILWAY) && GetRailTileType(t) == 2 /* RAIL_TILE_WAYPOINT */ && _m[t].m2 == wp->index) { /* The tile might've been reserved! */ bool reserved = !IsSavegameVersionBefore(100) && HasBit(_m[t].m5, 4); /* The tile really has our waypoint, so reassign the map array */ MakeRailWaypoint(t, GetTileOwner(t), new_wp->index, (Axis)GB(_m[t].m5, 0, 1), 0, GetRailType(t)); new_wp->facilities |= FACIL_TRAIN; new_wp->owner = GetTileOwner(t); SetRailStationReservation(t, reserved); if (wp->spec != NULL) { SetCustomStationSpecIndex(t, AllocateSpecToStation(wp->spec, new_wp, true)); } new_wp->rect.BeforeAddTile(t, StationRect::ADD_FORCE); } wp->new_index = new_wp->index; } /* Update the orders of vehicles */ OrderList *ol; FOR_ALL_ORDER_LISTS(ol) { if (ol->GetFirstSharedVehicle()->type != VEH_TRAIN) continue; for (Order *o = ol->GetFirstOrder(); o != NULL; o = o->next) UpdateWaypointOrder(o); } Vehicle *v; FOR_ALL_VEHICLES(v) { if (v->type != VEH_TRAIN) continue; UpdateWaypointOrder(&v->current_order); } _old_waypoints.Reset(); }
/** * Try to add a fios item set with the given filename. * @param filename the full path to the file to read * @param basepath_length amount of characters to chop of before to get a relative filename * @return true if the file is added. */ bool FiosFileScanner::AddFile(const char *filename, size_t basepath_length, const char *tar_filename) { const char *ext = strrchr(filename, '.'); if (ext == NULL) return false; char fios_title[64]; fios_title[0] = '\0'; // reset the title; FiosType type = this->callback_proc(this->mode, filename, ext, fios_title, lastof(fios_title)); if (type == FIOS_TYPE_INVALID) return false; for (const FiosItem *fios = _fios_items.Begin(); fios != _fios_items.End(); fios++) { if (strcmp(fios->name, filename) == 0) return false; } FiosItem *fios = _fios_items.Append(); #ifdef WIN32 struct _stat sb; if (_tstat(OTTD2FS(filename), &sb) == 0) { #else struct stat sb; if (stat(filename, &sb) == 0) { #endif fios->mtime = sb.st_mtime; } else { fios->mtime = 0; } fios->type = type; strecpy(fios->name, filename, lastof(fios->name)); /* If the file doesn't have a title, use its filename */ const char *t = fios_title; if (StrEmpty(fios_title)) { t = strrchr(filename, PATHSEPCHAR); t = (t == NULL) ? filename : (t + 1); } strecpy(fios->title, t, lastof(fios->title)); str_validate(fios->title, lastof(fios->title)); return true; } /** * Fill the list of the files in a directory, according to some arbitrary rule. * @param mode The mode we are in. Some modes don't allow 'parent'. * @param callback_proc The function that is called where you need to do the filtering. * @param subdir The directory from where to start (global) searching. */ static void FiosGetFileList(SaveLoadDialogMode mode, fios_getlist_callback_proc *callback_proc, Subdirectory subdir) { struct stat sb; struct dirent *dirent; DIR *dir; FiosItem *fios; int sort_start; char d_name[sizeof(fios->name)]; _fios_items.Clear(); /* A parent directory link exists if we are not in the root directory */ if (!FiosIsRoot(_fios_path)) { fios = _fios_items.Append(); fios->type = FIOS_TYPE_PARENT; fios->mtime = 0; strecpy(fios->name, "..", lastof(fios->name)); strecpy(fios->title, ".. (Parent directory)", lastof(fios->title)); } /* Show subdirectories */ if ((dir = ttd_opendir(_fios_path)) != NULL) { while ((dirent = readdir(dir)) != NULL) { strecpy(d_name, FS2OTTD(dirent->d_name), lastof(d_name)); /* found file must be directory, but not '.' or '..' */ if (FiosIsValidFile(_fios_path, dirent, &sb) && S_ISDIR(sb.st_mode) && (!FiosIsHiddenFile(dirent) || strncasecmp(d_name, PERSONAL_DIR, strlen(d_name)) == 0) && strcmp(d_name, ".") != 0 && strcmp(d_name, "..") != 0) { fios = _fios_items.Append(); fios->type = FIOS_TYPE_DIR; fios->mtime = 0; strecpy(fios->name, d_name, lastof(fios->name)); snprintf(fios->title, lengthof(fios->title), "%s" PATHSEP " (Directory)", d_name); str_validate(fios->title, lastof(fios->title)); } } closedir(dir); } /* Sort the subdirs always by name, ascending, remember user-sorting order */ { SortingBits order = _savegame_sort_order; _savegame_sort_order = SORT_BY_NAME | SORT_ASCENDING; QSortT(_fios_items.Begin(), _fios_items.Length(), CompareFiosItems); _savegame_sort_order = order; } /* This is where to start sorting for the filenames */ sort_start = _fios_items.Length(); /* Show files */ FiosFileScanner scanner(mode, callback_proc); if (subdir == NO_DIRECTORY) { scanner.Scan(NULL, _fios_path, false); } else { scanner.Scan(NULL, subdir, true, true); } QSortT(_fios_items.Get(sort_start), _fios_items.Length() - sort_start, CompareFiosItems); /* Show drives */ FiosGetDrives(); _fios_items.Compact(); } /** * Get the title of a file, which (if exists) is stored in a file named * the same as the data file but with '.title' added to it. * @param file filename to get the title for * @param title the title buffer to fill * @param last the last element in the title buffer * @param subdir the sub directory to search in */ static void GetFileTitle(const char *file, char *title, const char *last, Subdirectory subdir) { char buf[MAX_PATH]; strecpy(buf, file, lastof(buf)); strecat(buf, ".title", lastof(buf)); FILE *f = FioFOpenFile(buf, "r", subdir); if (f == NULL) return; size_t read = fread(title, 1, last - title, f); assert(title + read <= last); title[read] = '\0'; str_validate(title, last); FioFCloseFile(f); }