Too long to save

Discuss the new AI features ("NoAI") introduced into OpenTTD 0.7, allowing you to implement custom AIs, and the new Game Scripts available in OpenTTD 1.2 and higher.

Moderator: OpenTTD Developers

Post Reply
Aphid
Traffic Manager
Traffic Manager
Posts: 168
Joined: 16 Dec 2011 17:08

Too long to save

Post by Aphid »

When any script terminates on saving with the error message that it took 'too long' to save, what does this mean specifically?

How long is too long?

Note: you can reproduce this error by saving a large amount of data. (Mine failed to save about 40,000 integers, or about 160 kB).
Yexo
Tycoon
Tycoon
Posts: 3663
Joined: 20 Dec 2007 12:49

Re: Too long to save

Post by Yexo »

It's not about the amount of data you store, but the amount of ticks used in the Save() function. I think the limit is 100k opcodes, but I'm not entirely sure on that. This limit is in place to make sure scripts can't "hang" in the save function. Try to either save less data or make sure the data you want to save is always prepared to your Save() function can be fast.
Aphid
Traffic Manager
Traffic Manager
Posts: 168
Joined: 16 Dec 2011 17:08

Re: Too long to save

Post by Aphid »

I've been experimenting a lot, but how to do it even faster than this?

Code: Select all

	function Scriptname::Save(){return{this};}
Or maybe a way to increase the limit? Does making parts of the data members of classes static (where this can be done) help?
Aphid
Traffic Manager
Traffic Manager
Posts: 168
Joined: 16 Dec 2011 17:08

Re: Too long to save

Post by Aphid »

Even something like

Code: Select all

function ScriptName::Save(return data;)
won't work.

(Where data is a table, already filled with the data/classes to be saved).

Edit: Apparently, I've found the cause of the problem after about a month...

Code: Select all

 return {
x = 0
};
is different from

Code: Select all

 return
{
x = 0
};
I'm unsure what the second statement does, but apparently it always causes a hang.
Yexo
Tycoon
Tycoon
Posts: 3663
Joined: 20 Dec 2007 12:49

Re: Too long to save

Post by Yexo »

My guess is that the second version the line "return" is seen a complete statement, the semicolon at the end is optional in squirrel. This means that the function returns nothing, or "null". What the first case is supposed to do I'm unsure, is that even valid?
Aphid
Traffic Manager
Traffic Manager
Posts: 168
Joined: 16 Dec 2011 17:08

Re: Too long to save

Post by Aphid »

The first returns a table. Syntax for table (size n) is:
my_table = {
entry_1 = var_1
...
entry_n = var_n}
entry_i and var_i can be any variable name of any type.

and you can add stuff with

Code: Select all

 my_table.entryname <- variable
where entryname does not exist in the table yet.
Anywho, I've solved the problem by doing a very cool little trick. I made various variables static, and copied from my classes the bare minimum needed to save. It meant random effects would
be regenned on load and I had to cut a feature here and there, but in theory, it works.

Code: Select all

function CityBuilder::Save()
{
	Log.Info("Saving data", Log.LVL_INFO);
	data = {	sv_mode = mode,
				sv_registered_companies = registered_companies,
				sv_go = go,
				sv_last_date = last_date,
				sv_month =month,
				sv_game_length = game_length,
				sv_start_year = start_year,
				sv_metro_town_id = metro_town_id,
				sv_companies = array(companies.len(), []),
				// these four are heavy!
				sv_town_access = town_access,
				sv_city_access = city_access, 
				sv_towns = array(towns.len(), []),
				sv_cities = array(cities.len(), [])
};
	for(local l = 0; l < companies.len(); ++l)
		{
		data.sv_companies[l].append(companies[l].global_goal_id); // int
		data.sv_companies[l].append(companies[l].tzgt); // array of int
		data.sv_companies[l].append(companies[l].tzgtwns); //array of int
		data.sv_companies[l].append(companies[l].id); // int
		data.sv_companies[l].append(companies[l].my_town); // weak reference to reference of object of type 'Town', stored as int.
		data.sv_companies[l].append(companies[l].gametype); // int
		data.sv_companies[l].append(companies[l].score);  // int
		data.sv_companies[l].append(companies[l].score_quarter); // int
		data.sv_companies[l].append(companies[l].hq); // TileIndex (int)
		}
	for(local l = 0; l < towns.len(); ++l)
		{		
		if(typeof towns[l] == "Town"){
		data.sv_towns[l].append(towns[l].id); // int
		data.sv_towns[l].append(towns[l].start_population); // int
		data.sv_towns[l].append(towns[l].supply_cargo); // array of int
		data.sv_towns[l].append(towns[l].stocked_cargo); // array of int
		data.sv_towns[l].append(towns[l].company); // CompanyID (int)
		data.sv_towns[l].append(towns[l].metro); // bool
		data.sv_towns[l].append(towns[l].num_signs); // int
		data.sv_towns[l].append(towns[l].cargo_signs); // array of SignID(int)
		data.sv_towns[l].append(towns[l].basicsign); // SignID(int)
		data.sv_towns[l].append(towns[l].muncipalities); // array of TownID(int)
		data.sv_towns[l].append(towns[l].ismuncipality);} // bool
		}
	for(local l = 0; l < cities.len(); ++l)
		{
		if(typeof cities[l] == "City"){
		data.sv_cities[l].append(cities[l].id); // int
		data.sv_cities[l].append(cities[l].mult); // float
		data.sv_cities[l].append(cities[l].sign_id); // SignID (int)
			}
		}
	return data;
}
Notice the typeof checks, some elements in the array can be 'null'.

EDIT: This code doesn't work because of the single float element. This means I need to somehow save this data differently. How is the question.
Post Reply

Return to “OpenTTD AIs and Game Scripts”

Who is online

Users browsing this forum: No registered users and 9 guests