Basically y_iterate/foreach iterator is just an array which holds taken indexes of another array (that array is of dynamic size, using y_malloc) (+ helper variable holding count of indexes held). y_iterate has few built-in iterators, and iterator functions.
The most common builtin iterator used is Player. Basically when a new player connects it adds his id this special array (and removes it when he disconnects).
pawn Code:
foreach(new playerid:Player) {
printf("Player %d is currently connected", playerid);
}
You can create your own iterators. In example below I use #define to, well, define the size of the iterator, because I can keep all my defines in one place, and naming a number reduces number of "magic numbers" (too much number in that sentence).
pawn Code:
#define DescriptiveNameOfNumber 20
new Iter:MySpecialIterator<DescriptiveNameOfNumber>;
You just created an iterator with 20 slots. You have to add items to it manually. Say you're loading something from database/ini file/whatever - the code is mainly pseudo-code:
pawn Code:
new MySpecialData[DescriptiveNameOfNumber] = { -1, ... };
MyFunctionLoadingData() {
for(new i = 0; i != rows; ++i) {
MySpecialData[i] = fetch_data_from_source(i);
Iter_Add(MySpecialIterator, i);
}
}
Just like that you can now do:
pawn Code:
foreach(new index:MySpecialIterator) {
printf("My special data at index %d holds", MySpecialData[i]);
}
Neat! There are also 2d-iterators:
pawn Code:
#define MAX_CELLPHONES_PER_PLAYER 2
new Iter:PlayerCellphones[MAX_PLAYERS]<MAX_CELLPHONES_PER_PLAYER>;
Unless you are using
Zeex's compiler (which I guess you don't as you're a beginner), you must initialize it in OnGameModeInit (I can't remember ATM if main is good too, but just to be safe):
pawn Code:
public OnGameModeInit() {
Iter_Init(PlayerCellphones);
}
Now let's say player wants to buy a cellphone, and you want to check if he has an empty slot:
pawn Code:
YCMD:buycell(playerid, params[], help) {
if(Iter_Free(PlayerCellphones[playerid]) == cellmin) SCM(playerid, -1, "Sorry mate, no more cellphones for you!");
}
We use Iter_Free to check if there are empty slots. If not, the function will return cellmin (
this is under discussion, but at the moment of writing that's the value you should use)/
Removing a value is as easy as
pawn Code:
Iter_Remove(YourIterator, index);
There's also Iter_Alloc (add at first free slot), Iter_Random (return random item from an iterator) and Iter_Clear (remove all values).
That's all the basics you need. For those of you more interested, there are some more things:
pawn Code:
new Iterator:PlayerCars<MAX_PLAYERS, MAX_VEHICLES>;
This iterator is used when you're sure that no two players can own the same vehicle - it decreases iterator size from MAX_PLAYERS * MAX_VEHICLES to MAX_PLAYERS + MAX_VEHICLES. For usage, I recommend reading through
YSI unit tests.
There are iterator functions, which are really cool:
pawn Code:
foreach(new playerid:Reverse(Player)) //Reverse the array looping
foreach(new i:Powers(4)) //1, 4, 16, ...
You can write your own custom iterator functions, just look through iterators.inc. I don't exactly remember more than using @iterfunc, but there are live examples so I won't bother.
And of course, there is integration with other YSI libraries (basically just iterator functions, but builtin in other libraries). If you are using y_groups, you should be familiar with Group (now deperecated in favour of GroupMember):
pawn Code:
foreach(new player:GroupMember[MyGroup])
That's it. Reading YSI source (you don't need to know macro voodoo to do so, most of it is really clean code) is the best code reference.
My not-so-good tutorial, there's some code examples, not much changed since then
http://misiur.github.io/2015/03/07/y...how-to-use-it/