Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*----------------------------------------------------------------------------*-
- ==========================
- NPC script communication
- ==========================
- Description:
- This code provides a system to communicate with bots via files. It uses
- locks to ensure only one script may communicate at once - bots and the main
- server run in separate processes so it is possible to read and write from
- the files at the same time if locks are not used.
- Because the communication is asynchronous replies are not instant, you send
- a message to the bot (or vice versa) then use a callback to process the
- response later.
- Fast communication with bots is done via OnClientMessage, but there is no
- way of returning data using this method, any responses from the bot will
- have to go via the regular file system.
- This file defines functions useable from scripts, both server and bot end,
- to communicate with each other. At the server end this file posts the
- messages off to the communication filterscript, except fast messages which,
- as the name implies, are done specially and instantly. At the bot end this
- file handles all its own file reading and writing as only one script can
- access the files it relates to.
- Legal:
- Copyright (C) 2009 Alex "Y_Less" Cole
- The contents of this file are subject to the Mozilla Public License
- Version 1.1 (the "License"); you may not use this file except in
- compliance with the License. You may obtain a copy of the License at
- http://www.mozilla.org/MPL/
- Software distributed under the License is distributed on an "AS IS"
- basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
- License for the specific language governing rights and limitations
- under the License.
- The Original Code is the NPC synchronisation code include.
- The Initial Developer of the Original Code is Alex "Y_Less" Cole. All
- Rights Reserved.
- Version:
- 0.1
- Changelog:
- 02/09/09:
- First version
- Functions:
- Public:
- -
- Core:
- -
- Stock:
- -
- Static:
- -
- Inline:
- -
- API:
- -
- Callbacks:
- -
- Hooks:
- -
- Definitions:
- BOTSYNC_IS_BOT - Detects where this is included, in a bot or server script.
- MAX_FAST_MESSAGE - Max length of a fast bot message.
- Enums:
- -
- Macros:
- -
- Tags:
- -
- Variables:
- Global:
- -
- Static:
- -
- Commands:
- -
- Compile options:
- -
- Operators:
- -
- Iterators:
- BotSync - Array of unsent messages.
- -*----------------------------------------------------------------------------*/
- #if !defined _samp_included
- #error "Please include a_samp or a_npc before botsync"
- #endif
- #include <foreach>
- #if defined SendChat
- #define BOTSYNC_IS_BOT (true)
- #endif
- #if defined BOTSYNC_IS_BOT
- #define BOTSYNC_LOCK_STRING "0"
- #define BOTSYNC_LOCK_CHAR '0'
- #define BOTSYNC_IN_STR "t"
- #define BOTSYNC_OUT_STR "f"
- #define BOTSYNC_MESSAGE_BUFFER (20)
- #else
- #define BOTSYNC_LOCK_STRING "1"
- #define BOTSYNC_LOCK_CHAR '1'
- #define BOTSYNC_IN_STR "f"
- #define BOTSYNC_OUT_STR "t"
- #define BOTSYNC_MESSAGE_BUFFER (128)
- #endif
- #define BOTSYNC_MESSAGE_LENGTH (124)
- #define BOTSYNC_FOLDER "BotSync."
- #define BOTSYNC_FILE_LENGTH (20)
- #define BOTSYNC_FILE (BOTSYNC_FOLDER "%03d.%s.l"), (bot), (read ? (BOTSYNC_IN_STR) : (BOTSYNC_OUT_STR))
- #if !defined isnull
- #define isnull(%0) \
- (((%0)[0] == '\0') || (((%0)[0] == '\1') && ((%0)[1] == '\0')))
- #endif
- forward
- OnBotSyncData(bot, const name[], const msg[]);
- #if defined BOTSYNC_SYNC_FS || defined BOTSYNC_IS_BOT
- Itter_Create(BotSync, BOTSYNC_MESSAGE_BUFFER);
- forward
- BotSync_Tick();
- static
- bool:
- BotSync_GetLock(bot, bool:read)
- {
- new
- name[BOTSYNC_FILE_LENGTH];
- format(name, sizeof (name), BOTSYNC_FILE);
- if (fexist(name))
- {
- return false;
- }
- new
- File:fhnd = fopen(name, io_write);
- if (fhnd)
- {
- fwrite(fhnd, BOTSYNC_LOCK_STRING);
- fclose(fhnd);
- fhnd = fopen(name, io_read);
- if (fhnd)
- {
- if (fgetchar(fhnd, 0, false) == BOTSYNC_LOCK_CHAR)
- {
- fclose(fhnd);
- return true;
- }
- fclose(fhnd);
- }
- else
- {
- printf("BotSync error: Lock fail");
- }
- }
- return false;
- }
- static
- BotSync_ReleaseLock(bot, bool:read)
- {
- new
- name[BOTSYNC_FILE_LENGTH];
- format(name, sizeof (name), BOTSYNC_FILE);
- fremove(name);
- }
- static
- BSF:
- BotSync_Open(bot)
- {
- new
- name[BOTSYNC_FILE_LENGTH];
- format(name, sizeof (name), BOTSYNC_FOLDER "%03d." BOTSYNC_OUT_STR ".d", bot);
- return BSF:fopen(name, io_append);
- }
- #define BotSync_Write(%0,%1) \
- fwrite(File:%0, %1)
- #define BotSync_Close(%0) \
- fclose(File:%0)
- #endif
- #if defined BOTSYNC_IS_BOT
- static
- BS_g_MessageBuffer[BOTSYNC_MESSAGE_BUFFER][BOTSYNC_MESSAGE_LENGTH],
- BS_g_me;
- public
- BotSync_Tick()
- {
- if (Itter_Count(BotSync))
- {
- if (BotSync_GetLock(BS_g_me, false))
- {
- new
- BSF:fhnd = BotSync_Open(BS_g_me);
- if (fhnd)
- {
- new
- msg = YSI_gBotSyncS,
- nxt;
- while (msg != -1)
- {
- BotSync_Write(fhnd, BS_g_MessageBuffer[msg]);
- nxt = YSI_gBotSyncA[msg];
- YSI_gBotSyncA[msg] = -1;
- msg = nxt;
- }
- YSI_gBotSyncC = 0;
- YSI_gBotSyncS = -1;
- BotSync_Close(fhnd);
- }
- BotSync_ReleaseLock(BS_g_me, false);
- }
- }
- #if defined BOT_SYNC_CALLBACK
- new
- name[BOTSYNC_FILE_LENGTH];
- format(name, sizeof (name), BOTSYNC_FOLDER "%03d." BOTSYNC_IN_STR ".d", BS_g_me);
- if (fexist(name))
- {
- if (BotSync_GetLock(BS_g_me, true))
- {
- new
- File:fhnd = fopen(name, io_read);
- if (fhnd)
- {
- new
- str[BOTSYNC_MESSAGE_LENGTH];
- while (fread(fhnd, str))
- {
- new
- pos0 = -1;
- while (str[++pos0] > '\1') {}
- if (str[pos0] == '\1')
- {
- new
- pos1 = pos0;
- while (str[++pos1] >= ' ') {}
- str[pos0] = '\0';
- str[pos1] = '\0';
- BOT_SYNC_CALLBACK(-1, str, str[pos0 + 1]);
- }
- }
- fclose(fhnd);
- fremove(name);
- }
- BotSync_ReleaseLock(BS_g_me, true);
- }
- }
- #endif
- }
- public
- OnNPCConnect(myplayerid)
- {
- SetTimer("BotSync_Tick", 10, true);
- BS_g_me = myplayerid;
- BotSync_OnNPCConnect(myplayerid);
- }
- #define OnNPCConnect BotSync_OnNPCConnect
- forward
- BotSync_OnNPCConnect(myplayerid);
- public
- OnClientMessage(color, text[])
- {
- if (color)
- {
- return BotSync_OnClientMessage(color, text);
- }
- new
- pos0 = -1;
- while (text[++pos0] > '\1') {}
- if (text[pos0] == '\1')
- {
- text[pos0] = '\0';
- BOT_SYNC_CALLBACK(-1, text, text[pos0 + 1]);
- }
- return 0;
- }
- #define OnClientMessage BotSync_OnClientMessage
- forward
- BotSync_OnClientMessage(color, text[]);
- stock
- BotSync_Send(bot, type[], message[])
- {
- new
- slot = Itter_Free(BotSync);
- if (slot != -1)
- {
- if (strlen(type) + strlen(message) < BOTSYNC_MESSAGE_LENGTH - 3)
- {
- format(BS_g_MessageBuffer[slot], BOTSYNC_MESSAGE_LENGTH, "%s\1%s\n", type, message);
- Itter_Add(BotSync, slot);
- return 1;
- }
- }
- return 0;
- #pragma unused bot
- }
- #else
- #if defined BOTSYNC_SYNC_FS
- enum E_BOTSYNC_BUFFER
- {
- E_BOTSYNC_BOT,
- E_BOTSYNC_MESSAGE[BOTSYNC_MESSAGE_LENGTH]
- }
- static
- BS_g_MessageBuffer[BOTSYNC_MESSAGE_BUFFER][E_BOTSYNC_BUFFER];
- forward
- BotSync_Buffer(bot, type[], message[]);
- public
- BotSync_Tick()
- {
- new
- dun = -1,
- msg,
- last;
- do
- {
- last = -1;
- foreachex (BotSync, msg)
- {
- if (msg > dun)
- {
- new
- bot = BS_g_MessageBuffer[msg][E_BOTSYNC_BOT];
- if (BotSync_GetLock(bot, false))
- {
- new
- BSF:fhnd = BotSync_Open(bot);
- if (fhnd)
- {
- BotSync_Write(fhnd, BS_g_MessageBuffer[msg][E_BOTSYNC_MESSAGE]);
- new
- cur = YSI_gBotSyncA[msg],
- lst = msg;
- while (cur != -1)
- {
- if (BS_g_MessageBuffer[cur][E_BOTSYNC_BOT] == bot)
- {
- BotSync_Write(fhnd, BS_g_MessageBuffer[cur][E_BOTSYNC_MESSAGE]);
- YSI_gBotSyncA[lst] = YSI_gBotSyncA[cur];
- YSI_gBotSyncA[cur] = -1;
- cur = YSI_gBotSyncA[lst];
- --YSI_gBotSyncC;
- }
- else
- {
- lst = cur;
- cur = YSI_gBotSyncA[cur];
- }
- }
- BotSync_Close(fhnd);
- BotSync_ReleaseLock(bot, false);
- dun = msg;
- if (last == -1)
- {
- YSI_gBotSyncS = YSI_gBotSyncA[msg];
- }
- else
- {
- YSI_gBotSyncA[last] = YSI_gBotSyncA[msg];
- }
- YSI_gBotSyncA[msg] = -1;
- --YSI_gBotSyncC;
- break;
- }
- BotSync_ReleaseLock(bot, false);
- }
- }
- last = msg;
- }
- }
- while (msg != -1);
- foreach (Bot, bot)
- {
- new
- name[BOTSYNC_FILE_LENGTH];
- format(name, sizeof (name), BOTSYNC_FOLDER "%03d." BOTSYNC_IN_STR ".d", bot);
- if (fexist(name))
- {
- if (BotSync_GetLock(bot, true))
- {
- new
- File:fhnd = fopen(name, io_read);
- if (fhnd)
- {
- new
- str[BOTSYNC_MESSAGE_LENGTH];
- while (fread(fhnd, str))
- {
- new
- pos0 = -1;
- while (str[++pos0] > '\1') {}
- if (str[pos0] == '\1')
- {
- new
- pos1 = pos0;
- while (str[++pos1] >= ' ') {}
- str[pos0] = '\0';
- str[pos1] = '\0';
- CallRemoteFunction("OnBotSyncData", "iss", bot, str, str[pos0 + 1]);
- }
- }
- fclose(fhnd);
- fremove(name);
- }
- BotSync_ReleaseLock(bot, true);
- }
- }
- }
- }
- public
- BotSync_Buffer(bot, type[], message[])
- {
- // Buffer the message and send it later.
- if (isnull(type) || isnull(message))
- {
- return 0;
- }
- if (IsPlayerNPC(bot))
- {
- new
- slot = Itter_Free(BotSync);
- if (slot != -1)
- {
- if (strlen(type) + strlen(message) < BOTSYNC_MESSAGE_LENGTH - 3)
- {
- format(BS_g_MessageBuffer[slot][E_BOTSYNC_MESSAGE], BOTSYNC_MESSAGE_LENGTH, "%s\1%s\n", type, message);
- BS_g_MessageBuffer[slot][E_BOTSYNC_BOT] = bot;
- Itter_Add(BotSync, slot);
- return 1;
- }
- }
- }
- return 0;
- }
- #else
- stock
- BotSync_SendFast(bot, type[], message[])
- {
- if (IsPlayerNPC(bot))
- {
- if (strlen(type) + strlen(message) < BOTSYNC_MESSAGE_LENGTH - 3)
- {
- new
- str[BOTSYNC_MESSAGE_LENGTH];
- format(str, sizeof (str), "%s\1%s", type, message);
- SendClientMessage(bot, 0, str);
- return 1;
- }
- }
- return 0;
- }
- stock
- BotSync_Send(bot, type[], message[])
- {
- CallRemoteFunction("BotSync_Buffer", "iss", bot, type, message);
- }
- #endif
- #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement