Changeset - r28374:799fec80d8df
[Not reviewed]
master
0 6 0
Loïc Guilloux - 4 months ago 2024-01-01 00:07:47
glx22@users.noreply.github.com
Add: [Script] Optional filter parameter to ScriptVehicleList constructor (#11663)
6 files changed with 108 insertions and 2 deletions:
0 comments (0 inline, 0 general)
regression/regression/main.nut
Show inline comments
 
@@ -1814,10 +1814,17 @@ function Regression::Vehicle()
 
	print("    GetLastErrorString():  " + AIError.GetLastErrorString());
 

	
 
	local list = AIVehicleList();
 
	local in_depot = AIVehicleList(AIVehicle.IsInDepot);
 
	local IsType = function(vehicle_id, type) {
 
		return AIVehicle.GetVehicleType(vehicle_id) == type;
 
	}
 
	local rv_list = AIVehicleList(IsType, AIVehicle.VT_ROAD);
 

	
 
	print("");
 
	print("--VehicleList--");
 
	print("  Count():             " + list.Count());
 
	print("  InDepot Count():     " + in_depot.Count());
 
	print("  RoadVehicle Count(): " + rv_list.Count());
 
	list.Valuate(AIVehicle.GetLocation);
 
	print("  Location ListDump:");
 
	for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
regression/regression/result.txt
Show inline comments
 
@@ -9391,6 +9391,8 @@ ERROR: IsEnd() is invalid as Begin() is 
 

	
 
--VehicleList--
 
  Count():             5
 
  InDepot Count():     4
 
  RoadVehicle Count(): 2
 
  Location ListDump:
 
    13 => 33417
 
    12 => 33417
src/script/api/ai_changelog.hpp
Show inline comments
 
@@ -24,6 +24,9 @@
 
 * API removals:
 
 * \li AIError::ERR_PRECONDITION_TOO_MANY_PARAMETERS, that error is never returned anymore.
 
 *
 
 * Other changes:
 
 * \li AIVehicleList accepts an optional filter function
 
 *
 
 * \b 13.0
 
 *
 
 * API additions:
src/script/api/game_changelog.hpp
Show inline comments
 
@@ -84,6 +84,9 @@
 
 * API removals:
 
 * \li GSError::ERR_PRECONDITION_TOO_MANY_PARAMETERS, that error is never returned anymore.
 
 *
 
 * Other changes:
 
 * \li GSVehicleList accepts an optional filter function
 
 *
 
 * \b 13.0
 
 *
 
 * API additions:
src/script/api/script_vehiclelist.cpp
Show inline comments
 
@@ -18,12 +18,78 @@
 

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

	
 
ScriptVehicleList::ScriptVehicleList()
 
ScriptVehicleList::ScriptVehicleList(HSQUIRRELVM vm)
 
{
 
	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);
 

	
 
	for (const Vehicle *v : Vehicle::Iterate()) {
 
		if ((v->owner == ScriptObject::GetCompany() || ScriptCompanyMode::IsDeity()) && (v->IsPrimaryVehicle() || (v->type == VEH_TRAIN && ::Train::From(v)->IsFreeWagon()))) this->AddItem(v->index);
 
		if (v->owner != ScriptObject::GetCompany() && !ScriptCompanyMode::IsDeity()) 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");
 
		}
 

	
 
		/* 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)
src/script/api/script_vehiclelist.hpp
Show inline comments
 
@@ -20,7 +20,32 @@
 
 */
 
class ScriptVehicleList : public ScriptList {
 
public:
 
#ifdef DOXYGEN_API
 
	ScriptVehicleList();
 

	
 
	/**
 
	 * 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:
 
	 *  ScriptVehicleList(ScriptVehicle.IsInDepot);
 
	 *  function IsType(vehicle_id, type)
 
	 *  {
 
	 *    return ScriptVehicle.GetVehicleType(vehicle_id) == type;
 
	 *  }
 
	 *  ScriptVehicleList(IsType, ScriptVehicle.VT_ROAD);
 
	 */
 
	ScriptVehicleList(void *filter_function, int params, ...);
 
#else
 
	/**
 
	 * The constructor wrapper from Squirrel.
 
	 */
 
	ScriptVehicleList(HSQUIRRELVM vm);
 
#endif
 
};
 

	
 
/**
0 comments (0 inline, 0 general)