/********************************************************* * Bugblatter Language Extension - V3.4 * ********************************************************* * * * This plug-in is linux & win32 friendly. NOTE: Version * * 2.50.31 or later of adminmod is required. * * * * Version history * * * * Version 3.4: * * * * - Removed warnings compiling on Admin Mod 2.50.56 * * * * Version 3.3: * * * * - Fixed bug that broke the plugin on 32 player * * servers if the 32nd slot was used. NOTE: This * * fix means new versions of all plugins that use * * plugin_blatt_language. If you have used it in * * your own plugin, you simply need to recompile * * with the updated language.inc. * * * * - Validates that chosen language is withing range. * * When another plugin pops up a menu at the same * * time as this one it is possible for this plugin * * to read the wrong results. * * * * - Contains workaround for bugs in playerinfo when * * a player reconnects in a previously used slot * * that prevented the menu appearing and used the * * players team as their choice of language. * * * * - Fixed bug where plugin was not reading back mode * * and report settings after a map change * * * * Version 3.2: * * * * - Fixes to the german transalation strings for real * * this time :) Last time I put the comment in that * * there were fixes, but somehow forgo to copy any * * of the actual new strings. /me makes Homer noises * * * * Version 3.1: * * * * - Fixes to the german transalation strings * * * * Version 2.6: * * * * - Added colour and timing settings for all * * messageex class on 2.51.xx alpha builds. * * - Handles the menu being cancelled better * * - Support setinfo lang "<language>" setting * * * * Version 2.5: * * * * - Bugfix to default language selection * * - Removed menu display timing, and plugin no * * no longer uses logd for this. * * * * Version 2.4: * * * * - Updated for adminmod 2.50.50 * * - Doesn't return plugin failure during init * * - Works around bug in calling admin_command bb,,, * * from in a .cfg file saved in DOS format * * - Default language command added * * * * Version 2.3: * * * * - Checks values of server.cfg vars during init * * * * Version 2.2: * * * * - Logd detected messages aren't logged anymore * * * * Version 2.1: * * * * - Initial release. * * * *********************************************************/ #include <core> #include <console> #include <string> #include <admin> #include <adminlib> #include "settings" #include "clientio" #include "language" #include "connections" new g_Version[] = "3.4"; /* NOTE: This plugin does not contain any settings that should * be configured by changing the source */ #define DEFAULT_MODE 1; #define MIN_MODE 0; #define MAX_MODE 1; #define DEFAULT_REPORT 1; #define MIN_REPORT 0; #define MAX_REPORT 1; #define MAX_MENU_LENGTH 512; #define RECHECK_TIME 15; /* Current confgiuration */ new g_Mode = DEFAULT_MODE; new g_Report = DEFAULT_REPORT; new g_UserInMenu[MAX_PLAYERS]; /* Cached IDs from last map */ new g_AuthLanguage[MAX_PLAYERS]; new g_AuthID[MAX_PLAYERS][MAX_AUTHID_LENGTH]; new g_Registered=0; new g_Timer=0; new g_ConnectX[MAX_PLAYERS]; new g_ConnectY[MAX_PLAYERS]; new g_ConnectZ[MAX_PLAYERS]; new g_MSG_PROMPT[] = "Bugblatter multi-lingual configuration:| configuration multilingue Bugblatter:|Bugblatter mehrsprachige Konfiguration:"; new g_MSG_DISABLED[] = " - Language selection is currently disabled.(bblanguage_mode)| - Le choix de langue est actuellement neutralise.(bblanguage_mode)| - Sprachvorwahl ist z.Z. gesperrt (bblanguage_mode)"; new g_MSG_ENABLED[] = " - Language selection is currently enabled. (bblanguage_mode)| - Le choix de langue est actuellement permis.(bblanguage_mode)| - Sprachvorwahl ist z.Z. aktiv (bblanguage_mode)"; new g_MSG_DEFAULT[] = " - Default language option is %1i (bblanguage_default)|- L'option de lange par defaut est %1i (bblanguage_default)| - Voreingestellte Sprachoption ist %1i (bblanguage_default)"; new g_MSG_DEFAULTNEXTMAP[] = "Defaut language change will not take effect until the next map change|Le changement de langue par defaut ne prendra pas effet avant le prochain changement de map|Die Aenderung der voreingestellten Sprache ist bis zum naechsten Mapwechsel unwirksam"; forward BBLanguageMode(HLCommand,HLData,HLUserName,UserIndex); forward BBLanguageReset(HLCommand,HLData,HLUserName,UserIndex); forward BBLanguageReport(HLCommand,HLData,HLUserName,UserIndex); forward BBLanguageDefault(HLCommand,HLData,HLUserName,UserIndex); forward ShowConfig(Force,UserIndex); forward check_languages(); forward display_menu(Index,Name[]); forward menuselect(HLCommand,HLData,HLUserName,UserIndex); forward menucancel(HLCommand,HLData,HLUserName,UserIndex); forward writeauthcache(); forward readauthcache(); forward checkauthcache(AuthID[]); /* ********************************************************* * PLUGIN INITIALISATION * ********************************************************* */ public plugin_init() { plugin_registerinfo("Bugblatter's Multi-lingual Plugin","Allows other plugins to communicate with each player in their own language",g_Version); new fOK = checkVaultOK(); if (fOK == 0) { return PLUGIN_CONTINUE; } readvaultnum("bblanguage_mode",g_Mode,DEFAULT_MODE,MIN_MODE,MAX_MODE); readvaultnum("bblanguage_report",g_Report,DEFAULT_REPORT,MIN_REPORT,MAX_REPORT); /* bblanguage_default is read inside language_init */ readauthcache(); /* Register callbacks with admin mod */ language_init(); plugin_registercmd("bblanguage_report","BBLanguageReport",ACCESS_ALL, "bblanguage_report [ ^"on^" | ^"off^" ]: Shows the language config, and enables/disable report after every command"); plugin_registercmd("bblanguage_reset","BBLanguageReset",ACCESS_CONFIG, "bblanguage_reset: sets all language settings to defaults"); plugin_registercmd("bblanguage_mode","BBLanguageMode",ACCESS_CONFIG, "bblanguage_mode < ^"on^" | ^"off^" >: Enables / Disables language selection menus"); plugin_registercmd("bblanguage_default","BBLanguageDefault",ACCESS_CONFIG, "bblanguage_default <number>: Sets default language for server"); plugin_registercmd("say","HandleSay",ACCESS_ALL); plugin_registercmd("radio1","menucancel",ACCESS_ALL); plugin_registercmd("radio2","menucancel",ACCESS_ALL); plugin_registercmd("radio3","menucancel",ACCESS_ALL); plugin_registercmd("buy","menucancel",ACCESS_ALL); plugin_registercmd("buyequip","menucancel",ACCESS_ALL); plugin_registercmd("chooseteam","menucancel",ACCESS_ALL); plugin_registercmd("menuselect","menuselect",ACCESS_ALL); g_Registered=1; if (g_Mode==1) { g_Timer = set_timer("check_languages",15,1,""); } return PLUGIN_CONTINUE; } /* ********************************************************* * ADMINISTRATOR COMMAND HANDLER FUNCTIONS * ********************************************************* */ public BBLanguageDefault(HLCommand,HLData,HLUserName,UserIndex) { if (readHLnum(HLData,g_DefaultLanguage,DEFAULT_DEFAULT_LANGUAGE,MIN_DEFAULT_LANGUAGE,MAX_DEFAULT_LANGUAGE)) { writevaultnum("bblanguage_default",g_DefaultLanguage); language_say(UserIndex,g_MSG_DEFAULTNEXTMAP,print_type:print_console); } return ShowConfig(0,UserIndex); } public BBLanguageMode(HLCommand,HLData,HLUserName,UserIndex) { if (readHLonoff(HLData,g_Mode,DEFAULT_MODE,MIN_MODE,MAX_MODE)) { writevaultnum("bblanguage_mode",g_Mode); } return ShowConfig(0,UserIndex); } public BBLanguageReset(HLCommand,HLData,HLUserName,UserIndex) { g_Mode=DEFAULT_MODE; writevaultnum("bblanguage_mode",g_Mode); if (g_Timer!=0) { kill_timer(g_Timer); g_Timer=0; } if (g_Mode==1) { g_Timer = set_timer("check_languages",15,99999,""); } return ShowConfig(0,UserIndex); } public BBLanguageReport(HLCommand,HLData,HLUserName,UserIndex) { if (readHLonoff(HLData,g_Report,DEFAULT_REPORT,MIN_REPORT,MAX_REPORT)) { writevaultnum("bblanguage_report",g_Report); ShowConfig(0,UserIndex); } else { ShowConfig(1,UserIndex); } return PLUGIN_HANDLED; } public HandleSay(HLCommand,HLData,HLUserName,UserIndex) { new Data[MAX_DATA_LENGTH]; new User[MAX_NAME_LENGTH]; convert_string(HLData,Data,MAX_DATA_LENGTH); convert_string(HLUserName,User,MAX_DATA_LENGTH); strstripquotes(Data); if (streq(Data,"language")) { display_menu(UserIndex,User); return PLUGIN_HANDLED; } return PLUGIN_CONTINUE; } ShowConfig(Force,UserIndex) { if ((Force==0) && (g_Report==0)) { return PLUGIN_HANDLED; } language_say(UserIndex,g_MSG_PROMPT,print_type:print_console); if (g_Mode ==0) { language_say(UserIndex,g_MSG_DISABLED,print_type:print_console); } else if (g_Mode == 1) { language_say(UserIndex,g_MSG_ENABLED,print_type:print_console); } language_sayf(UserIndex,g_MSG_DEFAULT,print_type:print_console,0,0,0,0,g_DefaultLanguage); /* TODO: Report on player's languages */ return PLUGIN_HANDLED; } /* ********************************************************* * MENU SELECTION ON CONNECT FUNCTIONS * ********************************************************* */ public plugin_connect(HLUserName, HLIP, UserIndex) { if (g_Registered ==0) { return PLUGIN_FAILURE; } new Name[MAX_NAME_LENGTH]; safe_convert(HLUserName, Name, MAX_NAME_LENGTH); get_userorigin(Name,g_ConnectX[UserIndex],g_ConnectY[UserIndex],g_ConnectZ[UserIndex]); g_UserInMenu[UserIndex]=0; g_Languages[UserIndex-1]=64; return PLUGIN_CONTINUE; } public plugin_disconnect(HLUserName, UserIndex) { if (g_Registered ==0) { return PLUGIN_FAILURE; } set_timer("writeauthcache",3,1,""); return PLUGIN_CONTINUE; } public check_languages() { new c = maxplayercount(); new Name[MAX_NAME_LENGTH]; new dummy; new i; new wonid; new team; new dead; new AuthID[MAX_AUTHID_LENGTH]; new x; new y; new z; new delay=15; for(i=1;i<=c;i++) { /* Check if language is known */ if (g_Languages[i-1]!=64) { continue; } if (playerinfo(i,Name,MAX_NAME_LENGTH,dummy,wonid,team,dead,AuthID)) { /* Check player isn't a bot */ if (!ishuman(AuthID)) { continue; } /* Check if language is known from client setinfo */ g_Languages[i-1]=checkinfo(Name); if (g_Languages[i-1]!=64) { plugin_exec("language_update",g_Languages); continue; } /* Check if language is known from last map */ g_Languages[i-1]=checkauthcache(AuthID); if (g_Languages[i-1]!=64) { plugin_exec("language_update",g_Languages); continue; } /* Check if player has picked a team and is not still at connection co-ordinates - i.e. has spawned. */ get_userorigin(Name,x,y,z); if ((x!=g_ConnectX[i]) || (y!=g_ConnectY[i]) || (z!=g_ConnectZ[i])) { if ((team > 0) && (team < 5)) { /* Yes, display the menu */ display_menu(i,Name); } else { /* Has spawned but hasn't chosen team. Switch to fast checking mode * so menu appears before they start buying */ delay=2; } } } } g_Timer = set_timer("check_languages",delay,1,""); } display_menu(Index,Name[]) { new act_keys=7; new MenuText[MAX_MENU_LENGTH]; snprintf(MenuText, MAX_MENU_LENGTH, "Choose your language:^n^n1. English^n2. Francais^n3. Deutsch^n"); menu(Name,MenuText,act_keys); g_UserInMenu[Index]=1; return 0; } public menucancel(HLCommand,HLData,HLUserName,UserIndex) { if (g_UserInMenu[UserIndex]) { log("Menu cancelled"); if (g_Timer==0) { g_Timer=set_timer("check_languages",RECHECK_TIME,5,""); } g_UserInMenu[UserIndex]=0; } return PLUGIN_CONTINUE; } public menuselect(HLCommand,HLData,HLUserName,UserIndex){ if (g_Registered ==0) { return PLUGIN_FAILURE; } new Data[MAX_DATA_LENGTH]; safe_convert(HLData,Data,MAX_DATA_LENGTH); new Name[MAX_DATA_LENGTH]; safe_convert(HLUserName,Name,MAX_DATA_LENGTH); if (g_UserInMenu[UserIndex]==0) { return PLUGIN_CONTINUE; } g_UserInMenu[UserIndex]=0; new nLang = strtonum(Data); if ((nLang>0) && (nLang<4)) { g_Languages[UserIndex-1] = 64+nLang; new Msg[MAX_TEXT_LENGTH]; snprintf(Msg,MAX_TEXT_LENGTH,"User %i %s has selected language %s",UserIndex,Name,Data); log(Msg); /* record for the next map */ writeauthcache(); /* tell other plugins that use language.inc about the change */ plugin_exec("language_update",g_Languages); } else { plugin_message("WARNING: Language plugin recevied the result of another plugins menu."); } return PLUGIN_CONTINUE; } /* ********************************************************* * SUPPORT FUNCTIONS * ********************************************************* */ /* * Writes each players chosen language and WONID * to a cache file to all recovery on map change * */ public writeauthcache() { resetfile("languagecache.ini"); new c = maxplayercount(); new Name[MAX_NAME_LENGTH]; new dummy; new i; new wonid; new team; new dead; new AuthID[MAX_AUTHID_LENGTH]; new ln[MAX_TEXT_LENGTH]; for(i=1;i<=c;i++) { if (playerinfo(i,Name,MAX_NAME_LENGTH,dummy,wonid,team,dead,AuthID)) { /* Don't want to record bots or lan players */ if (wonid>0) { if (g_Languages[i-1]!=64) { snprintf(ln,MAX_TEXT_LENGTH,"%c%s",g_Languages[i-1],AuthID); writefile("languagecache.ini",ln); } } } } } /* Reads the woncache from the * last map into memory */ readauthcache() { new ReadCount=filesize("languagecache.ini",fsize_unit:lines)+1; if (ReadCount > MAX_PLAYERS) { ReadCount = MAX_PLAYERS; } new i; new buf[MAX_TEXT_LENGTH]; for(i=0;i<ReadCount;i++) { readfile("languagecache.ini",buf,i,MAX_TEXT_LENGTH); if (strlen(buf)>1) { g_AuthLanguage[i]=buf[0]; new j=1; while (buf[j]!=0) { buf[j-1]=buf[j]; j++; } buf[j-1]=0; strcpy(g_AuthID[i],buf,MAX_AUTHID_LENGTH); } } return 1; } /* Searches the woncache for a player's language */ checkauthcache(AuthID[]) { new i=0; while (i<MAX_PLAYERS) { if (strcmp(g_AuthID[i],AuthID) == 0) { g_AuthID[i][0]=0; /* Only retrieve a cached value once */ return g_AuthLanguage[i]; } i++; } return 64; } checkinfo(Name[]) { new Info[20]; if (get_userinfo(Name,"lang",Info,20)) { if (streq(Info,"english")) { return 65; } else if (streq(Info,"french") || streq(Info,"francais")) { return 66; } else if (streq(Info,"german") || streq(Info,"deutsch")) { return 67; } } return 64; }