Advertisement
Guest User

botsync.inc

a guest
Jul 10th, 2011
404
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Pawn 10.76 KB | None | 0 0
  1. /*----------------------------------------------------------------------------*-
  2.                     ==========================
  3.                      NPC script communication
  4.                     ==========================
  5. Description:
  6.     This code provides a system to communicate with bots via files.  It uses
  7.     locks to ensure only one script may communicate at once - bots and the main
  8.     server run in separate processes so it is possible to read and write from
  9.     the files at the same time if locks are not used.
  10.    
  11.     Because the communication is asynchronous replies are not instant, you send
  12.     a message to the bot (or vice versa) then use a callback to process the
  13.     response later.
  14.    
  15.     Fast communication with bots is done via OnClientMessage, but there is no
  16.     way of returning data using this method, any responses from the bot will
  17.     have to go via the regular file system.
  18.    
  19.     This file defines functions useable from scripts, both server and bot end,
  20.     to communicate with each other.  At the server end this file posts the
  21.     messages off to the communication filterscript, except fast messages which,
  22.     as the name implies, are done specially and instantly.  At the bot end this
  23.     file handles all its own file reading and writing as only one script can
  24.     access the files it relates to.
  25. Legal:
  26.     Copyright (C) 2009 Alex "Y_Less" Cole
  27.  
  28.     The contents of this file are subject to the Mozilla Public License
  29.     Version 1.1 (the "License"); you may not use this file except in
  30.     compliance with the License. You may obtain a copy of the License at
  31.     http://www.mozilla.org/MPL/
  32.    
  33.     Software distributed under the License is distributed on an "AS IS"
  34.     basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
  35.     License for the specific language governing rights and limitations
  36.     under the License.
  37.    
  38.     The Original Code is the NPC synchronisation code include.
  39.    
  40.     The Initial Developer of the Original Code is Alex "Y_Less" Cole.  All
  41.     Rights Reserved.
  42. Version:
  43.     0.1
  44. Changelog:
  45.     02/09/09:
  46.         First version
  47. Functions:
  48.     Public:
  49.         -
  50.     Core:
  51.         -
  52.     Stock:
  53.         -
  54.     Static:
  55.         -
  56.     Inline:
  57.         -
  58.     API:
  59.         -
  60. Callbacks:
  61.     -
  62. Hooks:
  63.     -
  64. Definitions:
  65.     BOTSYNC_IS_BOT - Detects where this is included, in a bot or server script.
  66.     MAX_FAST_MESSAGE - Max length of a fast bot message.
  67. Enums:
  68.     -
  69. Macros:
  70.     -
  71. Tags:
  72.     -
  73. Variables:
  74.     Global:
  75.         -
  76.     Static:
  77.         -
  78. Commands:
  79.     -
  80. Compile options:
  81.     -
  82. Operators:
  83.     -
  84. Iterators:
  85.     BotSync - Array of unsent messages.
  86. -*----------------------------------------------------------------------------*/
  87.  
  88. #if !defined _samp_included
  89.     #error "Please include a_samp or a_npc before botsync"
  90. #endif
  91.  
  92. #include <foreach>
  93.  
  94. #if defined SendChat
  95.     #define BOTSYNC_IS_BOT     (true)
  96. #endif
  97.  
  98. #if defined BOTSYNC_IS_BOT
  99.     #define BOTSYNC_LOCK_STRING "0"
  100.     #define BOTSYNC_LOCK_CHAR   '0'
  101.    
  102.     #define BOTSYNC_IN_STR      "t"
  103.     #define BOTSYNC_OUT_STR     "f"
  104.    
  105.     #define BOTSYNC_MESSAGE_BUFFER (20)
  106. #else
  107.     #define BOTSYNC_LOCK_STRING "1"
  108.     #define BOTSYNC_LOCK_CHAR   '1'
  109.    
  110.     #define BOTSYNC_IN_STR      "f"
  111.     #define BOTSYNC_OUT_STR     "t"
  112.    
  113.     #define BOTSYNC_MESSAGE_BUFFER (128)
  114. #endif
  115.  
  116. #define BOTSYNC_MESSAGE_LENGTH (124)
  117.  
  118. #define BOTSYNC_FOLDER         "BotSync."
  119.  
  120. #define BOTSYNC_FILE_LENGTH    (20)
  121.  
  122. #define BOTSYNC_FILE           (BOTSYNC_FOLDER "%03d.%s.l"), (bot), (read ? (BOTSYNC_IN_STR) : (BOTSYNC_OUT_STR))
  123.  
  124. #if !defined isnull
  125.     #define isnull(%0) \
  126.         (((%0)[0] == '\0') || (((%0)[0] == '\1') && ((%0)[1] == '\0')))
  127. #endif
  128.  
  129. forward
  130.     OnBotSyncData(bot, const name[], const msg[]);
  131.  
  132. #if defined BOTSYNC_SYNC_FS || defined BOTSYNC_IS_BOT
  133.     Itter_Create(BotSync, BOTSYNC_MESSAGE_BUFFER);
  134.    
  135.     forward
  136.         BotSync_Tick();
  137.    
  138.     static
  139.     bool:
  140.         BotSync_GetLock(bot, bool:read)
  141.     {
  142.         new
  143.             name[BOTSYNC_FILE_LENGTH];
  144.         format(name, sizeof (name), BOTSYNC_FILE);
  145.         if (fexist(name))
  146.         {
  147.             return false;
  148.         }
  149.         new
  150.             File:fhnd = fopen(name, io_write);
  151.         if (fhnd)
  152.         {
  153.             fwrite(fhnd, BOTSYNC_LOCK_STRING);
  154.             fclose(fhnd);
  155.             fhnd = fopen(name, io_read);
  156.             if (fhnd)
  157.             {
  158.                 if (fgetchar(fhnd, 0, false) == BOTSYNC_LOCK_CHAR)
  159.                 {
  160.                     fclose(fhnd);
  161.                     return true;
  162.                 }
  163.                 fclose(fhnd);
  164.             }
  165.             else
  166.             {
  167.                 printf("BotSync error: Lock fail");
  168.             }
  169.         }
  170.         return false;
  171.     }
  172.    
  173.     static
  174.         BotSync_ReleaseLock(bot, bool:read)
  175.     {
  176.         new
  177.             name[BOTSYNC_FILE_LENGTH];
  178.         format(name, sizeof (name), BOTSYNC_FILE);
  179.         fremove(name);
  180.     }
  181.    
  182.     static
  183.     BSF:
  184.         BotSync_Open(bot)
  185.     {
  186.         new
  187.             name[BOTSYNC_FILE_LENGTH];
  188.         format(name, sizeof (name), BOTSYNC_FOLDER "%03d." BOTSYNC_OUT_STR ".d", bot);
  189.         return BSF:fopen(name, io_append);
  190.     }
  191.    
  192.     #define BotSync_Write(%0,%1) \
  193.         fwrite(File:%0, %1)
  194.    
  195.     #define BotSync_Close(%0) \
  196.         fclose(File:%0)
  197. #endif
  198.  
  199. #if defined BOTSYNC_IS_BOT
  200.     static
  201.         BS_g_MessageBuffer[BOTSYNC_MESSAGE_BUFFER][BOTSYNC_MESSAGE_LENGTH],
  202.         BS_g_me;
  203.    
  204.     public
  205.         BotSync_Tick()
  206.     {
  207.         if (Itter_Count(BotSync))
  208.         {
  209.             if (BotSync_GetLock(BS_g_me, false))
  210.             {
  211.                 new
  212.                     BSF:fhnd = BotSync_Open(BS_g_me);
  213.                 if (fhnd)
  214.                 {
  215.                     new
  216.                         msg = YSI_gBotSyncS,
  217.                         nxt;
  218.                     while (msg != -1)
  219.                     {
  220.                         BotSync_Write(fhnd, BS_g_MessageBuffer[msg]);
  221.                         nxt = YSI_gBotSyncA[msg];
  222.                         YSI_gBotSyncA[msg] = -1;
  223.                         msg = nxt;
  224.                     }
  225.                     YSI_gBotSyncC = 0;
  226.                     YSI_gBotSyncS = -1;
  227.                     BotSync_Close(fhnd);
  228.                 }
  229.                 BotSync_ReleaseLock(BS_g_me, false);
  230.             }
  231.         }
  232.         #if defined BOT_SYNC_CALLBACK
  233.             new
  234.                 name[BOTSYNC_FILE_LENGTH];
  235.             format(name, sizeof (name), BOTSYNC_FOLDER "%03d." BOTSYNC_IN_STR ".d", BS_g_me);
  236.             if (fexist(name))
  237.             {
  238.                 if (BotSync_GetLock(BS_g_me, true))
  239.                 {
  240.                     new
  241.                         File:fhnd = fopen(name, io_read);
  242.                     if (fhnd)
  243.                     {
  244.                         new
  245.                             str[BOTSYNC_MESSAGE_LENGTH];
  246.                         while (fread(fhnd, str))
  247.                         {
  248.                             new
  249.                                 pos0 = -1;
  250.                             while (str[++pos0] > '\1') {}
  251.                             if (str[pos0] == '\1')
  252.                             {
  253.                                 new
  254.                                     pos1 = pos0;
  255.                                 while (str[++pos1] >= ' ') {}
  256.                                 str[pos0] = '\0';
  257.                                 str[pos1] = '\0';
  258.                                 BOT_SYNC_CALLBACK(-1, str, str[pos0 + 1]);
  259.                             }
  260.                         }
  261.                         fclose(fhnd);
  262.                         fremove(name);
  263.                     }
  264.                     BotSync_ReleaseLock(BS_g_me, true);
  265.                 }
  266.             }
  267.         #endif
  268.     }
  269.    
  270.     public
  271.         OnNPCConnect(myplayerid)
  272.     {
  273.         SetTimer("BotSync_Tick", 10, true);
  274.         BS_g_me = myplayerid;
  275.         BotSync_OnNPCConnect(myplayerid);
  276.     }
  277.    
  278.     #define OnNPCConnect BotSync_OnNPCConnect
  279.    
  280.     forward
  281.         BotSync_OnNPCConnect(myplayerid);
  282.    
  283.     public
  284.         OnClientMessage(color, text[])
  285.     {
  286.         if (color)
  287.         {
  288.             return BotSync_OnClientMessage(color, text);
  289.         }
  290.         new
  291.             pos0 = -1;
  292.         while (text[++pos0] > '\1') {}
  293.         if (text[pos0] == '\1')
  294.         {
  295.             text[pos0] = '\0';
  296.             BOT_SYNC_CALLBACK(-1, text, text[pos0 + 1]);
  297.         }
  298.         return 0;
  299.     }
  300.    
  301.     #define OnClientMessage BotSync_OnClientMessage
  302.    
  303.     forward
  304.         BotSync_OnClientMessage(color, text[]);
  305.    
  306.     stock
  307.         BotSync_Send(bot, type[], message[])
  308.     {
  309.         new
  310.             slot = Itter_Free(BotSync);
  311.         if (slot != -1)
  312.         {
  313.             if (strlen(type) + strlen(message) < BOTSYNC_MESSAGE_LENGTH - 3)
  314.             {
  315.                 format(BS_g_MessageBuffer[slot], BOTSYNC_MESSAGE_LENGTH, "%s\1%s\n", type, message);
  316.                 Itter_Add(BotSync, slot);
  317.                 return 1;
  318.             }
  319.         }
  320.         return 0;
  321.         #pragma unused bot
  322.     }
  323. #else
  324.     #if defined BOTSYNC_SYNC_FS
  325.         enum E_BOTSYNC_BUFFER
  326.         {
  327.             E_BOTSYNC_BOT,
  328.             E_BOTSYNC_MESSAGE[BOTSYNC_MESSAGE_LENGTH]
  329.         }
  330.        
  331.         static
  332.             BS_g_MessageBuffer[BOTSYNC_MESSAGE_BUFFER][E_BOTSYNC_BUFFER];
  333.        
  334.         forward
  335.             BotSync_Buffer(bot, type[], message[]);
  336.        
  337.         public
  338.             BotSync_Tick()
  339.         {
  340.             new
  341.                 dun = -1,
  342.                 msg,
  343.                 last;
  344.             do
  345.             {
  346.                 last = -1;
  347.                 foreachex (BotSync, msg)
  348.                 {
  349.                     if (msg > dun)
  350.                     {
  351.                         new
  352.                             bot = BS_g_MessageBuffer[msg][E_BOTSYNC_BOT];
  353.                         if (BotSync_GetLock(bot, false))
  354.                         {
  355.                             new
  356.                                 BSF:fhnd = BotSync_Open(bot);
  357.                             if (fhnd)
  358.                             {
  359.                                 BotSync_Write(fhnd, BS_g_MessageBuffer[msg][E_BOTSYNC_MESSAGE]);
  360.                                 new
  361.                                     cur = YSI_gBotSyncA[msg],
  362.                                     lst = msg;
  363.                                 while (cur != -1)
  364.                                 {
  365.                                     if (BS_g_MessageBuffer[cur][E_BOTSYNC_BOT] == bot)
  366.                                     {
  367.                                         BotSync_Write(fhnd, BS_g_MessageBuffer[cur][E_BOTSYNC_MESSAGE]);
  368.                                         YSI_gBotSyncA[lst] = YSI_gBotSyncA[cur];
  369.                                         YSI_gBotSyncA[cur] = -1;
  370.                                         cur = YSI_gBotSyncA[lst];
  371.                                         --YSI_gBotSyncC;
  372.                                     }
  373.                                     else
  374.                                     {
  375.                                         lst = cur;
  376.                                         cur = YSI_gBotSyncA[cur];
  377.                                     }
  378.                                 }
  379.                                 BotSync_Close(fhnd);
  380.                                 BotSync_ReleaseLock(bot, false);
  381.                                 dun = msg;
  382.                                 if (last == -1)
  383.                                 {
  384.                                     YSI_gBotSyncS = YSI_gBotSyncA[msg];
  385.                                 }
  386.                                 else
  387.                                 {
  388.                                     YSI_gBotSyncA[last] = YSI_gBotSyncA[msg];
  389.                                 }
  390.                                 YSI_gBotSyncA[msg] = -1;
  391.                                 --YSI_gBotSyncC;
  392.                                 break;
  393.                             }
  394.                             BotSync_ReleaseLock(bot, false);
  395.                         }
  396.                     }
  397.                     last = msg;
  398.                 }
  399.             }
  400.             while (msg != -1);
  401.             foreach (Bot, bot)
  402.             {
  403.                 new
  404.                     name[BOTSYNC_FILE_LENGTH];
  405.                 format(name, sizeof (name), BOTSYNC_FOLDER "%03d." BOTSYNC_IN_STR ".d", bot);
  406.                 if (fexist(name))
  407.                 {
  408.                     if (BotSync_GetLock(bot, true))
  409.                     {
  410.                         new
  411.                             File:fhnd = fopen(name, io_read);
  412.                         if (fhnd)
  413.                         {
  414.                             new
  415.                                 str[BOTSYNC_MESSAGE_LENGTH];
  416.                             while (fread(fhnd, str))
  417.                             {
  418.                                 new
  419.                                     pos0 = -1;
  420.                                 while (str[++pos0] > '\1') {}
  421.                                 if (str[pos0] == '\1')
  422.                                 {
  423.                                     new
  424.                                         pos1 = pos0;
  425.                                     while (str[++pos1] >= ' ') {}
  426.                                     str[pos0] = '\0';
  427.                                     str[pos1] = '\0';
  428.                                     CallRemoteFunction("OnBotSyncData", "iss", bot, str, str[pos0 + 1]);
  429.                                 }
  430.                             }
  431.                             fclose(fhnd);
  432.                             fremove(name);
  433.                         }
  434.                         BotSync_ReleaseLock(bot, true);
  435.                     }
  436.                 }
  437.             }
  438.         }
  439.        
  440.         public
  441.             BotSync_Buffer(bot, type[], message[])
  442.         {
  443.             // Buffer the message and send it later.
  444.             if (isnull(type) || isnull(message))
  445.             {
  446.                 return 0;
  447.             }
  448.             if (IsPlayerNPC(bot))
  449.             {
  450.                 new
  451.                     slot = Itter_Free(BotSync);
  452.                 if (slot != -1)
  453.                 {
  454.                     if (strlen(type) + strlen(message) < BOTSYNC_MESSAGE_LENGTH - 3)
  455.                     {
  456.                         format(BS_g_MessageBuffer[slot][E_BOTSYNC_MESSAGE], BOTSYNC_MESSAGE_LENGTH, "%s\1%s\n", type, message);
  457.                         BS_g_MessageBuffer[slot][E_BOTSYNC_BOT] = bot;
  458.                         Itter_Add(BotSync, slot);
  459.                         return 1;
  460.                     }
  461.                 }
  462.             }
  463.             return 0;
  464.         }
  465.     #else
  466.         stock
  467.             BotSync_SendFast(bot, type[], message[])
  468.         {
  469.             if (IsPlayerNPC(bot))
  470.             {
  471.                 if (strlen(type) + strlen(message) < BOTSYNC_MESSAGE_LENGTH - 3)
  472.                 {
  473.                     new
  474.                         str[BOTSYNC_MESSAGE_LENGTH];
  475.                     format(str, sizeof (str), "%s\1%s", type, message);
  476.                     SendClientMessage(bot, 0, str);
  477.                     return 1;
  478.                 }
  479.             }
  480.             return 0;
  481.         }
  482.        
  483.         stock
  484.             BotSync_Send(bot, type[], message[])
  485.         {
  486.             CallRemoteFunction("BotSync_Buffer", "iss", bot, type, message);
  487.         }
  488.     #endif
  489. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement