/****************************************************************************************************
* *
* FoX Foreach *
* *
* Copyright © 2016 Abyss Morgan. All rights reserved. *
* *
* Download: https://github.com/AbyssMorgan/SA-MP/tree/master/include/SAM *
* *
* Plugins: None *
* Modules: None *
* *
* File Version: 1.2.1 *
* SA:MP Version: 0.3.7 *
* *
* Functions: *
* FoxForeach(variable,tag); //Tags: Player, Bot, Character *
* *
* Player Functions: *
* CountFoxPlayer(); *
* FoxForeachRandomPlayer(); *
* bool:IsPlayerInFoxPool(playerid); *
* *
* Bot Functions: *
* CountFoxBot(); *
* FoxForeachRandomBot(); *
* bool:IsBotInFoxPool(playerid); *
* *
* Character Functions: *
* CountFoxCharacter(); *
* FoxForeachRandomCharacter(); *
* bool:IsCharacterInFoxPool(playerid); *
* *
* Extended functions: *
* foX(variable,beginning,end); *
* foreach(variable); *
* *
* Auto functions: *
* FoxForeachInit(); *
* bool:FoxAddPlayer(playerid); *
* bool:FoxRemovePlayer(playerid); *
* bool:FoxAddBot(playerid); *
* bool:FoxRemoveBot(playerid); *
* bool:FoxAddCharacter(playerid); *
* bool:FoxRemoveCharacter(playerid); *
* *
****************************************************************************************************/
foreach(new i : Player){
SendClientMessage(i,0xFFFFFFFF,"Hello players!");
}
foreach(new i : Bot){
SendClientMessage(i,0xFFFFFFFF,"Hello bot!");
}
foreach(new i : Character){
SendClientMessage(i,0xFFFFFFFF,"Hello all!");
}
FoxForeach(i,Player){
SendClientMessage(i,0xFFFFFFFF,"Hello players!");
}
FoxForeach(i,Bot){
SendClientMessage(i,0xFFFFFFFF,"Hello bots!");
}
FoxForeach(i,Character){
SendClientMessage(i,0xFFFFFFFF,"Hello all!");
}
Differences between foreach.inc and FoxForeach.inc |
The difference presented here is totally untrue. Foreach counts in the connected one or more of registered entries. So yea, every player in a foreach loop is connected, that's what makes the difference in foreach and GetPlayerPoolSize.
|
Don't use SendClientMessage inside the command. It invalidates the speed test.
Here is the reason. Let's say ZCMD takes 10ms to process a command in OnPlayerCommandText and iZCMD takes 5ms to do the same. An empty command takes 1ms to execute and a command with one SendClientMessage takes 20ms. Now when you do the speed tests, you will find ZCMD to take 30ms and iZCMD to take 25ms. Now you obviously will say they are almost the same even though iZCMD processes commands twice as fast as ZCMD. |
native SLE_algo_foreach_list_init(list:listid, &val); native SLE_algo_foreach_list_get(feid); #define foreach::list(%0(%1)) for(new %1, fel_%0@%1_id = SLE_algo_foreach_list_init(%0, %1); SLE_algo_foreach_list_get(fel_%0@%1_id);)
class ForeachList { public: ForeachList(AMX * amx, cell * counter, std::list<cell>::const_iterator itr, std::list<cell>::const_iterator end) : amx(amx), counter(counter), itr(itr), end(end) {} . . . . inline cell iterate() { bool cond = itr != end; if (cond) { *counter = *itr++; } return cond; } AMX * amx; cell * counter; std::list<cell>::const_iterator itr; std::list<cell>::const_iterator end; }; cell AMX_NATIVE_CALL SLE_algo_foreach_list_init(AMX* amx, cell* params) { unsigned int id = -1; if (IsValidListID(static_cast<int>(params[1]))) { cell* addr = NULL; amx_GetAddr(amx, params[2], &addr); if (unused_foreach_list_ids.size()) { id = unused_foreach_list_ids.back(); unused_foreach_list_ids.pop_back(); } else { id = foreach_list_loop_maxid = active_foreach_list_loops.size(); active_foreach_list_loops.push_back(nullptr); } active_foreach_list_loops[id] = new ForeachList(amx, addr, active_lists[static_cast<int>(params[1])]->container->cbegin(), active_lists[static_cast<int>(params[1])]->container->cend()); } return id; } cell AMX_NATIVE_CALL SLE_algo_foreach_list_get(AMX* amx, cell* params) { // Assuming that people don't try to screw with these internal functions // As long as the foreach define makes this call, it shall always be valid. // TO:CHECK If iterator remains valid when nodes are removed/added to the list while the foreach is running int foreachid = static_cast<int>(params[1]); if (foreachid > static_cast<int>(foreach_list_loop_maxid) || foreachid < 0) return 0; return active_foreach_list_loops[foreachid]->iterate(); }
Your speed test is flawed.
All the foreach includes are going to have the same speed while looping since they use the same idea. The only faster foreach can be made using native calls to plugin. Код:
native SLE_algo_foreach_list_init(list:listid, &val); native SLE_algo_foreach_list_get(feid); #define foreach::list(%0(%1)) for(new %1, fel_%0@%1_id = SLE_algo_foreach_list_init(%0, %1); SLE_algo_foreach_list_get(fel_%0@%1_id);) Код:
class ForeachList { public: ForeachList(AMX * amx, cell * counter, std::list<cell>::const_iterator itr, std::list<cell>::const_iterator end) : amx(amx), counter(counter), itr(itr), end(end) {} . . . . inline cell iterate() { bool cond = itr != end; if (cond) { *counter = *itr++; } return cond; } AMX * amx; cell * counter; std::list<cell>::const_iterator itr; std::list<cell>::const_iterator end; }; cell AMX_NATIVE_CALL SLE_algo_foreach_list_init(AMX* amx, cell* params) { unsigned int id = -1; if (IsValidListID(static_cast<int>(params[1]))) { cell* addr = NULL; amx_GetAddr(amx, params[2], &addr); if (unused_foreach_list_ids.size()) { id = unused_foreach_list_ids.back(); unused_foreach_list_ids.pop_back(); } else { id = foreach_list_loop_maxid = active_foreach_list_loops.size(); active_foreach_list_loops.push_back(nullptr); } active_foreach_list_loops[id] = new ForeachList(amx, addr, active_lists[static_cast<int>(params[1])]->container->cbegin(), active_lists[static_cast<int>(params[1])]->container->cend()); } return id; } cell AMX_NATIVE_CALL SLE_algo_foreach_list_get(AMX* amx, cell* params) { // Assuming that people don't try to screw with these internal functions // As long as the foreach define makes this call, it shall always be valid. // TO:CHECK If iterator remains valid when nodes are removed/added to the list while the foreach is running int foreachid = static_cast<int>(params[1]); if (foreachid > static_cast<int>(foreach_list_loop_maxid) || foreachid < 0) return 0; return active_foreach_list_loops[foreachid]->iterate(); } This idea wont work in PAWN because you are going to de-reference an array after calling the function which is slow whereas in my case the hard work was done by the plugin and you know that plugin can do things amazingly fast. Areas where you can look for improvements are:
|