y_iterate.inc 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. /**--------------------------------------------------------------------------**\
  2. ===========================
  3. foreach efficient looping
  4. ===========================
  5. Description:
  6. Provides efficient looping through sparse data sets, such as connected
  7. players. Significantly improved from the original version to be a generic
  8. loop system, rather then purely a player loop system. When used for
  9. players this has constant time O(n) for number of connected players (n),
  10. unlike standard player loops which are O(MAX_PLAYERS), regardless of the
  11. actual number of connected players. Even when n is MAX_PLAYERS this is
  12. still faster.
  13. For extensive documentation on writing and using iterators, see this topic:
  14. http://forum.sa-mp.com/showthread.php?t=481877
  15. Legal:
  16. Version: MPL 1.1
  17. The contents of this file are subject to the Mozilla Public License Version
  18. 1.1 (the "License"); you may not use this file except in compliance with
  19. the License. You may obtain a copy of the License at
  20. [url]http://www.mozilla.org/MPL/[/url]
  21. Software distributed under the License is distributed on an "AS IS" basis,
  22. WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  23. for the specific language governing rights and limitations under the
  24. License.
  25. The Original Code is the YSI foreach include.
  26. The Initial Developer of the Original Code is Alex "Y_Less" Cole.
  27. Portions created by the Initial Developer are Copyright (C) 2011
  28. the Initial Developer. All Rights Reserved.
  29. Contributors:
  30. ZeeX, koolk, JoeBullet/Google63, g_aSlice/Slice
  31. Thanks:
  32. JoeBullet/Google63 - Handy arbitrary ASM jump code using SCTRL.
  33. ZeeX - Very productive conversations.
  34. koolk - IsPlayerinAreaEx code.
  35. TheAlpha - Danish translation.
  36. breadfish - German translation.
  37. Fireburn - Dutch translation.
  38. yom - French translation.
  39. 50p - Polish translation.
  40. Zamaroht - Spanish translation.
  41. Dracoblue, sintax, mabako, Xtreme, other coders - Producing other modes
  42. for me to strive to better.
  43. Pixels^ - Running XScripters where the idea was born.
  44. Matite - Pestering me to release it and using it.
  45. Very special thanks to:
  46. Thiadmer - PAWN, whose limits continue to amaze me!
  47. Kye/Kalcor - SA:MP.
  48. SA:MP Team past, present and future - SA:MP.
  49. Version:
  50. 0.4
  51. Changelog:
  52. 29/03/15:
  53. More testing.
  54. Repaired special iterators.
  55. 28/03/15:
  56. Breaking change: "Iter_Add" returns value added, not true/false.
  57. Breaking change: Special iterators take "cellmin", not "-1".
  58. Wrote many tests.
  59. Split in to multiple files.
  60. Added multi-iterators.
  61. Officially deprecated "foreach (Player, i)".
  62. 26/03/15:
  63. Re-added reverse iterators.
  64. Added support for extra spaces in "foreach".
  65. 26/12/13:
  66. Added sections.
  67. 17/10/12:
  68. Fixed a bug that was here but not in "foreach.inc".
  69. 04/10/12:
  70. Added a tiny tweak to detect tag-returning iterator functions.
  71. Added Iter_InternalSize.
  72. 13/01/12:
  73. Fixed the count thanks to AndreT.
  74. 05/01/12:
  75. Fixed multi-dimensional iterators.
  76. Fixed "FOREACH_NO_BOTS".
  77. Made "Iterator:" support multi-dimensional arrays.
  78. 24/12/11:
  79. Added _YSI_SPECIAL_DEBUG support.
  80. Added fix for function iterators.
  81. Ported back to YSI.
  82. Changed to use internal YSI "__" natives.
  83. Fixed calls order by using ALS.
  84. 31/10/11:
  85. Changed the underlying loop code to be slightly faster.
  86. Added support for Iter_SafeRemove, prompting refactoring.
  87. 17/09/11:
  88. Fixed arrays under the new syntax.
  89. 28/04/11:
  90. Moved iterator identifiers to end of variables.
  91. Rewrote "foreach" to accept two syntaxes for "foreach (new i : Iter)".
  92. 16/08/10:
  93. Removed all the "2" versions of the functions.
  94. 14/08/10:
  95. Added Iter_Clear to reset an array.
  96. 06/08/10:
  97. Added special array declaration format.
  98. 18/12/09:
  99. Added Iter_Func2 functions for multi-dimensional iterators.
  100. Renamed foreact et al as keywords in the documentation.
  101. Changed licensing from GPL to MPL.
  102. 02/09/09:
  103. Fixed (again) for 0.3.
  104. Added free slot finding.
  105. 21/08/09:
  106. Updated to include random functions.
  107. Made entirely stand alone.
  108. Ported to 0.3 (separate version).
  109. Added automatic callback hook code.
  110. Removed debug information from stand alone version.
  111. 06/01/08:
  112. Added debug information.
  113. 09/10/07:
  114. Moved to system.
  115. 16/09/07:
  116. Added list sorting.
  117. Made this part of Y SeRver Includes, not Y Sever Includes.
  118. Made list sorting optional.
  119. Fixed version number.
  120. 08/09/07:
  121. First version.
  122. Functions:
  123. Public:
  124. OnPlayerDisconnect - Called when a player leaves to remove them.
  125. OnPlayerConnect - Called when a player connects to add them.
  126. Core:
  127. -
  128. Stock:
  129. Iter_ShowArray - Displays the contents of the array.
  130. Iter_AddInternal - Add a value to an iterator.
  131. Iter_RemoveInternal - Remove a value from an iterator.
  132. Iter_RandomInternal - Get a random item from an iterator.
  133. Iter_FreeInternal - Gets the first free slot in the iterator.
  134. Iter_InitInternal - Initialises a multi-dimensional iterator.
  135. Static:
  136. -
  137. Inline:
  138. Iter_Create - Create a new iterator value set.
  139. Iter_Add - Wraps Iter_AddInternal.
  140. Iter_Remove - Wraps Iter_RemoveInternal.
  141. Iter_Random - Wraps Iter_RandomInternal.
  142. Iter_Count - Gets the number of items in an iterator.
  143. Iter_Debug - Wraps around Iter_ShowArray.
  144. Iter_Free - Wraps around Iter_FreeInternal.
  145. Iter_Create2 - Create a new iterator array value set.
  146. Iter_Add2 - Wraps Iter_AddInternal for arrays.
  147. Iter_Remove2 - Wraps Iter_RemoveInternal for arrays.
  148. Iter_Random2 - Wraps Iter_RandomInternal for arrays.
  149. Iter_Count2 - Gets the number of items in an iterator array.
  150. Iter_Debug2 - Wraps around Iter_ShowArray for arrays.
  151. Iter_Free2 - Wraps around Iter_FreeInternal for arrays.
  152. API:
  153. -
  154. Callbacks:
  155. -
  156. Hooks:
  157. Iter_OnPlayerConnect - Hook for the OnPlayerConnect callback.
  158. Iter_OnPlayerDisconnect - Hook for the OnPlayerDisconnect callback.
  159. Iter_OnGameModeInit - Only exists to make the code compile correctly...
  160. Definitions:
  161. -
  162. Enums:
  163. -
  164. Macros:
  165. -
  166. Keywords:
  167. foreach - Command to loop an iterator.
  168. foreachex - Like foreach but without a new variable.
  169. foreach2 - Command to loop through an iterator array.
  170. foreachex - Like foreach2 but without a new variable.
  171. Tags:
  172. Iterator - Declare an iterator.
  173. Variables:
  174. Global:
  175. -
  176. Static:
  177. YSI_g_OPC - Records wether Iter_OnPlayerConnect exists for speed.
  178. YSI_g_OPDC - Records wether Iter_OnPlayerDisconnect exists for speed.
  179. Commands:
  180. -
  181. Compile options:
  182. YSI_ITTER_NO_SORT - Removed.
  183. FOREACH_NO_BOTS - Remove the bot iterators for smaller code.
  184. FOREACH_NO_PLAYERS - Remove all default code for player itteration.
  185. Operators:
  186. -
  187. Iterators:
  188. Player - List of all players connected.
  189. Bot - List of all bots (npcs) connected.
  190. NPC - Alias of Bot.
  191. Character - All players and bots.
  192. \**--------------------------------------------------------------------------**/
  193. /*
  194. ad88888ba
  195. d8" "8b ,d
  196. Y8, 88
  197. `Y8aaaaa, ,adPPYba, MM88MMM 88 88 8b,dPPYba,
  198. `"""""8b, a8P_____88 88 88 88 88P' "8a
  199. `8b 8PP""""""" 88 88 88 88 d8
  200. Y8a a8P "8b, ,aa 88, "8a, ,a88 88b, ,a8"
  201. "Y88888P" `"Ybbd8"' "Y888 `"YbbdP'Y8 88`YbbdP"'
  202. 88
  203. 88
  204. */
  205. // "y_iterate" is always higher than "foreach".
  206. #define _Y_ITERATE_LOCAL_VERSION 42
  207. #if __Pawn != 0x030A
  208. #define NO_CUSTOM_WARNINGS
  209. #endif
  210. #if !defined _inc_y_iterate
  211. // The stand-alone version looks for this symbol, even on the new compiler.
  212. #define _inc_y_iterate
  213. #endif
  214. // Extra macro so that those paranoid about accidentally including YSI can
  215. // ensure it never happens.
  216. #if defined NEVER_Y_ITERATE
  217. // Set `FOREACH_VERSION` as equal to whatever the version of the stand-alone
  218. // include is.
  219. #define FOREACH_VERSION _FOREACH_LOCAL_VERSION
  220. #undef _inc_y_iterate
  221. #undef _Y_ITERATE_LOCAL_VERSION
  222. #if defined _FOREACH_INC_TEST
  223. // This is `foreach` testing our version - nothing more need doing.
  224. #endinput
  225. #endif
  226. // Otherwise, include `foreach`. Don't use `#tryinclude`, since they want
  227. // a version of `foreach` and it would be an error to not give them one.
  228. #define _FOREACH_NO_TEST
  229. #include <foreach>
  230. #endinput
  231. #endif
  232. // Foreach is testing us.
  233. #if defined _FOREACH_INC_TEST
  234. #if !defined _Y_ITERATE_FOUND
  235. // Set up so that you can use `FOREACH_VERSION` even if the older
  236. // stand-alone version doesn't support it.
  237. #define FOREACH_VERSION _FOREACH_LOCAL_VERSION
  238. #define _FOREACH_CUR_VERSION _Y_ITERATE_LOCAL_VERSION
  239. #endif
  240. #endinput
  241. #endif
  242. #if !defined _FOREACH_NO_TEST
  243. #define _FOREACH_INC_TEST
  244. // Ignore the broken stand-alone version.
  245. #define _foreach_included
  246. #tryinclude <foreach>
  247. #undef _FOREACH_INC_TEST
  248. // <foreach> exists - test which is newer.
  249. #if defined _FOREACH_LOCAL_VERSION
  250. #if _FOREACH_LOCAL_VERSION > _Y_ITERATE_LOCAL_VERSION
  251. // Foreach is newer.
  252. #if defined _inc_foreach
  253. #undef _inc_foreach
  254. #endif
  255. #define _FOREACH_NO_TEST
  256. // Actually include the code.
  257. #include <foreach>
  258. // Mark the include as found and exit.
  259. #define FOREACH_VERSION _FOREACH_LOCAL_VERSION
  260. #define _FOREACH_INC_TEST
  261. #define _Y_ITERATE_FOUND
  262. #endinput
  263. #endif
  264. #elseif defined foreach
  265. // I made this a warning on compilers that supported them, but that's a
  266. // silly idea!
  267. #error The old <foreach> include is no longer compatible with YSI.
  268. #endif
  269. #endif
  270. // Set `FOREACH_VERSION` as this file's version.
  271. #if defined FOREACH_VERSION
  272. #undef FOREACH_VERSION
  273. #endif
  274. #define FOREACH_VERSION _Y_ITERATE_LOCAL_VERSION
  275. #define _FOREACH_INC_TEST
  276. #define _Y_ITERATE_FOUND
  277. // Remove `_FOREACH_CUR_VERSION` incase someone includes an older version of
  278. // `foreach` later on that doesn't check if this symbol is already defined.
  279. #if defined _FOREACH_CUR_VERSION
  280. #undef _FOREACH_CUR_VERSION
  281. #endif
  282. #if !defined _samp_included
  283. #error "Please include a_samp or a_npc before foreach"
  284. #endif
  285. #if defined _YSI_SPECIAL_DEBUG
  286. #define PS_IS_PLAYER_CONNECTED(%0) (%0 != INVALID_PLAYER_ID)
  287. #else
  288. #define PS_IS_PLAYER_CONNECTED IsPlayerConnected
  289. #endif
  290. //
  291. // _FOREACH_BOTS
  292. //
  293. // Should the "NPC", "Bot", and "Character" iterators be included by default?
  294. // Disabled by declaring "FOREACH_NO_BOTS".
  295. //
  296. #define _FOREACH_BOTS 0
  297. #if defined IsPlayerNPC
  298. #define _FOREACH_BOT
  299. #if !defined FOREACH_NO_BOTS
  300. #undef _FOREACH_BOTS
  301. #define _FOREACH_BOTS 1
  302. #endif
  303. #endif
  304. //
  305. // _FOREACH_LOCALS
  306. //
  307. // Should the "LocalActor" and "LocalVehicle" iterators be included? These only
  308. // loop through ones created by the current script, instead of through ones
  309. // created in any script.
  310. //
  311. #define _FOREACH_LOCALS 1
  312. #if defined SendChat || defined FOREACH_NO_LOCALS
  313. #undef _FOREACH_LOCALS
  314. #define _FOREACH_LOCALS 0
  315. #endif
  316. //
  317. // _FOREACH_VEHICLES
  318. //
  319. // Should the "Vehicle" iterator be included? "Vehicle" loops over all vehicles
  320. // created on the server, "LocalVehicle" iterates over vehicles created only in
  321. // the current script. They are the same when "YSI_NO_MASTER" is declared.
  322. // Disabled by declaring "FOREACH_NO_VEHICLES".
  323. //
  324. #define _FOREACH_VEHICLES 1
  325. #if defined SendChat || defined FOREACH_NO_VEHICLES
  326. #undef _FOREACH_VEHICLES
  327. #define _FOREACH_VEHICLES 0
  328. #endif
  329. //
  330. // _FOREACH_ACTORS
  331. //
  332. // Should the "Actor" iterator be included? "Actor" loops over all actors
  333. // created on the server, "LocalActor" iterates over actors created only in the
  334. // current script. They are the same when "YSI_NO_MASTER" is declared.
  335. // Disabled by declaring "FOREACH_NO_ACTORS".
  336. //
  337. #define _FOREACH_ACTORS 0
  338. #if defined GetActorPos
  339. #if !defined FOREACH_NO_ACTORS
  340. #undef _FOREACH_ACTORS
  341. #define _FOREACH_ACTORS 1
  342. #endif
  343. #endif
  344. //
  345. // _FOREACH_PLAYERS
  346. //
  347. // Should the "Player" iterator be included? If "_FOREACH_BOTS" is set, the
  348. // "Player" iterator only loops over human players, "NPC" and "Bot" loop over
  349. // computer players, and "Character" loops over them all. If "_FOREACH_BOTS" is
  350. // not set, then the "Player" iterator loops over every player in the server,
  351. // the same as "Character" would do otherwise, since it has no way to know if a
  352. // player is human or not. Disabled by declaring "FOREACH_NO_PLAYERS".
  353. //
  354. #define _FOREACH_PLAYERS 1
  355. #if defined SendChat || defined FOREACH_NO_PLAYERS
  356. #undef _FOREACH_PLAYERS
  357. #define _FOREACH_PLAYERS 0
  358. #endif
  359. //
  360. // _FOREACH_CHARACTERS
  361. //
  362. // Bot or Player iterators included.
  363. //
  364. #define _FOREACH_CHARACTERS (_FOREACH_BOTS || _FOREACH_PLAYERS)
  365. #if !defined BOTSYNC_IS_BOT
  366. forward Iter_OPDCInternal(playerid);
  367. #endif
  368. #include "..\YSI_Internal\y_natives"
  369. #include "..\YSI_Internal\y_shortfunc"
  370. #include "..\YSI_Internal\y_compilerpass"
  371. #include "..\YSI_Core\y_debug"
  372. #include "y_foreach/impl"
  373. #if _FOREACH_CHARACTERS || _FOREACH_VEHICLES || _FOREACH_ACTORS
  374. #include "..\YSI_Coding\y_hooks"
  375. #endif
  376. #if _FOREACH_VEHICLES || _FOREACH_ACTORS
  377. #include "..\YSI_Coding\y_remote"
  378. #endif
  379. #include "y_foreach/iterators"
  380. #if defined YSI_TESTS
  381. #include "..\YSI_Core\y_testing"
  382. #include "y_foreach/tests"
  383. #endif