Changeset - r28420:d7244101c0d9
[Not reviewed]
src/3rdparty/squirrel/include/squirrel.h
Show inline comments
 
@@ -361,6 +361,15 @@ void sq_setdebughook(HSQUIRRELVM v);
 
#define sq_isweakref(o) ((o)._type==OT_WEAKREF)
 
#define sq_type(o) ((o)._type)
 

	
 
/* Limit the total number of ops that can be consumed by an operation */
 
struct SQOpsLimiter {
 
	SQOpsLimiter(HSQUIRRELVM v, SQInteger ops, const char *label);
 
	~SQOpsLimiter();
 
private:
 
	HSQUIRRELVM _v;
 
	SQInteger _ops;
 
};
 

	
 
/* deprecated */
 
#define sq_createslot(v,n) sq_newslot(v,n,SQFalse)
 

	
src/3rdparty/squirrel/squirrel/sqapi.cpp
Show inline comments
 
@@ -1323,3 +1323,16 @@ void sq_free(void *p,SQUnsignedInteger s
 
	SQ_FREE(p,size);
 
}
 

	
 
SQOpsLimiter::SQOpsLimiter(HSQUIRRELVM v, SQInteger ops, const char *label) : _v(v)
 
{
 
	this->_ops = v->_ops_till_suspend_error_threshold;
 
	if (this->_ops == INT64_MIN) {
 
		v->_ops_till_suspend_error_threshold = v->_ops_till_suspend - ops;
 
		v->_ops_till_suspend_error_label = label;
 
	}
 
}
 

	
 
SQOpsLimiter::~SQOpsLimiter()
 
{
 
	this->_v->_ops_till_suspend_error_threshold = this->_ops;
 
}
src/script/api/ai_changelog.hpp
Show inline comments
 
@@ -25,6 +25,11 @@
 
 * \li AIError::ERR_PRECONDITION_TOO_MANY_PARAMETERS, that error is never returned anymore.
 
 *
 
 * Other changes:
 
 * \li AIGroupList accepts an optional filter function
 
 * \li AIIndustryList accepts an optional filter function
 
 * \li AISignList accepts an optional filter function
 
 * \li AISubsidyList accepts an optional filter function
 
 * \li AITownList accepts an optional filter function
 
 * \li AIVehicleList accepts an optional filter function
 
 *
 
 * \b 13.0
src/script/api/game_changelog.hpp
Show inline comments
 
@@ -85,6 +85,11 @@
 
 * \li GSError::ERR_PRECONDITION_TOO_MANY_PARAMETERS, that error is never returned anymore.
 
 *
 
 * Other changes:
 
 * \li GSGroupList accepts an optional filter function
 
 * \li GSIndustryList accepts an optional filter function
 
 * \li GSSignList accepts an optional filter function
 
 * \li GSSubsidyList accepts an optional filter function
 
 * \li GSTownList accepts an optional filter function
 
 * \li GSVehicleList accepts an optional filter function
 
 *
 
 * \b 13.0
src/script/api/script_grouplist.cpp
Show inline comments
 
@@ -14,11 +14,11 @@
 

	
 
#include "../../safeguards.h"
 

	
 
ScriptGroupList::ScriptGroupList()
 
ScriptGroupList::ScriptGroupList(HSQUIRRELVM vm)
 
{
 
	EnforceCompanyModeValid_Void();
 
	CompanyID owner = ScriptObject::GetCompany();
 
	for (const Group *g : Group::Iterate()) {
 
		if (g->owner == owner) this->AddItem(g->index);
 
	}
 
	ScriptList::FillList<Group>(vm, this,
 
		[owner](const Group *g) { return g->owner == owner; }
 
	);
 
}
src/script/api/script_grouplist.hpp
Show inline comments
 
@@ -20,10 +20,35 @@
 
 */
 
class ScriptGroupList : public ScriptList {
 
public:
 
#ifdef DOXYGEN_API
 
	/**
 
	 * @game @pre ScriptCompanyMode::IsValid().
 
	 */
 
	ScriptGroupList();
 

	
 
	/**
 
	 * Apply a filter when building the list.
 
	 * @param filter_function The function which will be doing the filtering.
 
	 * @param params The params to give to the filters (minus the first param,
 
	 *  which is always the index-value).
 
	 * @game @pre ScriptCompanyMode::IsValid().
 
	 * @note You can write your own filters and use them. Just remember that
 
	 *  the first parameter should be the index-value, and it should return
 
	 *  a bool.
 
	 * @note Example:
 
	 *  function IsType(group_id, type)
 
	 *  {
 
	 *    return ScriptGroup.GetVehicleType(group_id) == type;
 
	 *  }
 
	 *  ScriptGroupList(IsType, ScriptVehicle.VT_ROAD);
 
	 */
 
	ScriptGroupList(void *filter_function, int params, ...);
 
#else
 
	/**
 
	 * The constructor wrapper from Squirrel.
 
	 */
 
	ScriptGroupList(HSQUIRRELVM vm);
 
#endif /* DOXYGEN_API */
 
};
 

	
 
#endif /* SCRIPT_GROUPLIST_HPP */
src/script/api/script_industrylist.cpp
Show inline comments
 
@@ -13,23 +13,21 @@
 

	
 
#include "../../safeguards.h"
 

	
 
ScriptIndustryList::ScriptIndustryList()
 
ScriptIndustryList::ScriptIndustryList(HSQUIRRELVM vm)
 
{
 
	for (const Industry *i : Industry::Iterate()) {
 
		this->AddItem(i->index);
 
	}
 
	ScriptList::FillList<Industry>(vm, this);
 
}
 

	
 
ScriptIndustryList_CargoAccepting::ScriptIndustryList_CargoAccepting(CargoID cargo_id)
 
{
 
	for (const Industry *i : Industry::Iterate()) {
 
		if (i->IsCargoAccepted(cargo_id)) this->AddItem(i->index);
 
	}
 
	ScriptList::FillList<Industry>(this,
 
		[cargo_id](const Industry *i) { return i->IsCargoAccepted(cargo_id); }
 
	);
 
}
 

	
 
ScriptIndustryList_CargoProducing::ScriptIndustryList_CargoProducing(CargoID cargo_id)
 
{
 
	for (const Industry *i : Industry::Iterate()) {
 
		if (i->IsCargoProduced(cargo_id)) this->AddItem(i->index);
 
	}
 
	ScriptList::FillList<Industry>(this,
 
		[cargo_id](const Industry *i) { return i->IsCargoProduced(cargo_id); }
 
	);
 
}
src/script/api/script_industrylist.hpp
Show inline comments
 
@@ -19,7 +19,32 @@
 
 */
 
class ScriptIndustryList : public ScriptList {
 
public:
 
#ifdef DOXYGEN_API
 
	ScriptIndustryList();
 

	
 
	/**
 
	 * Apply a filter when building the list.
 
	 * @param filter_function The function which will be doing the filtering.
 
	 * @param params The params to give to the filters (minus the first param,
 
	 *  which is always the index-value).
 
	 * @note You can write your own filters and use them. Just remember that
 
	 *  the first parameter should be the index-value, and it should return
 
	 *  a bool.
 
	 * @note Example:
 
	 *  ScriptIndustryList(ScriptIndustry.HasDock);
 
	 *  function IsType(industry_id, type)
 
	 *  {
 
	 *    return ScriptIndustry.GetIndustryType(industry_id) == type;
 
	 *  }
 
	 *  ScriptIndustryList(IsType, 0);
 
	 */
 
	ScriptIndustryList(void *filter_function, int params, ...);
 
#else
 
	/**
 
	 * The constructor wrapper from Squirrel.
 
	 */
 
	ScriptIndustryList(HSQUIRRELVM vm);
 
#endif /* DOXYGEN_API */
 
};
 

	
 
/**
src/script/api/script_list.cpp
Show inline comments
 
@@ -11,9 +11,7 @@
 
#include "script_list.hpp"
 
#include "script_controller.hpp"
 
#include "../../debug.h"
 
#include "../../core/backup_type.hpp"
 
#include "../../script/squirrel.hpp"
 
#include <../squirrel/sqvm.h>
 

	
 
#include "../../safeguards.h"
 

	
 
@@ -869,12 +867,7 @@ SQInteger ScriptList::Valuate(HSQUIRRELV
 
	ScriptObject::SetAllowDoCommand(false);
 

	
 
	/* Limit the total number of ops that can be consumed by a valuate operation */
 
	SQInteger new_ops_error_threshold = vm->_ops_till_suspend_error_threshold;
 
	if (vm->_ops_till_suspend_error_threshold == INT64_MIN) {
 
		new_ops_error_threshold = vm->_ops_till_suspend - MAX_VALUATE_OPS;
 
		vm->_ops_till_suspend_error_label = "valuator function";
 
	}
 
	AutoRestoreBackup ops_error_threshold_backup(vm->_ops_till_suspend_error_threshold, new_ops_error_threshold);
 
	SQOpsLimiter limiter(vm, MAX_VALUATE_OPS, "valuator function");
 

	
 
	/* Push the function to call */
 
	sq_push(vm, 2);
src/script/api/script_list.hpp
Show inline comments
 
@@ -42,6 +42,107 @@ private:
 
	bool initialized;             ///< Whether an iteration has been started
 
	int modifications;            ///< Number of modification that has been done. To prevent changing data while valuating.
 

	
 
protected:
 
	template<typename T, class ItemValid, class ItemFilter>
 
	static void FillList(ScriptList *list, ItemValid item_valid, ItemFilter item_filter)
 
	{
 
		for (const T *item : T::Iterate()) {
 
			if (!item_valid(item)) continue;
 
			if (!item_filter(item)) continue;
 
			list->AddItem(item->index);
 
		}
 
	}
 

	
 
	template<typename T, class ItemValid>
 
	static void FillList(ScriptList *list, ItemValid item_valid)
 
	{
 
		ScriptList::FillList<T>(list, item_valid, [](const T *) { return true; });
 
	}
 

	
 
	template<typename T>
 
	static void FillList(ScriptList *list)
 
	{
 
		ScriptList::FillList<T>(list, [](const T *) { return true; });
 
	}
 

	
 
	template<typename T, class ItemValid>
 
	static void FillList(HSQUIRRELVM vm, ScriptList *list, ItemValid item_valid)
 
	{
 
		int nparam = sq_gettop(vm) - 1;
 
		if (nparam >= 1) {
 
			/* Make sure the filter function is really a function, and not any
 
			 * other type. It's parameter 2 for us, but for the user it's the
 
			 * first parameter they give. */
 
			SQObjectType valuator_type = sq_gettype(vm, 2);
 
			if (valuator_type != OT_CLOSURE && valuator_type != OT_NATIVECLOSURE) {
 
				throw sq_throwerror(vm, "parameter 1 has an invalid type (expected function)");
 
			}
 

	
 
			/* Push the function to call */
 
			sq_push(vm, 2);
 
		}
 

	
 
		/* Don't allow docommand from a Valuator, as we can't resume in
 
		 * mid C++-code. */
 
		bool backup_allow = ScriptObject::GetAllowDoCommand();
 
		ScriptObject::SetAllowDoCommand(false);
 

	
 

	
 
		if (nparam < 1) {
 
			ScriptList::FillList<T>(list, item_valid);
 
		} else {
 
			/* Limit the total number of ops that can be consumed by a filter operation, if a filter function is present */
 
			SQOpsLimiter limiter(vm, MAX_VALUATE_OPS, "list filter function");
 

	
 
			ScriptList::FillList<T>(list, item_valid,
 
				[vm, nparam, backup_allow](const T *item) {
 
					/* Push the root table as instance object, this is what squirrel does for meta-functions. */
 
					sq_pushroottable(vm);
 
					/* Push all arguments for the valuator function. */
 
					sq_pushinteger(vm, item->index);
 
					for (int i = 0; i < nparam - 1; i++) {
 
						sq_push(vm, i + 3);
 
					}
 

	
 
					/* Call the function. Squirrel pops all parameters and pushes the return value. */
 
					if (SQ_FAILED(sq_call(vm, nparam + 1, SQTrue, SQTrue))) {
 
						ScriptObject::SetAllowDoCommand(backup_allow);
 
						throw sq_throwerror(vm, "failed to run filter");
 
					}
 

	
 
					SQBool add = SQFalse;
 

	
 
					/* Retrieve the return value */
 
					switch (sq_gettype(vm, -1)) {
 
						case OT_BOOL:
 
							sq_getbool(vm, -1, &add);
 
							break;
 

	
 
						default:
 
							ScriptObject::SetAllowDoCommand(backup_allow);
 
							throw sq_throwerror(vm, "return value of filter is not valid (not bool)");
 
					}
 

	
 
					/* Pop the return value. */
 
					sq_poptop(vm);
 

	
 
					return add;
 
				}
 
			);
 

	
 
			/* Pop the filter function */
 
			sq_poptop(vm);
 
		}
 

	
 
		ScriptObject::SetAllowDoCommand(backup_allow);
 
	}
 

	
 
	template<typename T>
 
	static void FillList(HSQUIRRELVM vm, ScriptList *list)
 
	{
 
		ScriptList::FillList<T>(vm, list, [](const T *) { return true; });
 
	}
 

	
 
public:
 
	typedef std::set<SQInteger> ScriptItemList;                   ///< The list of items inside the bucket
 
	typedef std::map<SQInteger, ScriptItemList> ScriptListBucket; ///< The bucket list per value
src/script/api/script_signlist.cpp
Show inline comments
 
@@ -14,9 +14,9 @@
 

	
 
#include "../../safeguards.h"
 

	
 
ScriptSignList::ScriptSignList()
 
ScriptSignList::ScriptSignList(HSQUIRRELVM vm)
 
{
 
	for (const Sign *s : Sign::Iterate()) {
 
		if (ScriptSign::IsValidSign(s->index)) this->AddItem(s->index);
 
	}
 
	ScriptList::FillList<Sign>(vm, this,
 
		[](const Sign *s) { return ScriptSign::IsValidSign(s->index); }
 
	);
 
}
src/script/api/script_signlist.hpp
Show inline comments
 
@@ -19,7 +19,29 @@
 
 */
 
class ScriptSignList : public ScriptList {
 
public:
 
#ifdef DOXYGEN_API
 
	ScriptSignList();
 

	
 
	/**
 
	 * Apply a filter when building the list.
 
	 * @param filter_function The function which will be doing the filtering.
 
	 * @param params The params to give to the filters (minus the first param,
 
	 *  which is always the index-value).
 
	 * @note You can write your own filters and use them. Just remember that
 
	 *  the first parameter should be the index-value, and it should return
 
	 *  a bool.
 
	 * @note Example:
 
	 *  function Contains(sign_id, str)
 
	 *  {
 
	 *    local name = ScriptSign.GetName(sign_id);
 
	 *    return name != null && name.find(str) != null;
 
	 *  }
 
	 *  ScriptSignList(Contains, "something");
 
	 */
 
	ScriptSignList(void *filter_function, int params, ...);
 
#else
 
	ScriptSignList(HSQUIRRELVM);
 
#endif /* DOXYGEN_API */
 
};
 

	
 
#endif /* SCRIPT_SIGNLIST_HPP */
src/script/api/script_subsidylist.cpp
Show inline comments
 
@@ -13,9 +13,7 @@
 

	
 
#include "../../safeguards.h"
 

	
 
ScriptSubsidyList::ScriptSubsidyList()
 
ScriptSubsidyList::ScriptSubsidyList(HSQUIRRELVM vm)
 
{
 
	for (const Subsidy *s : Subsidy::Iterate()) {
 
		this->AddItem(s->index);
 
	}
 
	ScriptList::FillList<Subsidy>(vm, this);
 
}
src/script/api/script_subsidylist.hpp
Show inline comments
 
@@ -19,7 +19,28 @@
 
 */
 
class ScriptSubsidyList : public ScriptList {
 
public:
 
#ifdef DOXYGEN_API
 
	ScriptSubsidyList();
 

	
 
	/**
 
	 * Apply a filter when building the list.
 
	 * @param filter_function The function which will be doing the filtering.
 
	 * @param params The params to give to the filters (minus the first param,
 
	 *  which is always the index-value).
 
	 * @note You can write your own filters and use them. Just remember that
 
	 *  the first parameter should be the index-value, and it should return
 
	 *  a bool.
 
	 * @note Example:
 
	 *  function IsType(subsidy_id, type)
 
	 *  {
 
	 *    return ScriptSubsidy.GetSourceType(subsidy_id) == type;
 
	 *  }
 
	 *  ScriptSubsidyList(IsType, ScriptSubsidy.SPT_TOWN);
 
	 */
 
	ScriptSubsidyList(void *filter_function, int params, ...);
 
#else
 
	ScriptSubsidyList(HSQUIRRELVM vm);
 
#endif /* DOXYGEN_API */
 
};
 

	
 
#endif /* SCRIPT_SUBSIDYLIST_HPP */
src/script/api/script_townlist.cpp
Show inline comments
 
@@ -13,11 +13,9 @@
 

	
 
#include "../../safeguards.h"
 

	
 
ScriptTownList::ScriptTownList()
 
ScriptTownList::ScriptTownList(HSQUIRRELVM vm)
 
{
 
	for (const Town *t : Town::Iterate()) {
 
		this->AddItem(t->index);
 
	}
 
	ScriptList::FillList<Town>(vm, this);
 
}
 

	
 
ScriptTownEffectList::ScriptTownEffectList()
src/script/api/script_townlist.hpp
Show inline comments
 
@@ -19,7 +19,29 @@
 
 */
 
class ScriptTownList : public ScriptList {
 
public:
 
#ifdef DOXYGEN_API
 
	ScriptTownList();
 

	
 
	/**
 
	 * Apply a filter when building the list.
 
	 * @param filter_function The function which will be doing the filtering.
 
	 * @param params The params to give to the filters (minus the first param,
 
	 *  which is always the index-value).
 
	 * @note You can write your own filters and use them. Just remember that
 
	 *  the first parameter should be the index-value, and it should return
 
	 *  a bool.
 
	 * @note Example:
 
	 *  ScriptTownList(ScriptTown.IsActionAvailable, ScriptTown.TOWN_ACTION_BRIBE);
 
	 *  function MinPopulation(town_id, pop)
 
	 *  {
 
	 *    return ScriptTown.GetPopulation(town_id) >= pop;
 
	 *  }
 
	 *  ScriptTownList(MinPopulation, 1000);
 
	 */
 
	ScriptTownList(void *filter_function, int params, ...);
 
#else
 
	ScriptTownList(HSQUIRRELVM vm);
 
#endif /* DOXYGEN_API */
 
};
 

	
 
/**
src/script/api/script_vehiclelist.cpp
Show inline comments
 
@@ -16,8 +16,6 @@
 
#include "../../vehicle_base.h"
 
#include "../../vehiclelist_func.h"
 
#include "../../train.h"
 
#include "../../core/backup_type.hpp"
 
#include <../squirrel/sqvm.h>
 

	
 
#include "../../safeguards.h"
 

	
 
@@ -25,84 +23,14 @@ ScriptVehicleList::ScriptVehicleList(HSQ
 
{
 
	EnforceDeityOrCompanyModeValid_Void();
 

	
 
	int nparam = sq_gettop(vm) - 1;
 
	if (nparam >= 1) {
 
		/* Make sure the filter function is really a function, and not any
 
		 * other type. It's parameter 2 for us, but for the user it's the
 
		 * first parameter they give. */
 
		SQObjectType valuator_type = sq_gettype(vm, 2);
 
		if (valuator_type != OT_CLOSURE && valuator_type != OT_NATIVECLOSURE) {
 
			throw sq_throwerror(vm, "parameter 1 has an invalid type (expected function)");
 
		}
 

	
 
		/* Push the function to call */
 
		sq_push(vm, 2);
 
	}
 

	
 
	/* Don't allow docommand from a Valuator, as we can't resume in
 
	 * mid C++-code. */
 
	bool backup_allow = ScriptObject::GetAllowDoCommand();
 
	ScriptObject::SetAllowDoCommand(false);
 

	
 
	/* Limit the total number of ops that can be consumed by a filter operation, if a filter function is present */
 
	SQInteger new_ops_error_threshold = vm->_ops_till_suspend_error_threshold;
 
	if (nparam >= 1 && vm->_ops_till_suspend_error_threshold == INT64_MIN) {
 
		new_ops_error_threshold = vm->_ops_till_suspend - MAX_VALUATE_OPS;
 
		vm->_ops_till_suspend_error_label = "vehicle filter function";
 
	}
 
	AutoRestoreBackup ops_error_threshold_backup(vm->_ops_till_suspend_error_threshold, new_ops_error_threshold);
 

	
 
	bool is_deity = ScriptCompanyMode::IsDeity();
 
	CompanyID owner = ScriptObject::GetCompany();
 
	for (const Vehicle *v : Vehicle::Iterate()) {
 
		if (v->owner != owner && !is_deity) continue;
 
		if (!v->IsPrimaryVehicle() && !(v->type == VEH_TRAIN && ::Train::From(v)->IsFreeWagon())) continue;
 

	
 
		if (nparam < 1) {
 
			/* No filter, just add the item. */
 
			this->AddItem(v->index);
 
			continue;
 
		}
 

	
 
		/* Push the root table as instance object, this is what squirrel does for meta-functions. */
 
		sq_pushroottable(vm);
 
		/* Push all arguments for the valuator function. */
 
		sq_pushinteger(vm, v->index);
 
		for (int i = 0; i < nparam - 1; i++) {
 
			sq_push(vm, i + 3);
 
		}
 

	
 
		/* Call the function. Squirrel pops all parameters and pushes the return value. */
 
		if (SQ_FAILED(sq_call(vm, nparam + 1, SQTrue, SQTrue))) {
 
			ScriptObject::SetAllowDoCommand(backup_allow);
 
			throw sq_throwerror(vm, "failed to run filter");
 
	ScriptList::FillList<Vehicle>(vm, this,
 
		[is_deity, owner](const Vehicle *v) {
 
			return (is_deity || v->owner == owner) && (v->IsPrimaryVehicle() || (v->type == VEH_TRAIN && ::Train::From(v)->IsFreeWagon()));
 
		}
 

	
 
		/* Retrieve the return value */
 
		switch (sq_gettype(vm, -1)) {
 
			case OT_BOOL: {
 
				SQBool add;
 
				sq_getbool(vm, -1, &add);
 
				if (add) this->AddItem(v->index);
 
				break;
 
			}
 

	
 
			default: {
 
				ScriptObject::SetAllowDoCommand(backup_allow);
 
				throw sq_throwerror(vm, "return value of filter is not valid (not bool)");
 
			}
 
		}
 

	
 
		/* Pop the return value. */
 
		sq_poptop(vm);
 
	}
 

	
 
	if (nparam >= 1) {
 
		/* Pop the filter function */
 
		sq_poptop(vm);
 
	}
 

	
 
	ScriptObject::SetAllowDoCommand(backup_allow);
 
	);
 
}
 

	
 
ScriptVehicleList_Station::ScriptVehicleList_Station(StationID station_id)
 
@@ -182,11 +110,11 @@ ScriptVehicleList_Group::ScriptVehicleLi
 
	if (!ScriptGroup::IsValidGroup((ScriptGroup::GroupID)group_id)) return;
 

	
 
	CompanyID owner = ScriptObject::GetCompany();
 
	for (const Vehicle *v : Vehicle::Iterate()) {
 
		if (v->owner == owner && v->IsPrimaryVehicle()) {
 
			if (v->group_id == group_id) this->AddItem(v->index);
 
		}
 
	}
 

	
 
	ScriptList::FillList<Vehicle>(this,
 
		[owner](const Vehicle *v) { return v->owner == owner && v->IsPrimaryVehicle(); },
 
		[group_id](const Vehicle *v) { return v->group_id == group_id; }
 
	);
 
}
 

	
 
ScriptVehicleList_DefaultGroup::ScriptVehicleList_DefaultGroup(ScriptVehicle::VehicleType vehicle_type)
 
@@ -195,9 +123,9 @@ ScriptVehicleList_DefaultGroup::ScriptVe
 
	if (vehicle_type < ScriptVehicle::VT_RAIL || vehicle_type > ScriptVehicle::VT_AIR) return;
 

	
 
	CompanyID owner = ScriptObject::GetCompany();
 
	for (const Vehicle *v : Vehicle::Iterate()) {
 
		if (v->owner == owner && v->IsPrimaryVehicle()) {
 
			if (v->type == (::VehicleType)vehicle_type && v->group_id == ScriptGroup::GROUP_DEFAULT) this->AddItem(v->index);
 
		}
 
	}
 

	
 
	ScriptList::FillList<Vehicle>(this,
 
		[owner](const Vehicle *v) { return v->owner == owner && v->IsPrimaryVehicle(); },
 
		[vehicle_type](const Vehicle *v) { return v->type == (::VehicleType)vehicle_type && v->group_id == ScriptGroup::GROUP_DEFAULT; }
 
	);
 
}
0 comments (0 inline, 0 general)