template <> inline Array *GetParam(ForceType<Array *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQObject obj; sq_getstackobj(vm, index, &obj); sq_pushobject(vm, obj); sq_pushnull(vm); SmallVector<int32, 2> data; while (SQ_SUCCEEDED(sq_next(vm, -2))) { SQInteger tmp; if (SQ_SUCCEEDED(sq_getinteger(vm, -1, &tmp))) { *data.Append() = (int32)tmp; } else { sq_pop(vm, 4); throw sq_throwerror(vm, _SC("a member of an array used as parameter to a function is not numeric")); } sq_pop(vm, 2); } sq_pop(vm, 2); Array *arr = (Array*)MallocT<byte>(sizeof(Array) + sizeof(int32) * data.Length()); arr->size = data.Length(); memcpy(arr->array, data.Begin(), sizeof(int32) * data.Length()); *ptr->Append() = arr; return arr; }
/* Text Effects */ TextEffectID AddTextEffect(StringID msg, int center, int y, uint8 duration, TextEffectMode mode) { if (_game_mode == GM_MENU) return INVALID_TE_ID; TextEffectID i; for (i = 0; i < _text_effects.Length(); i++) { if (_text_effects[i].string_id == INVALID_STRING_ID) break; } if (i == _text_effects.Length()) _text_effects.Append(); TextEffect *te = _text_effects.Get(i); /* Start defining this object */ te->string_id = msg; te->duration = duration; te->params_1 = GetDParam(0); te->params_2 = GetDParam(1); te->mode = mode; /* Make sure we only dirty the new area */ te->width_normal = 0; te->UpdatePosition(center, y, msg); return i; }
inline void Assign(const SmallVector<T, X> &other) { if ((const void *)&other == (void *)this) return; this->Clear(); if (other.Length() > 0) MemCpyT<T>(this->Append(other.Length()), other.Begin(), other.Length()); }
/** * 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(); }
/** * Get a SaveLoad array for a link graph job. The settings struct is derived from * the global settings saveload array. The exact entries are calculated when the function * is called the first time. * It's necessary to keep a copy of the settings for each link graph job so that you can * change the settings while in-game and still not mess with current link graph runs. * Of course the settings have to be saved and loaded, too, to avoid desyncs. * @return Array of SaveLoad structs. */ const SaveLoad *GetLinkGraphJobDesc() { static SmallVector<SaveLoad, 16> saveloads; static const char *prefix = "linkgraph."; /* Build the SaveLoad array on first call and don't touch it later on */ if (saveloads.Length() == 0) { size_t offset_gamesettings = cpp_offsetof(GameSettings, linkgraph); size_t offset_component = cpp_offsetof(LinkGraphJob, settings); size_t prefixlen = strlen(prefix); int setting = 0; const SettingDesc *desc = GetSettingDescription(setting); while (desc->save.cmd != SL_END) { if (desc->desc.name != NULL && strncmp(desc->desc.name, prefix, prefixlen) == 0) { SaveLoad sl = desc->save; char *&address = reinterpret_cast<char *&>(sl.address); address -= offset_gamesettings; address += offset_component; *(saveloads.Append()) = sl; } desc = GetSettingDescription(++setting); } const SaveLoad job_desc[] = { SLE_VAR(LinkGraphJob, join_date, SLE_INT32), SLE_VAR(LinkGraphJob, link_graph.index, SLE_UINT16), SLE_END() }; int i = 0; do { *(saveloads.Append()) = job_desc[i++]; } while (saveloads[saveloads.Length() - 1].cmd != SL_END); } return &saveloads[0]; }
/** * Test if any saved rail type labels are different to the currently loaded * rail types, which therefore requires conversion. * @return true if (and only if) conversion due to rail type changes is needed. */ static bool NeedRailTypeConversion() { for (uint i = 0; i < _railtype_list.Length(); i++) { if ((RailType)i < RAILTYPE_END) { const RailtypeInfo *rti = GetRailTypeInfo((RailType)i); if (rti->label != _railtype_list[i]) return true; } else { if (_railtype_list[i] != 0) return true; } } /* No rail type conversion is necessary */ return false; }
void AfterLoadLabelMaps() { if (NeedRailTypeConversion()) { SmallVector<RailType, RAILTYPE_END> railtype_conversion_map; for (uint i = 0; i < _railtype_list.Length(); i++) { RailType r = GetRailTypeByLabel(_railtype_list[i]); if (r == INVALID_RAILTYPE) r = RAILTYPE_BEGIN; *railtype_conversion_map.Append() = r; } for (TileIndex t = 0; t < MapSize(); t++) { switch (GetTileType(t)) { case MP_RAILWAY: SetRailType(t, railtype_conversion_map[GetRailType(t)]); break; case MP_ROAD: if (IsLevelCrossing(t)) { SetRailType(t, railtype_conversion_map[GetRailType(t)]); } break; case MP_STATION: if (HasStationRail(t)) { SetRailType(t, railtype_conversion_map[GetRailType(t)]); } break; case MP_TUNNELBRIDGE: if (GetTunnelBridgeTransportType(t) == TRANSPORT_RAIL) { SetRailType(t, railtype_conversion_map[GetRailType(t)]); } break; default: break; } } } _railtype_list.Clear(); }
/* 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++; } }
SmallVector(const SmallVector<T, X> &other) : data(NULL), items(0), capacity(0) { MemCpyT<T>(this->Append(other.Length()), other.Begin(), other.Length()); }
uint GetNumSounds() { return _sounds.Length(); }
SoundEntry *GetSound(SoundID index) { if (index >= _sounds.Length()) return NULL; return &_sounds[index]; }
/** * 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); }