/*********************************************************
 *          Bugblatter Script Extension - V3.3           *
 *********************************************************
 *                                                       *
 * This plug-in is linux & win32 friendly.               *
 *                                                       *
 * Version history                                       *
 *                                                       *
 * Version 3.3:                                          *
 *                                                       *
 *  - Removed warnings compiling on Admin Mod 2.50.56    *
 *                                                       *
 * Version 3.2:                                          *
 *                                                       *
 *  - Updated for language plugin version 3.3            *
 *                                                       *
 * Version 3.1:                                          *
 *                                                       *
 *  -  No change                                         *
 *                                                       *
 * Version 2.6:                                          *
 *                                                       *
 *  -  Added colour and timing settings for all          *
 *     messageex class on 2.51.xx alpha builds.          *
 *                                                       *
 * Version 2.5:                                          *
 *                                                       *
 *  -  Move prominent error messages in log              *
 *                                                       *
 * Version 2.4:                                          *
 *  -  Updated for adminmod 2.50.50                      *
 *  -  Searchs new style locations for default.script    *
 *  -  Does not return PLUGIN_FAILRE during init         *
 *  -  Works around bug in calling admin_command bb,,,   *
 *     from in a .cfg file saved in DOS format           *
 *                                                       *
 * Version 2.3:                                          *
 *  -  Checks values of server.cfg vars during init      *
 *  -  Supports exec to run client commands              *
 *                                                       *
 * Version 2.2:                                          *
 *  - Logd detection is not logged anymore               *
 *                                                       *
 * Version 2.1:                                          *
 *  - Multilingual                                       *
 *  - Updated for adminmod 2.50.37                       *
 *                                                       *
 * Version 2.0:                                          *
 *                                                       *
 *  - Initial release.                                   *
 *                                                       *
 *********************************************************/
 
#include <core>
#include <console>
#include <string>
#include <admin>
#include <adminlib>
#include <plugin>
#include "settings"
#include "language"
#include "clientio"
 
 
new g_Version[] ="3.3";
 
/* NOTE: This plugin does not contain any settings that should
 * be configured by changing the source */
 
#define MAX_LINE_LENGTH 300;
#define MAX_MAP_LENGTH 100;
 
#define DEFAULT_MODE 1;
#define MIN_MODE 0;
#define MAX_MODE 1;
 
#define DEFAULT_REPORT 1;
#define MIN_REPORT 0;
#define MAX_REPORT 1;
 
 
new MSG_REPORTTITLE[] = "Bugblatter script configuration:|Configuration du script Bugblatter:|Bugblatter Script Konfiguration:";
new MSG_SCRIPTDISABLED[] = " - Script execution is currently disabled (bbscript_mode)| - L'execution de script est actuellement desactivee (bbscript_mode)| - Script-Ausfuehrung ist momentan deaktiviert (bbscript_mode)";
new MSG_SCRIPTENABLED[] =  " - Script execution is currently enabled (bbscript_mode)| - L'execution de script est actuellement activee (bbscript_mode)| - Script-Ausfuehrung ist momentan aktiviert (bbscript_mode)";
new MSG_NOSCRIPTLOADED[] = " - No script loaded. (bbscript_load)| - Pas de script charge. (bbscript_load)| - Kein Script geladen. (bbscript_load)";
new MSG_SCRIPTLOADED[] = " - Script %1s loaded. (bbscript_load)| - Script %1s charge. (bbscript_load)| - Script %1s ist geladen. (bbscript_load)";
 
new MSG_SCRIPTFILEIS[] = "Script file is %1s:|Le fichier script est %1s:|Script-Datei ist %1s:";
new MSG_SCRIPTDISABLED2[] = "Script execution is currently disabled.|L'execution de script est actuellement desactivee.|Script-Ausfuehrung ist momentan deaktiviert";
 
/* Configuration variables */
new g_Report=DEFAULT_REPORT;   /* Automatically show report after command? */
new g_Mode=DEFAULT_MODE;       /* Is scripting enabled */
 
/* Status variables */
new g_Rounds=0;                /* Number of rounds before next line of script should run */
new g_Script[MAX_LINE_LENGTH];  /* Name of script to run */
new g_LineNum=1;               /* Current line in script */
new g_Timer=0;                 /* Current timer */
 
forward RegisterPlugin();
forward BBScriptMode(HLCommand,HLData,HLUserName,UserIndex);
forward BBScriptReset(HLCommand,HLData,HLUserName,UserIndex);
forward BBScriptReport(HLCommand,HLData,HLUserName,UserIndex);
forward BBScriptLoad(HLCommand,HLData,HLUserName,UserIndex);
forward BBScriptList(HLCommand,HLData,HLUserName,UserIndex);
forward ShowConfig(Force,UserIndex);
forward ProcessModeChange(OldMode);
forward ProcessScript();
forward ProcessWait(Line[]);
forward BBLogdWorldAction(HLCommand,HLData,HLUserName,UserIndex);
 
public plugin_init() {
  plugin_registerinfo("Bugblatter's Script Plugin","Runs a script of admin commands at defined intervals",g_Version);
 
  new fOK = checkAdminVoteAutostart();
  fOK = checkVaultOK() && fOK;
  if (fOK == 0) {
    return PLUGIN_CONTINUE;
  }
  /* No need to abort if this one fails */
  checkLanguage();
 
  /* Determine if a map specific script exists.  Otherwise check for the default.script file */
  new Current[MAX_MAP_LENGTH];
  currentmap(Current,MAX_MAP_LENGTH);
 
  strcpy(g_Script,"maps/",MAX_LINE_LENGTH);
  strcat(g_Script,Current,MAX_LINE_LENGTH);
  strcat(g_Script,".script",MAX_LINE_LENGTH);
 
  /* Register with logd */
  plugin_registercmd("bbscript_logdwa","BBLogdWorldAction",131072,"");
  exec("logd_reg 62 admin_command bbscript_logdwa",0);
 
  if (fileexists(g_Script) == 0) {
    if (getfilelocation(g_Script,"default.script")==0) {
      log("WARNING: plugin_blatt_script cannot find a map script or default.script");
      g_Script[0]=NULL_CHAR;
    }
    else {
      ProcessScript();
    }
  }
  else {
    ProcessScript();
  }
 
  language_init();
  RegisterPlugin();
  return PLUGIN_CONTINUE;
}
 
RegisterPlugin() {
  /* Register callbacks with admin mod */
  plugin_registercmd("bbscript_report","BBScriptReport",ACCESS_CONFIG,
                     "bbscript_report [ ^"on^" | ^"off^" ]: shows the scripting config, and enables/disable report after every command");
  plugin_registercmd("bbscript_reset","BBScriptReset",ACCESS_CONFIG,
                     "bbscript_reset: sets all script settings to defaults");
  plugin_registercmd("bbscript_mode","BBScriptMode",ACCESS_CONFIG,
         "bbscript_mode < ^"on^" | ^"off^" >: Enables / Disables runing .script files");
  plugin_registercmd("bbscript_list","BBScriptList",ACCESS_ALL,
         "bbscript_list: Shows the current list of scripted commands");
  plugin_registercmd("bbscript_load","BBScriptLoad",ACCESS_CONFIG,
         "bbscript_load <filename>: Loads a different script and enables the plugin");
 
  return 0;
}
 
 
public BBScriptMode(HLCommand,HLData,HLUserName,UserIndex) {
  new OldMode = g_Mode;
  if (readHLonoff(HLData,g_Mode,DEFAULT_MODE,MIN_MODE,MAX_MODE)) {
  writevaultnum("bbscript_mode",g_Mode);
  }
  ProcessModeChange(OldMode);
  return ShowConfig(0,UserIndex);
}
 
public BBScriptReset(HLCommand,HLData,HLUserName,UserIndex) {
  new OldMode = g_Mode;
  g_Mode=DEFAULT_MODE;
  g_LineNum=1;
  writevaultnum("bbscript_mode",g_Mode);
  ProcessModeChange(OldMode);
  return ShowConfig(0,UserIndex);
}
 
public BBScriptReport(HLCommand,HLData,HLUserName,UserIndex) {
  if (readHLonoff(HLData,g_Report,DEFAULT_REPORT,MIN_REPORT,MAX_REPORT)) {
    writevaultnum("bbscript_report",g_Report);
    ShowConfig(0,UserIndex);
  }
  else {
    ShowConfig(1,UserIndex);
  }
  return PLUGIN_HANDLED;
}
 
public BBScriptLoad(HLCommand,HLData,HLUserName,UserIndex) {
  new Data[MAX_DATA_LENGTH];
  safe_convert(HLData,Data,MAX_DATA_LENGTH);
 
  if (strstr(Data,".script") <= 0) {
    strcat(Data,".script",MAX_DATA_LENGTH);
  }
 
  if (fileexists(Data)) {
    strcpy(g_Script,Data,MAX_LINE_LENGTH);
    g_LineNum = 1;
    if (g_Timer) {
      kill_timer(g_Timer);
      g_Timer=0;
    }
    g_Rounds=0;
    g_Mode=1;
    ProcessScript();
  }
  else {
    selfmessage("File not found");
  }
 
  return PLUGIN_HANDLED;
}
 
public BBScriptList(HLCommand,HLData,HLUserName,UserIndex) {
  if (g_Mode ==0) {
    language_say(UserIndex,MSG_SCRIPTDISABLED2,print_type:print_console);
    return PLUGIN_HANDLED;
  }
 
  if ((strlen(g_Script)==0) || (fileexists(g_Script) == 0)) {
    language_say(UserIndex,MSG_NOSCRIPTLOADED,print_type:print_console);
    return PLUGIN_HANDLED;
  }
 
  new ReadCount=filesize(g_Script,fsize_unit:lines)+1;
  new i;
  new Line[MAX_LINE_LENGTH];
  new Msg[MAX_LINE_LENGTH];
 
  language_sayf(UserIndex,MSG_SCRIPTFILEIS,print_type:print_console,0,0,0,0,g_Script);
 
  for(i=0;i<ReadCount;i++) {
    /* File line numbers are indexed from 1, not 0, hence the +1 */
    readfile(g_Script,Line,i,MAX_LINE_LENGTH);
 
    if (i == g_LineNum-1) {
      strcpy(Msg,"-> ", MAX_LINE_LENGTH);
    }
    else {
      strcpy(Msg,"   ", MAX_LINE_LENGTH);
    }
 
    strtrim(Line," ^t",2);
    if (strlen(Line)>0) {
      strcat(Msg,Line,MAX_LINE_LENGTH);
      selfmessage(Msg);
    }
  }
  return PLUGIN_HANDLED;
}
 
 
ShowConfig(Force,UserIndex) {
  if ((Force==0) && (g_Report==0)) {
    return PLUGIN_HANDLED;
  }
 
  language_say(UserIndex,MSG_REPORTTITLE,print_type:print_console);
  if (g_Mode ==0) {
    language_say(UserIndex,MSG_SCRIPTDISABLED,print_type:print_console);
  }
  else if (g_Mode == 1) {
    language_say(UserIndex,MSG_SCRIPTENABLED,print_type:print_console);
  }
 
  if ((strlen(g_Script)==0) ||(fileexists(g_Script) == 0)) {
    language_say(UserIndex,MSG_NOSCRIPTLOADED,print_type:print_console);
  }
  else {
    language_sayf(UserIndex,MSG_SCRIPTLOADED,print_type:print_console,0,0,0,0,g_Script);
  }
  return PLUGIN_HANDLED;
}
 
ProcessModeChange(OldMode) {
  if ((g_Mode == 1) && (OldMode == 0)) {
    if (g_Rounds == 0) {
      ProcessScript();
    }
  }
 
  if ((g_Mode == 0) && (OldMode == 1)) {
    if (g_Timer != 0) {
      kill_timer(g_Timer);
      g_Timer =0;
    }
  }
}
 
public ProcessScript() {
  new Line[MAX_LINE_LENGTH];
  new Lines=filesize(g_Script,fsize_unit:lines)+1;
  new msg[MAX_TEXT_LENGTH];
  new fContinue=1;
  new i;
  new len;
  while(fContinue) {
    if (g_LineNum >= Lines) {
      g_LineNum = 1;
    }
 
    readfile(g_Script,Line,g_LineNum,MAX_LINE_LENGTH);
    g_LineNum++;
    strtrim(Line," ^t",2);
 
    if (strlen(Line)>0) {
      if (strstr(Line,"wait ")==0) {
        ProcessWait(Line);
        fContinue=0;
      }
      else if (strcasecmp(Line,"quit")==0) {
        snprintf(msg,MAX_TEXT_LENGTH,"[SCRIPT] quit",Line);
        log (msg);
        g_Script[0]=NULL_CHAR;
        fContinue=0;
      }
      else if (strstr(Line,"exec ") == 0) {
        len = strlen(Line);
        for(i=5;i<=len;i++) {
          Line[i-5] = Line[i];
        }
        Line[i-5] = NULL_CHAR;
        strtrim(Line," ^t",2);
        if (strlen(Line)>0) {
          safe_execall(Line);
        }
      }
      else if (strstr(Line,"admin_command ") == 0) {
        len = strlen(Line);
        new cmd[MAX_LINE_LENGTH];
        for(i=14;i<=len;i++) {
          Line[i-14] = Line[i];
        }
        Line[i-14] = NULL_CHAR;
 
        new pos = index(Line,' ');
        if (pos==-1) {
          snprintf(msg,MAX_TEXT_LENGTH,"[SCRIPT] Admin command: %s",Line);
          log (msg);
          plugin_exec(Line,"");
        }
        else {
          strncpy(cmd,Line,pos,MAX_LINE_LENGTH);
          pos++;
          cmd[pos]=NULL_CHAR;
          for(i=pos;i<=len;i++) {
            Line[i-pos] = Line[i];
          }
          Line[i-pos] = NULL_CHAR;
 
          snprintf(msg,MAX_TEXT_LENGTH,"[SCRIPT] Admin command: %s %s",cmd, Line);
          log (msg);
          plugin_exec(cmd,Line);
        }
      }
      else if (strstr(Line,"//")!=0) {
        snprintf(msg,MAX_TEXT_LENGTH,"[SCRIPT] Console command: %s",Line);
        log (msg);
        exec(Line);
      }
    }
  }
 
  return 0; /* Stops a compiler error - code never gets here */
}
 
ProcessWait(Line[]) {
  new Dummy[MAX_DATA_LENGTH];
  new Number[MAX_DATA_LENGTH];
  new Period[MAX_DATA_LENGTH];
  new msg[MAX_TEXT_LENGTH];
 
  new args=strsplit(Line," ",Dummy,MAX_DATA_LENGTH,Number,MAX_DATA_LENGTH,Period,MAX_DATA_LENGTH);
 
  if (args != 3) {
    snprintf(msg,MAX_TEXT_LENGTH,"%s, line %i contains an invalid wait command - script processing aborted.",g_Script,g_LineNum-1);
    configError(msg);
    return 0;
  }
 
  new Num = strtonum(Number);
  if (Num <1) {
    snprintf(msg,MAX_TEXT_LENGTH,"%s, line %i contains invalid wait value (%s) - script processing aborted.",g_Script,g_LineNum-1,Num);
    configError(msg);
    return 0;
  }
 
  if ((strcasecmp(Period,"minute")==0) || (strcasecmp(Period,"minutes")==0)) {
    g_Timer = set_timer("ProcessScript",Num*60,1,"");
    /*
      snprintf(msg,MAX_TEXT_LENGTH,"[SCRIPT] Wait %i minutes",Num);
      log (msg);*/
    return 1;
  }
  else if ((strcasecmp(Period,"second")==0) || (strcasecmp(Period,"seconds")==0)) {
    g_Timer = set_timer("ProcessScript",Num,1,"");
    /*
      snprintf(msg,MAX_TEXT_LENGTH,"[SCRIPT] Wait %i minutes",Num);
      log (msg);*/
    return 1;
  }
  else if ((strcasecmp(Period,"round")==0) || (strcasecmp(Period,"rounds")==0)) {
    /* snprintf(msg,MAX_TEXT_LENGTH,"[SCRIPT] Wait %i rounds",Num);
       log (msg);*/
    g_Rounds = Num;
    return 1;
  }
 
  snprintf(msg,MAX_TEXT_LENGTH,"%s, line %i contains invalid wait period (%s) - script processing aborted.",g_Script,g_LineNum-1,Period);
  configError(msg);
  return 0;
}
 
public BBLogdWorldAction(HLCommand,HLData,HLUserName,UserIndex) {
  new Data[MAX_DATA_LENGTH];
  safe_convert(HLData,Data,MAX_DATA_LENGTH);
 
  if (strmatch(Data,"Round_Start",11)==1) {
    if ((g_Rounds>0) && (g_Mode==1)) {
      g_Rounds--;
      /*      new msg[MAX_TEXT_LENGTH];
      snprintf(msg,MAX_TEXT_LENGTH,"[SCRIPT] %i rounds left",g_Rounds);
      log (msg);*/
      if (g_Rounds == 0) {
        ProcessScript();
      }
    }
  }
 
  return PLUGIN_HANDLED;
}