Example #1
0
/**
 * 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();
}
Example #2
0
NetworkHTTPSocketHandler::NetworkHTTPSocketHandler(SOCKET s,
		HTTPCallback *callback, const char *host, const char *url,
		const char *data, int depth) :
	NetworkSocketHandler(),
	recv_pos(0),
	recv_length(0),
	callback(callback),
	data(data),
	redirect_depth(depth),
	sock(s)
{
	size_t bufferSize = strlen(url) + strlen(host) + strlen(_openttd_revision) + (data == NULL ? 0 : strlen(data)) + 128;
	char *buffer = AllocaM(char, bufferSize);

	DEBUG(net, 7, "[tcp/http] requesting %s%s", host, url);
	if (data != NULL) {
		seprintf(buffer, buffer + bufferSize - 1, "POST %s HTTP/1.0\r\nHost: %s\r\nUser-Agent: OpenTTD/%s\r\nContent-Type: text/plain\r\nContent-Length: %d\r\n\r\n%s\r\n", url, host, _openttd_revision, (int)strlen(data), data);
	} else {
		seprintf(buffer, buffer + bufferSize - 1, "GET %s HTTP/1.0\r\nHost: %s\r\nUser-Agent: OpenTTD/%s\r\n\r\n", url, host, _openttd_revision);
	}

	ssize_t size = strlen(buffer);
	ssize_t res = send(this->sock, (const char*)buffer, size, 0);
	if (res != size) {
		/* Sending all data failed. Socket can't handle this little bit
		 * of information? Just fall back to the old system! */
		this->callback->OnFailure();
		delete this;
	}

	*_http_connections.Append() = this;
}
Example #3
0
/* 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;
}
Example #4
0
	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;
	}
Example #5
0
/**
 * Create a new connecter for the given address
 * @param address the (un)resolved address to connect to
 */
TCPConnecter::TCPConnecter(const NetworkAddress &address) :
	connected(false),
	aborted(false),
	killed(false),
	sock(INVALID_SOCKET),
	address(address)
{
	*_tcp_connecters.Append() = this;
	if (!ThreadObject::New(TCPConnecter::ThreadEntry, this, &this->thread)) {
		this->Connect();
	}
}
static void Load_RAIL()
{
	_railtype_list.Clear();

	LabelObject lo;
	int index;

	while ((index = SlIterateArray()) != -1) {
		SlObject(&lo, _label_object_desc);
		*_railtype_list.Append() = (RailTypeLabel)lo.label;
	}
}
Example #7
0
/**
 * 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];
}
Example #8
0
static void Load_WAYP()
{
	/* Precaution for when loading failed and it didn't get cleared */
	_old_waypoints.Clear();

	int index;

	while ((index = SlIterateArray()) != -1) {
		OldWaypoint *wp = _old_waypoints.Append();
		memset(wp, 0, sizeof(*wp));

		wp->index = index;
		SlObject(wp, _old_waypoint_desc);
	}
}
/**
 * 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;
}
/* Allocate a new Sound */
SoundEntry *AllocateSound()
{
	SoundEntry *sound = _sounds.Append();
	MemSetT(sound, 0);
	return sound;
}
Example #11
0
/**
 * 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);
}