y_masteronce.inc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459
  1. /*----------------------------------------------------------------------------*-
  2. ===================
  3. YSI - Master Core
  4. ===================
  5. Description:
  6. There seems to be a bug with a compiler when using #emit in files included
  7. more than once, so this code has been moved to a file only included once.
  8. Legal:
  9. Version: MPL 1.1
  10. The contents of this file are subject to the Mozilla Public License Version
  11. 1.1 (the "License"); you may not use this file except in compliance with
  12. the License. You may obtain a copy of the License at
  13. http://www.mozilla.org/MPL/
  14. Software distributed under the License is distributed on an "AS IS" basis,
  15. WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  16. for the specific language governing rights and limitations under the
  17. License.
  18. The Original Code is the SA:MP script information include.
  19. The Initial Developer of the Original Code is Alex "Y_Less" Cole.
  20. Portions created by the Initial Developer are Copyright (C) 2008
  21. the Initial Developer. All Rights Reserved.
  22. Contributors:
  23. ZeeX, koolk
  24. Thanks:
  25. Peter, Cam - Support.
  26. ZeeX - Very productive conversations.
  27. koolk - IsPlayerinAreaEx code.
  28. TheAlpha - Danish translation.
  29. breadfish - German translation.
  30. Fireburn - Dutch translation.
  31. yom - French translation.
  32. 50p - Polish translation.
  33. Zamaroht - Spanish translation.
  34. Dracoblue, sintax, mabako, Xtreme, other coders - Producing other modes
  35. for me to strive to better.
  36. Pixels^ - Running XScripters where the idea was born.
  37. Matite - Pestering me to release it and using it.
  38. Very special thanks to:
  39. Thiadmer - PAWN.
  40. Kye/Kalcor - SA:MP.
  41. SA:MP Team past, present and future - SA:MP.
  42. Version:
  43. 0.2
  44. Changelog:
  45. 07/08/10:
  46. Split in to y_masteronce.
  47. Added assembly for publics scanning.
  48. 06/08/10:
  49. Managed the ultimate - got completely transparent inclusion!
  50. 05/08/10:
  51. Completed new master system, now does all syncing and clients.
  52. 06/10/09:
  53. Rewrote using states.
  54. Added remote function macros.
  55. Reduced the number of masters to a single one. It must have them all.
  56. Vastly simplified the master model - ending the master ends everything.
  57. 06/01/08:
  58. Added code to not pass data if no other script exists.
  59. 17/11/07:
  60. Added code for a script to remove itself from the global list.
  61. 11/10/07:
  62. Not first version but added documentation months late.
  63. Functions:
  64. Public:
  65. -
  66. Core:
  67. -
  68. Stock:
  69. -
  70. Static:
  71. -
  72. Inline:
  73. -
  74. API:
  75. -
  76. Hooks:
  77. OnGameModeInit
  78. OnGameModeExit
  79. Callbacks:
  80. -
  81. Definitions:
  82. -
  83. Enums:
  84. -
  85. Macros:
  86. -
  87. Tags:
  88. -
  89. Variables:
  90. Global:
  91. _@ - ID of this script.
  92. Static:
  93. -
  94. Commands:
  95. -
  96. Compile options:
  97. -
  98. Operators:
  99. -
  100. Natives:
  101. -
  102. -*----------------------------------------------------------------------------*/
  103. // These parts should only be defined once ever. This code is not dependent on
  104. // the current MASTER value, it's all generic.
  105. #include <YSI\internal\y_version>
  106. #include <YSI\y_debug>
  107. #define YSIM_MASTER #M
  108. #define YSIM_RETURN #R
  109. #define YSIM_CALLER #C
  110. #define YSIM_STRING (42)
  111. // Define all the alternate spellings once.
  112. #define RF@cp RF@pc
  113. #define RF@pvc RF@pcv
  114. #define RF@cpv RF@pcv
  115. #define RF@cvp RF@pcv
  116. #define RF@vpc RF@pcv
  117. #define RF@vcp RF@pcv
  118. #define RF@vp RF@pv
  119. #define RF@cv RF@vc
  120. //#define RF@nv RF@vn
  121. #define RF@cpt RF@pct
  122. #define RF@tcp RF@pct
  123. #define RF@tpc RF@pct
  124. #define RF@ctp RF@pct
  125. #define RF@ptc RF@pct
  126. #define RF@tp RF@pt
  127. #define RF@tc RF@ct
  128. //#define RF@tn RF@nt
  129. #define OnScriptClose Master_OnScriptClose
  130. forward Master_OnScriptClose(script);
  131. #define YSIM_NOT_CLIENT (!YSIM_HAS_MASTER || !YSIM_IS_CLIENT)
  132. #define YSI_MAX_STRING (128)
  133. #if defined YSI_NO_MASTER
  134. // Public variable.
  135. public
  136. _@ = 0;
  137. #endinput
  138. #endif
  139. // Public variable.
  140. public
  141. _@ = -1;
  142. //#if !defined MAX_MASTERS
  143. #define MAX_MASTERS 26
  144. //#else
  145. // #if MAX_MASTERS > 32
  146. // #undef MAX_MASTERS
  147. // #define MAX_MASTERS 32
  148. // #endif
  149. //#endif
  150. forward Master_Reassert();
  151. static
  152. YSI_g_sMasterCount,
  153. YSI_g_sMasterData[MAX_MASTERS];
  154. #include <YSI\internal\y_shortfunc>
  155. stock X@(n)
  156. {
  157. setproperty(8, YSIM_RETURN, n);
  158. }
  159. stock Y@()
  160. {
  161. return setproperty(8, YSIM_CALLER, _@);
  162. }
  163. stock Z@()
  164. {
  165. setproperty(8, YSIM_CALLER, -1);
  166. return getproperty(8, YSIM_RETURN);
  167. }
  168. stock T@()
  169. {
  170. setproperty(8, YSIM_CALLER, -1);
  171. }
  172. new Q@[YSI_MAX_STRING];
  173. stock S@()
  174. {
  175. getproperty(9, "", YSIM_STRING, Q@);
  176. strunpack(Q@, Q@);
  177. setproperty(8, YSIM_CALLER, -1);
  178. return 0;
  179. }
  180. stock R@(buffer[])
  181. {
  182. setproperty(9, "", YSIM_STRING, buffer);
  183. }
  184. /*----------------------------------------------------------------------------*-
  185. Function:
  186. Master_GetNext
  187. Params:
  188. -
  189. Return:
  190. Next master ID to be assigned.
  191. Notes:
  192. -
  193. -*----------------------------------------------------------------------------*/
  194. stock Master_GetNext()
  195. {
  196. new
  197. masters = getproperty(8, YSIM_MASTER),
  198. i = 0;
  199. while (i != 32)
  200. {
  201. if (!(masters & (1 << i)))
  202. {
  203. return i;
  204. }
  205. ++i;
  206. }
  207. return -1;
  208. }
  209. /*----------------------------------------------------------------------------*-
  210. Hook:
  211. OnGameModeInit
  212. Notes:
  213. Constructor. Gets the script a master ID. Now ALWAYS gets an ID, even if
  214. the master system is disabled - doing otherwise is just too complicated.
  215. -*----------------------------------------------------------------------------*/
  216. #if defined FILTERSCRIPT
  217. public OnFilterScriptInit()
  218. #else
  219. public OnGameModeInit()
  220. #endif
  221. {
  222. P:1("Master_OGM");
  223. if (!existproperty(8, YSIM_MASTER))
  224. {
  225. setproperty(8, YSIM_MASTER, 0);
  226. }
  227. // Properties get lost between script changes so we need to force a rebuild.
  228. CallRemoteFunction("Master_Reassert", "");
  229. new
  230. masters = getproperty(8, YSIM_MASTER),
  231. i = 0;
  232. while (i != 32)
  233. {
  234. if (!(masters & (1 << i)))
  235. {
  236. _@ = i;
  237. masters |= 1 << i;
  238. break;
  239. }
  240. ++i;
  241. }
  242. if (i != 32)
  243. {
  244. setproperty(8, YSIM_MASTER, masters);
  245. }
  246. C:1(if (_@ == -1) printf("*** Internal Error! MasterID not assigned"););
  247. // Make sure this is called before all other YSI initialisations, at least
  248. // all the ones which use the master system.
  249. CallLocalFunction("YSIM_OnMasterSystemInit", "");
  250. // Just use one name...
  251. CallLocalFunction("YSIM_OnScriptInit", "");
  252. return 1;
  253. }
  254. #define OnMasterSystemInit YSIM_OnMasterSystemInit
  255. forward YSIM_OnMasterSystemInit();
  256. #if defined FILTERSCRIPT
  257. #if defined _ALS_OnFilterScriptInit
  258. #undef OnFilterScriptInit
  259. #else
  260. #define _ALS_OnFilterScriptInit
  261. #endif
  262. #define OnFilterScriptInit YSIM_OnScriptInit
  263. #else
  264. #if defined _ALS_OnGameModeInit
  265. #undef OnGameModeInit
  266. #else
  267. #define _ALS_OnGameModeInit
  268. #endif
  269. #define OnGameModeInit YSIM_OnScriptInit
  270. #endif
  271. forward YSIM_OnScriptInit();
  272. /*----------------------------------------------------------------------------*-
  273. Hook:
  274. OnGameModeExit
  275. Notes:
  276. Destructor.
  277. -*----------------------------------------------------------------------------*/
  278. #if defined FILTERSCRIPT
  279. public OnFilterScriptExit()
  280. #else
  281. public OnGameModeExit()
  282. #endif
  283. {
  284. // Loop through everything this script is master for and call the remote
  285. // function for it. EXCEPT for this script itself!
  286. new
  287. func[4];
  288. for (new i = 0; i != YSI_g_sMasterCount; ++i)
  289. {
  290. // This is slightly slower for ending and starting scripts, but uses far
  291. // less heap space, and these values are rarely used, so may as well
  292. // pack them (which is what has happened here).
  293. func[0] = YSI_g_sMasterData[i] & 0xFF;
  294. func[1] = (YSI_g_sMasterData[i] >> 8) & 0xFF;
  295. func[2] = YSI_g_sMasterData[i] >> 16;
  296. CallLocalFunction(func, "");
  297. // The properties currently clear instantly, but that may not always be
  298. // the case.
  299. setproperty(8, YSIM_MASTER, getproperty(8, YSIM_MASTER) & ~(1 << _@));
  300. }
  301. CallLocalFunction("YSIM_OnScriptExit", "");
  302. CallRemoteFunction("Master_OnScriptClose", "i", _@);
  303. return 1;
  304. }
  305. #if defined FILTERSCRIPT
  306. #if defined _ALS_OnFilterScriptExit
  307. #undef OnFilterScriptExit
  308. #else
  309. #define _ALS_OnFilterScriptExit
  310. #endif
  311. #define OnFilterScriptExit YSIM_OnScriptExit
  312. #else
  313. #if defined _ALS_OnGameModeExit
  314. #undef OnGameModeExit
  315. #else
  316. #define _ALS_OnGameModeExit
  317. #endif
  318. #define OnGameModeExit YSIM_OnScriptExit
  319. #endif
  320. forward YSIM_OnScriptExit();
  321. /*----------------------------------------------------------------------------*-
  322. Function:
  323. Master_Reassert
  324. Params:
  325. -
  326. Return:
  327. -
  328. Notes:
  329. Rebuilds the collection of master data whenever a script is restarted.
  330. -*----------------------------------------------------------------------------*/
  331. public Master_Reassert()
  332. {
  333. // Make sure that the caller parameter is always -1 by default.
  334. U@(8, YSIM_CALLER, -1);
  335. if (_@ != -1)
  336. {
  337. // Readd this script's master value.
  338. setproperty(8, YSIM_MASTER, getproperty(8, YSIM_MASTER) | (1 << _@));
  339. // Readd this script's owned scripts.
  340. new
  341. func[4];
  342. for (new i = 0; i != YSI_g_sMasterCount; ++i)
  343. {
  344. // This is slightly slower for ending and starting scripts, but uses far
  345. // less heap space, and these values are rarely used, so may as well
  346. // pack them (which is what has happened here).
  347. func[0] = YSI_g_sMasterData[i] & 0xFF;
  348. func[1] = (YSI_g_sMasterData[i] >> 8) & 0xFF;
  349. func[2] = YSI_g_sMasterData[i] >> 16;
  350. setproperty(8, func, _@);
  351. }
  352. }
  353. }
  354. /*----------------------------------------------------------------------------*-
  355. Function:
  356. _Master_Get
  357. Params:
  358. library[] - The name of the library to try become master for.
  359. Return:
  360. -
  361. Notes:
  362. -
  363. -*----------------------------------------------------------------------------*/
  364. stock bool:_Master_Get(library[], bool:force = false)
  365. {
  366. P:2("_Master_Get called");
  367. if (!force && existproperty(8, library))
  368. {
  369. P:4("_Master_Get: Prop exists: %d %d", getproperty(8, library), _@);
  370. if (getproperty(8, library) != -1)
  371. {
  372. P:4("_Master_Get: Prop set");
  373. return false;
  374. }
  375. }
  376. P:4("_Master_Get: Get master.");
  377. setproperty(8, library, _@);
  378. P:4("_Master_Get: Set master.");
  379. // Add this library to the list. The list is designed to only deal with
  380. // two or three character master names now!
  381. if (YSI_g_sMasterCount < MAX_MASTERS)
  382. {
  383. P:4("_Master_Get: Set master string.");
  384. YSI_g_sMasterData[YSI_g_sMasterCount++] = library[0] | (library[1] << 8) | (library[2] << 16);
  385. P:4("_Master_Get: Set master string.");
  386. }
  387. C:1(else printf("*** Internal Error! Too many master scripts"););
  388. return true;
  389. }
  390. //#define RS@pc RS@cp
  391. /*
  392. #define RF:%1[%2](%3)
  393. #define RF@p:%1[%2](%3)<%4>
  394. #define RF@c:%1[%2](%3)
  395. #define RF@v:%1[%2](%3)
  396. #define RF@n:%1[]()
  397. #define RF@pc:%1[%2](%3)<%4>
  398. #define RF@pv:%1[%2](%3)<%4>
  399. #define RF@pcv:%1[%2](%3)<%4>
  400. #define RF@vc:%1[%2](%3)
  401. #define RF@vn:%1[]()
  402. */
  403. // Define all the alternate spellings once.
  404. //#define RC@nv RC@vn
  405. /*
  406. #define RC:%1[%2](%3)
  407. #define RC@v:%1[%2](%3)
  408. #define RC@n:%1[]()
  409. #define RC@vn:%1[]()
  410. */