root/trunk/twcore/src/twcore/core/HubBot.java

Revision 3841, 50.7 KB (checked in by Arobas+, 10 days ago)

bad copy/paste

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1package twcore.core;
2import java.io.BufferedReader;
3import java.io.File;
4import java.io.FileNotFoundException;
5import java.io.FileReader;
6import java.io.IOException;
7import java.util.Date;
8import java.util.HashSet;
9import java.util.LinkedHashMap;
10import java.util.TimerTask;
11
12import twcore.core.command.CommandInterpreter;
13import twcore.core.events.ArenaJoined;
14import twcore.core.events.FileArrived;
15import twcore.core.events.LoggedOn;
16import twcore.core.events.Message;
17import twcore.core.util.Tools;
18
19/**
20 * Bot designed to spawn other bots (both manually and automatically from
21 * autoload.cfg).  It also sets access privileges based on the server's access
22 * lists.  The hub bot is essential for the operation of all other bots
23 * in TWCore.
24 */
25public class HubBot extends SubspaceBot {
26    private BotQueue            m_botQueue;             // Queue of bots to spawn
27    private ThreadGroup         m_kingGroup;            // Thread grouping the
28                                                        // hub belongs to
29    private CommandInterpreter  m_commandInterpreter;   // Handles commands
30
31    private TimerTask           m_smartShutdownTask;    // Periodically disconnects idle bots before shutdown
32    private int                 m_smartShutdownRate = 10 * 1000;    // How often to check for idle bots, in ms
33
34    private TimerTask           m_billerDownTask;       // Periodically displays biller down message
35    private int                 m_billerDownRate = 5 * 60 * 1000;   // How often to display biller down msg, in ms
36
37    private long                                spawnutime;                             // Stores the unix timestamp when the bot gets spawned for !uptime use
38
39    /**
40     * Creates the hub bot's thread grouping, registers commands, sets up
41     * accepted events, and starts the bot queue thread.  Once HubBot has
42     * logged on (LoggedOn event received) it begins loading other bots.
43     * @param botAction Reference to BotAction object from Session
44     */
45    public HubBot( BotAction botAction ){
46
47        super( botAction );
48        m_kingGroup = new ThreadGroup( "KingGroup" );
49        m_commandInterpreter = new CommandInterpreter( botAction );
50        registerCommands();
51        EventRequester events = m_botAction.getEventRequester();
52        events.request( EventRequester.MESSAGE );
53        events.request( EventRequester.LOGGED_ON );
54        events.request( EventRequester.ARENA_JOINED );
55        events.request( EventRequester.FILE_ARRIVED );
56        try {
57            Thread.sleep( 5000 );
58        } catch( InterruptedException ie ){
59            Tools.printLog( "Interrupted exception while starting HubBot. (Should never occur!)" );
60        }
61        m_botQueue = new BotQueue( m_kingGroup, botAction );
62        m_botQueue.start();
63    }
64
65    /**
66     * Registers all commands needed for operation of the HubBot.
67     */
68    public void registerCommands(){
69        int acceptedMessages = Message.PRIVATE_MESSAGE | Message.REMOTE_PRIVATE_MESSAGE;
70       
71        // Bot+
72        int accessRequired = OperatorList.BOT_LEVEL; 
73        m_commandInterpreter.registerCommand( "!spawn", acceptedMessages, this, "handleSpawnMessage", accessRequired );
74
75        // Outsider+
76        accessRequired = OperatorList.OUTSIDER_LEVEL; 
77        m_commandInterpreter.registerCommand( "!help", acceptedMessages, this, "handleHelp", accessRequired );
78        m_commandInterpreter.registerCommand( "!listOnbots", acceptedMessages, this, "handleListBots", accessRequired );
79        m_commandInterpreter.registerCommand( "!waitinglist", acceptedMessages, this, "handleShowWaitingList", accessRequired );
80        m_commandInterpreter.registerCommand( "!billerdown", acceptedMessages, this, "handleBillerDownCommand", accessRequired );
81        m_commandInterpreter.registerCommand( "!listbots", acceptedMessages, this, "displayListBots", accessRequired );
82        // Moderator+
83        m_commandInterpreter.registerCommand( "!uptime", acceptedMessages, this, "handleUptimeCommand", accessRequired );
84        m_commandInterpreter.registerCommand( "!dbstatus", acceptedMessages, this, "handleDbStatus", accessRequired );
85        m_commandInterpreter.registerCommand( "!version", acceptedMessages, this, "handleVersion", accessRequired );
86       
87        // Highmod+
88        accessRequired = OperatorList.HIGHMOD_LEVEL; 
89        m_commandInterpreter.registerCommand( "!spawnmax", acceptedMessages, this, "handleSpawnMaxMessage", accessRequired );
90        m_commandInterpreter.registerCommand( "!spawnauto", acceptedMessages, this, "handleSpawnAutoMessage", accessRequired );
91        m_commandInterpreter.registerCommand( "!remove", acceptedMessages, this, "handleRemove", accessRequired );
92        m_commandInterpreter.registerCommand( "!removetype", acceptedMessages, this, "handleRemoveType", accessRequired );
93        m_commandInterpreter.registerCommand( "!reloadconf", acceptedMessages, this, "handleReloadConfiguration", accessRequired );
94       
95        // Smod+
96        accessRequired = OperatorList.SMOD_LEVEL;
97        m_commandInterpreter.registerCommand( "!updateaccess", acceptedMessages, this, "handleUpdateAccess", accessRequired );
98        m_commandInterpreter.registerCommand( "!listoperators", acceptedMessages, this, "handleListOperators", accessRequired );
99        m_commandInterpreter.registerCommand( "!recycleserver", acceptedMessages, this, "handleRecycleCommand", accessRequired );
100       
101        // Sysop+
102        accessRequired = OperatorList.SYSOP_LEVEL;
103        m_commandInterpreter.registerCommand( "!forcespawn", acceptedMessages, this, "handleForceSpawnMessage", accessRequired );
104        m_commandInterpreter.registerCommand( "!shutdowncore", acceptedMessages, this, "handleShutdownCommand", accessRequired );
105        m_commandInterpreter.registerCommand( "!smartshutdown", acceptedMessages, this, "handleSmartShutdownCommand", accessRequired );
106        m_commandInterpreter.registerCommand( "!shutdownidlebots", acceptedMessages, this, "handleShutdownIdleBotsCommand", accessRequired );
107        m_commandInterpreter.registerCommand( "!shutdownallbots", acceptedMessages, this, "handleShutdownAllBotsCommand", accessRequired );
108       
109        m_commandInterpreter.registerDefaultCommand( Message.PRIVATE_MESSAGE, this, "handleInvalidMessage" );
110        m_commandInterpreter.registerDefaultCommand( Message.REMOTE_PRIVATE_MESSAGE, this, "handleInvalidMessage" );
111    }
112
113    /**
114     * Runs necessary setup, loads all access lists, and adds all bots in
115     * autoload.cfg to the bot loading queue.
116     */
117    public void handleEvent( LoggedOn event ){
118        // Stores the unix timestamp for use with !uptime
119        spawnutime = new Date().getTime();
120
121        m_botAction.joinArena( m_botAction.getGeneralSettings().getString("Arena") );
122       
123        // This is for the Message class where the alertcommands are stored
124        m_botAction.sendUnfilteredPublicMessage( "*g*misc:alertcommand" );
125        m_botAction.sendUnfilteredPublicMessage( "?chat=" + m_botAction.getGeneralSettings().getString( "Chat name" ) );
126        initOperators();
127        autoSpawnBots(false);
128       
129    }
130   
131    /**
132     * Reads bot types from autoload.cfg and spawns the bots
133     */
134    private void autoSpawnBots(boolean checkAlreadySpawned) {
135        try {
136                FileReader reader = new FileReader( m_botAction.getCoreCfg( "autoload.cfg" ) );
137            BufferedReader buffer = new BufferedReader( reader );
138            LinkedHashMap<String, Integer> autoLoads = new LinkedHashMap<String, Integer>();
139            // using LinkedHashMap implementation so the order of autoload.cfg is used when spawning bots
140           
141            String line = "";
142           
143            while( (line = buffer.readLine()) != null ){
144                if( line == null || line.length() == 0 ){
145                    continue;
146                }
147               
148                if( !line.startsWith("#") && !line.startsWith("[") ){
149                    String bottype = line.trim().toLowerCase();
150                   
151                    // Add bot to TreeMap or increase the number of bots on the TreeMap
152                    if(autoLoads.containsKey(bottype)) {
153                        autoLoads.put(bottype, autoLoads.get(bottype)+1);
154                    } else {
155                        autoLoads.put(bottype, 1);
156                    }
157                }
158            }
159           
160            for(String bottype : autoLoads.keySet()) {
161                int number = autoLoads.get(bottype);
162                int alreadySpawned = 0;
163               
164                if(checkAlreadySpawned) {
165                    // Check the botQueue how many times the bot is already spawned
166                    alreadySpawned = m_botQueue.getBotCount(bottype);
167                }
168               
169                if(alreadySpawned < number) {
170                    for(int i = 0 ; i < (number - alreadySpawned) ; i++) {
171                        m_botQueue.spawnBot( bottype, null );
172                    }
173                }
174            }
175           
176            buffer.close();
177            reader.close();
178        } catch( FileNotFoundException fnfe ){
179            Tools.printStackTrace( "File not found: autoload.cfg  ;  ", fnfe );
180        } catch( IOException ioe) {
181            Tools.printStackTrace( "IOException occured while reading autoload.cfg : ", ioe);
182        }
183    }
184
185    /**
186     * Sends online message once arena has been joined successfully.
187     */
188    public void handleEvent( ArenaJoined event ){
189        m_botAction.sendChatMessage(m_botAction.getBotName() + " bot hub is now online.");
190    }
191
192    /**
193     * Sends any messages received to the command interpreter for handling.
194     * @param event Event received
195     */
196    public void handleEvent( Message event ){
197        m_commandInterpreter.handleEvent( event );
198    }
199
200    /**
201     * After receiving access lists, parses them using the operator list reader.
202     * @param event Event received
203     */
204    public void handleEvent( FileArrived event ){
205
206        // Auto assign operators after the file has been downloaded from subgame
207        if(     event.getFileName().equals( "moderate.txt" ) || 
208                event.getFileName().equals( "smod.txt" ) ||
209                event.getFileName().equals( "sysop.txt" )) {
210            m_botAction.getOperatorList().autoAssignFile( m_botAction.getDataFile( event.getFileName() ) );
211           
212        }
213    }
214
215    /**
216     * Clears all current access lists, and sets up the new lists based on access
217     * CFG files and the three server-based access lists.
218     */
219    public void initOperators(){
220        Tools.printLog("Initializing operators.cfg ...");
221       
222        try {
223            m_botAction.getOperatorList().clear();
224            m_botAction.getOperatorList().init( m_botAction.getCoreCfg("operators.cfg" ) );
225           
226        } catch (IOException ioe) {
227            System.err.println("FATAL: IO Exception occured while initializing operators from operators.cfg: "+ ioe.getMessage());
228            System.err.println("FATAL: No operators loaded, shutting down TWCore.");
229            m_botAction.die();
230        }
231       
232        Tools.printLog("Done initializing operators from operators.cfg");
233       
234        // Initiate process to auto-assign operators using the subgame staff files
235        m_botAction.sendUnfilteredPublicMessage( "*getfile sysop.txt" );
236        m_botAction.sendUnfilteredPublicMessage( "*getfile smod.txt" );
237        m_botAction.sendUnfilteredPublicMessage( "*getfile moderate.txt" );
238       
239       
240    }
241
242    /**
243     * Sends a line to bot development chat when a message not matching any
244     * valid command is received.
245     * @param messager Name of the player who sent the message
246     * @param message Text of the message
247     */
248    public void handleInvalidMessage( String messager, String message ){
249        m_botAction.sendChatMessage( 1, messager + " said this: " + message );
250    }
251
252    /**
253     * Removes a bot based on login name.  The case must be exact.
254     * @param messager Name of the player who sent the command
255     * @param message Bot to remove
256     */
257    public void handleRemove( String messager, String message ){
258        message = message.trim();
259
260        m_botAction.sendPrivateMessage( messager, "attempting to remove " + message + "...  " + (m_botAction.getGeneralSettings().getInt( "FastDisconnect" ) == 0?"  This may take 30 seconds or more.":"" ) );
261       
262        String operationSuccess = m_botQueue.removeBot( message, "force-disconnected by " + messager );
263        if( operationSuccess.startsWith("has disconnected") ) {
264            m_botAction.sendPrivateMessage( messager, "'" + message + "' removed successfully." );
265            m_botAction.sendChatMessage( 1, messager + " force-disconnected " + message + ".");
266            System.gc();
267        } else {
268            m_botAction.sendPrivateMessage( messager, "Bot has NOT been removed.  Use exact casing of the name, i.e., !remove TWDBot." );
269        }
270    }
271
272    /**
273     * Removes all bots of a given type.
274     * @param messager Name of the player who sent the command
275     * @param message Type of bot to remove
276     */
277    public void handleRemoveType( String messager, String message ){
278        message = message.trim();
279
280        m_botAction.sendPrivateMessage( messager, "Removing all bots of type " + message + "." +
281                (m_botAction.getGeneralSettings().getInt( "FastDisconnect" ) == 0?"  This may take on average 30 seconds per bot ...":"" ) );
282        m_botAction.sendChatMessage( 1, messager + " is force-disconnecting all bots of type " + message );
283        m_botQueue.hardRemoveAllBotsOfType( message, messager );
284        m_botAction.sendPrivateMessage( messager, "Removed all bots of type " + message + " (if possible).  Count reset to 0." );
285        System.gc();
286    }
287   
288    /**
289     * Reload the configuration for a type of bots, need to implement Reloadable
290     * @param messager Name of the player who sent the command
291     * @param message Type of bot to reload configuration
292     */
293    public void handleReloadConfiguration( String messager, String message ){
294        message = message.trim();
295        m_botQueue.reloadConfiguration( message, messager );
296    }
297
298    /**
299     * Displays in PM the list of bots waiting to be spawned.
300     * @param messager Name of the player who sent the request
301     * @param message Text of the message following the command
302     */
303    public void handleShowWaitingList( String messager, String message ){
304        m_botQueue.listWaitingList( messager );
305    }
306
307    /**
308     * Sends a request to update all access levels based on access files.
309     * @param messager Name of the player who sent the command
310     * @param message Text of the message
311     */
312    public void handleUpdateAccess( String messager, String message ){
313        initOperators();
314        m_botAction.sendSmartPrivateMessage( messager, "Updating access levels..." );
315        m_botAction.sendChatMessage( 1, "Updating access levels at " + messager + "'s request" );
316    }
317
318    /**
319     * Lists bot names of a given bot type
320     * @param messager Name of the player who sent the command
321     * @param message Bot type to list
322     */
323    public void handleListBots( String messager, String message ){
324        String className = message.trim();
325
326        if( className.length() > 0 ){
327            m_botQueue.listBots( className, messager );
328        } else {
329                m_botQueue.listBotTypes( messager );
330        }
331    }
332
333    /**
334     * Lists operators registered with this hub/bots
335     * @param messager Name of the player who sent the command
336     * @param message Bot type to list
337     */
338    public void handleListOperators( String messager, String message ){
339        int linelength = 63;
340
341        OperatorList list = m_botAction.getOperatorList();
342
343        // Owners
344        HashSet<String> owners = (list.getAllOfAccessLevel(OperatorList.OWNER_LEVEL));
345        m_botAction.sendSmartPrivateMessage( messager, "Owners ("+owners.size()+")");
346        if(owners.size() > 0) {
347                String pm = "  ";
348
349                for(String owner:owners) {
350                        if(pm.length() < linelength) {
351                                pm += owner + ", ";
352                        } else {
353                                m_botAction.sendSmartPrivateMessage(messager, pm);
354                                pm = "  ";
355                        }
356                }
357                if(pm.length()>0) {
358                        m_botAction.sendSmartPrivateMessage(messager, pm);
359                }
360        }
361
362        // Sysops
363        HashSet<String> sysops = (list.getAllOfAccessLevel(OperatorList.SYSOP_LEVEL));
364        m_botAction.sendSmartPrivateMessage( messager, " ");
365                m_botAction.sendSmartPrivateMessage( messager, "System operators ("+sysops.size()+")");
366        if(sysops.size() > 0) {
367                String pm = "  ";
368
369                for(String sysop:sysops) {
370                        if(pm.length() < linelength) {
371                                pm += sysop + ", ";
372                        } else {
373                                m_botAction.sendSmartPrivateMessage(messager, pm);
374                                pm = "  ";
375                        }
376                }
377                if(pm.length()>0) {
378                        m_botAction.sendSmartPrivateMessage(messager, pm);
379                }
380        }
381
382        // Smods
383        HashSet<String> smods = (list.getAllOfAccessLevel(OperatorList.SMOD_LEVEL));
384        m_botAction.sendSmartPrivateMessage( messager, " ");
385                m_botAction.sendSmartPrivateMessage( messager, "Super Moderators ("+smods.size()+")");
386        if(smods.size() > 0) {
387                String pm = "  ";
388
389                for(String smod:smods) {
390                        if(pm.length() < linelength) {
391                                pm += smod + ", ";
392                        } else {
393                                m_botAction.sendSmartPrivateMessage(messager, pm);
394                                pm = "  ";
395                        }
396                }
397                if(pm.length()>0) {
398                        m_botAction.sendSmartPrivateMessage(messager, pm);
399                }
400        }
401       
402        // Developers
403        HashSet<String> devs = (list.getAllOfAccessLevel(OperatorList.DEV_LEVEL));
404        m_botAction.sendSmartPrivateMessage( messager, " ");
405                m_botAction.sendSmartPrivateMessage( messager, "Developers ("+devs.size()+")");
406        if(devs.size() > 0) {
407                String pm = "  ";
408
409                for(String dev:devs) {
410                        if(pm.length() < linelength) {
411                                pm += dev + ", ";
412                        } else {
413                                m_botAction.sendSmartPrivateMessage(messager, pm);
414                                pm = "  ";
415                        }
416                }
417                if(pm.length()>0) {
418                        m_botAction.sendSmartPrivateMessage(messager, pm);
419                }
420        }
421       
422        // Highmods
423        HashSet<String> highmods = (list.getAllOfAccessLevel(OperatorList.HIGHMOD_LEVEL));
424        m_botAction.sendSmartPrivateMessage( messager, " ");
425                m_botAction.sendSmartPrivateMessage( messager, "High Moderators ("+highmods.size()+")");
426        if(highmods.size() > 0) {
427                String pm = "  ";
428
429                for(String highmod:highmods) {
430                        if(pm.length() < linelength) {
431                                pm += highmod + ", ";
432                        } else {
433                                m_botAction.sendSmartPrivateMessage(messager, pm);
434                                pm = "  ";
435                        }
436                }
437                if(pm.length()>0) {
438                        m_botAction.sendSmartPrivateMessage(messager, pm);
439                }
440        }
441
442        // Mods
443        HashSet<String> mods = (list.getAllOfAccessLevel(OperatorList.MODERATOR_LEVEL));
444        m_botAction.sendSmartPrivateMessage( messager, " ");
445                m_botAction.sendSmartPrivateMessage( messager, "Moderators ("+mods.size()+")");
446        if(mods.size() > 0) {
447                String pm = "  ";
448
449                for(String mod:mods) {
450                        if(pm.length() < linelength) {
451                                pm += mod + ", ";
452                        } else {
453                                m_botAction.sendSmartPrivateMessage(messager, pm);
454                                pm = "  ";
455                        }
456                }
457                if(pm.length()>0) {
458                        m_botAction.sendSmartPrivateMessage(messager, pm);
459                }
460        }
461
462        // ERs
463        HashSet<String> ers = (list.getAllOfAccessLevel(OperatorList.ER_LEVEL));
464        m_botAction.sendSmartPrivateMessage( messager, " ");
465                m_botAction.sendSmartPrivateMessage( messager, "ERs ("+ers.size()+")");
466        if(ers.size() > 0) {
467                String pm = "  ";
468
469                for(String er:ers) {
470                        if(pm.length() < linelength) {
471                                pm += er + ", ";
472                        } else {
473                                m_botAction.sendSmartPrivateMessage(messager, pm);
474                                pm = "  ";
475                        }
476                }
477                if(pm.length()>0) {
478                        m_botAction.sendSmartPrivateMessage(messager, pm);
479                }
480        }
481       
482        // Outsiders
483        HashSet<String> outsiders = (list.getAllOfAccessLevel(OperatorList.OUTSIDER_LEVEL));
484        m_botAction.sendSmartPrivateMessage( messager, " ");
485                m_botAction.sendSmartPrivateMessage( messager, "Outsiders ("+outsiders.size()+")");
486        if(outsiders.size() > 0) {
487                String pm = "  ";
488
489                for(String outsider:outsiders) {
490                        if(pm.length() < linelength) {
491                                pm += outsider + ", ";
492                        } else {
493                                m_botAction.sendSmartPrivateMessage(messager, pm);
494                                pm = "  ";
495                        }
496                }
497                if(pm.length()>0) {
498                        m_botAction.sendSmartPrivateMessage(messager, pm);
499                }
500        }
501
502        // Bots
503        HashSet<String> bots = (list.getAllOfAccessLevel(OperatorList.BOT_LEVEL));
504        m_botAction.sendSmartPrivateMessage( messager, " ");
505                m_botAction.sendSmartPrivateMessage( messager, "Operators that have identified themselves as bots ("+bots.size()+")");
506        if(bots.size() > 0) {
507                String pm = "  ";
508
509                for(String bot:bots) {
510                        if(pm.length() < linelength) {
511                                pm += bot + ", ";
512                        } else {
513                                m_botAction.sendSmartPrivateMessage(messager, pm);
514                                pm = "  ";
515                        }
516                }
517                if(pm.length()>0) {
518                        m_botAction.sendSmartPrivateMessage(messager, pm);
519                }
520        }
521    }
522
523    /**
524     * Returns the uptime of this bot
525     * @param messager Name of the player who sent the command
526     * @param message is irrelevant
527     */
528    public void handleUptimeCommand( String messager, String message ){
529        // Calculate the uptime by using the spawnutime variable (ms)
530        m_botAction.sendSmartPrivateMessage(messager, "Uptime: "+ Tools.getTimeDiffString(spawnutime, false) + ".");
531    }
532
533    /**
534     * Shuts down the core immediately.
535     * @param messager Name of the player who sent the command
536     * @param message is irrelevant
537     */
538    public void handleBillerDownCommand( String messager, String message ){
539        if( !m_botAction.getOperatorList().isModerator( messager ) ) {
540            if( !message.equals("off") && !message.equals(m_botAction.getGeneralSettings().getNonNullString("BillerDownPassword"))) {
541                m_botAction.sendSmartPrivateMessage( messager, "Invalid password." );
542                m_botAction.sendChatMessage( 1, messager + " provided an invalid password for sending out the biller down message.");
543                return;
544            }
545        }
546
547        if( message.equals("off") ) {
548            if( m_billerDownTask == null ) {
549                m_botAction.sendSmartPrivateMessage( messager, "There is no biller down zone message currently being sent out." );
550                return;
551            }
552            try {
553                if( m_botAction.cancelTask(m_billerDownTask) == false )
554                    m_billerDownTask.cancel();
555            } catch (Exception e) {
556                m_botAction.sendSmartPrivateMessage( messager, "Disable failed.  Try again in a few moments." );
557                return;
558            }
559            m_botAction.cancelTask(m_billerDownTask);
560            m_billerDownTask = null;
561            m_botAction.sendSmartPrivateMessage( messager, "Biller down zone message disabled.  '!billerdown <password>' to turn back on." );
562            m_botAction.sendChatMessage( "Biller down zone message disabled by " + messager + ".  '!billerdown <password>' to turn back on." );
563            return;
564        }
565
566        if( m_billerDownTask != null ) {
567            m_botAction.sendSmartPrivateMessage( messager, "Message is already being sent out.  Use '!billerdown off' to disable." );
568            return;
569        }
570
571        m_botAction.sendSmartPrivateMessage( messager, "Sending out the biller down zone message approximately every " + (m_billerDownRate / 60000.0) + " minutes.  '!billerdown off' to disable." );
572        m_botAction.sendChatMessage( "Biller down zone message initiated by " + messager + ".  Message sent out every " + (m_billerDownRate / 60000.0) + "minutes.  '!billerdown off' to disable." );
573        Tools.printLog( "Biller down zone message initiated by " + messager + "." );
574
575        m_billerDownTask = new TimerTask() {
576            public void run() {
577                m_botAction.sendZoneMessage( "NOTICE: The billing server (player database) is temporarily down (beyond our control).  ?commands (?chat etc) are disabled and entering players will have ^ before their name.  Please be patient until normal service is restored.", Tools.Sound.BEEP1 );
578            }
579        };
580        // Send first after one second (also confirming !billerdown command, while the rest every 5 minutes)
581        m_botAction.scheduleTaskAtFixedRate(m_billerDownTask, Tools.TimeInMillis.SECOND, m_billerDownRate);
582    }
583
584    /**
585     * Recycles the server if the player has the correct password.
586     * @param messager Name of the player who sent the command
587     * @param message is irrelevant
588     */
589    public void handleRecycleCommand( String messager, String message ){
590        if( !message.equals(m_botAction.getGeneralSettings().getNonNullString("RecyclePassword"))) {
591            m_botAction.sendSmartPrivateMessage( messager, "Invalid password." );
592            m_botAction.sendChatMessage( 1, messager + " provided an invalid password for recycling the server.");
593            return;
594        }
595        m_botAction.sendZoneMessage( "NOTICE: Server recycling all users to regain full functionality ... please log in again in a few moments. -TWStaff", Tools.Sound.BEEP1 );
596        m_botAction.sendUnfilteredPublicMessage("*recycle");
597    }
598
599    /**
600     * Shuts down the core immediately.
601     * @param messager Name of the player who sent the command
602     * @param message is irrelevant
603     */
604    public void handleShutdownCommand( String messager, String message ){
605        m_botAction.sendSmartPrivateMessage( messager, "Shutting down the core ..." +
606                (m_botAction.getGeneralSettings().getInt( "FastDisconnect" ) == 0?"  This may take on average 30 seconds per bot ...":"" ) );
607
608        m_botAction.sendChatMessage( 1, "--- CORE SHUTDOWN initiated by " + messager + " ---" );
609        System.out.println();
610        System.out.println( "=== Shutdown initiated ===" );
611        String upString = Tools.getTimeDiffString( spawnutime, true);
612        Tools.printLog( "Beginning shutdown by " + messager + ".");
613        Tools.printLog( "Total uptime: " + upString );
614        m_botQueue.shutdownAllBots();
615        m_botAction.sendChatMessage( 1, "--- Shutdown complete.  Uptime: " + upString + " ---" );
616        try {
617            Thread.sleep(3000);
618        } catch( InterruptedException e ){
619        }
620        m_botAction.die();
621    }
622
623    /**
624     * Shuts down the core gradually by disconnecting bots when they are no longer in use.
625     * @param messager Name of the player who sent the command
626     * @param message is irrelevant
627     */
628    public void handleSmartShutdownCommand( String messager, String message ){
629        m_botAction.sendSmartPrivateMessage( messager, "Beginning gradual shutdown of the core ..." );
630        m_botAction.sendChatMessage( 1, "--- SMART CORE SHUTDOWN initiated by " + messager + " ---" );
631        m_botAction.sendChatMessage( 1, "   (Bots will be disconnected as they become idle.)" );
632        System.out.println();
633        System.out.println( "=== Smart shutdown initiated ===" );
634        Tools.printLog( "Beginning smart shutdown by " + messager + ".");
635
636        m_smartShutdownTask = new TimerTask() {
637            public void run() {
638                if( m_botQueue.shutdownIdleBots() ) {
639                    String upString = Tools.getTimeDiffString( spawnutime, true);
640                    Tools.printLog( "Total uptime: " + upString );
641                    m_botAction.sendChatMessage( 1, "--- Smart Shutdown complete.  Uptime: " + upString + " ---" );
642                    this.cancel();
643                    try {
644                        Thread.sleep(3000);
645                    } catch( InterruptedException e ){
646                    }
647                    m_botAction.die();
648                }
649            }
650        };
651        m_botAction.scheduleTask(m_smartShutdownTask, 100, m_smartShutdownRate );
652
653    }
654
655    /**
656     * Shuts down any idle bots, without continuing to check for when busy bots become idle.
657     * @param messager Name of the player who sent the command
658     * @param message is irrelevant
659     */
660    public void handleShutdownIdleBotsCommand( String messager, String message ){
661        m_botAction.sendSmartPrivateMessage( messager, "Shutting down all idle bots ..." );
662        m_botAction.sendChatMessage( 1, "Idle bot shutdown initiated by " + messager + ".  All idle bots will be removed." );
663        Tools.printLog( "Idle bot shutdown by " + messager + ".");
664
665        m_botQueue.shutdownIdleBots();
666    }
667
668    /**
669     * Shuts down any idle bots, without continuing to check for when busy bots become idle.
670     * @param messager Name of the player who sent the command
671     * @param message is irrelevant
672     */
673    public void handleShutdownAllBotsCommand( String messager, String message ){
674        m_botAction.sendSmartPrivateMessage( messager, "Shutting down all bots ..." );
675        m_botAction.sendChatMessage( 1, "Full bot shutdown initiated by " + messager + ".  All bots will be removed, but the Hub will be left online." );
676        Tools.printLog( "Full bot shutdown by " + messager + ".");
677
678        m_botQueue.shutdownAllBots();
679    }
680
681    /**
682     * Sends an appropriate help message based on access privileges.
683     * @param messager Name of the player who sent the command
684     * @param message Text of the message
685     */
686    public void handleHelp( String messager, String message ) {
687        OperatorList operatorList = m_botAction.getOperatorList();
688        int accessLevel = operatorList.getAccessLevel(messager);
689       
690        int accessCommandNumber = m_commandInterpreter.getAllowedCommandsCount(accessLevel)-1; // excluding !help
691        int totalCommandsNumber = m_commandInterpreter.getCommandsCount()-1; // excluding !help
692        String argument = message.replace("!", "").trim();
693       
694        // Access: Sysop [lvl 5]
695        // You have access to 12 / 18 commands.
696        // +-------------------------==  BOT CONTROL  ==--------------------------+
697        // | !spawn  !spawnmax  !spawnauto  !forcespawn  !waitinglist  !listbots  |
698        // | !remove  !removetype  !reloadconf                                               |
699        // | !shutdowncore  !smartshutdown  !shutdownidlebots  !shutdownallbots   |
700        // |                                                                      |
701        // +----------------------==  ACCESS MANAGEMENT  ==-----------------------+
702        // | !updateaccess  !listoperators                                        |
703        // |                                                                      |
704        // +--------------------==  SERVER TROUBLESHOOTING  ==--------------------+
705        // | !billerdown  !recycleserver                                          |
706        // |                                                                      |
707        // +---------------------------==  STATUS  ==-----------------------------+
708        // | !uptime  !dbstatus                                                   |
709        // |                                                                      |
710        // +-----------------------------------------------------TWCore rev 4444--+
711        // Private message '!help <command>' for more information.
712       
713       
714        // Access: Sysop [lvl 5]
715        // You have access to 12 / 18 commands.
716        // -----------------------------------------------
717        // BOT CONTROL:      !spawn !spawnmax !spawnauto !forcespawn !waitinglist !listbots
718        //                   !remove !removetype !reloadconf
719        //                   !shutdowncore !smartshutdown !shutdownidlebots !shutdownallbots
720        // ACCESS CONTROL:   !updateaccess !listoperators
721        // SERVER TROUBLESH: !billerdown !recycleserver
722        // STATUS:           !uptime !dbstatus !version
723        // -----------------------------------------------
724        // Private message '!help <command>' for more information.
725       
726
727        if(argument.length() == 0) {
728                        m_botAction.sendSmartPrivateMessage( messager, "Access: "+operatorList.getAccessLevelName(accessLevel) );
729                        m_botAction.sendSmartPrivateMessage( messager, "You have access to "+accessCommandNumber+" / "+totalCommandsNumber+" commands.");
730               
731                        m_botAction.sendSmartPrivateMessage( messager, "-----------------------------------------------");
732                if(operatorList.isOutsider(messager) && !operatorList.isHighmod(messager)) {
733                        m_botAction.sendSmartPrivateMessage( messager, "BOT CONTROL:      !spawn !waitinglist !listbots !listonbots");
734                }
735                if(operatorList.isHighmod(messager) && !operatorList.isSysop(messager)) {
736                        m_botAction.sendSmartPrivateMessage( messager, "BOT CONTROL:      !spawn !spawnmax !spawnauto !waitinglist !listbots !listonbots");
737                        m_botAction.sendSmartPrivateMessage( messager, "                  !remove !removetype !reloadconf");
738                }
739                if(operatorList.isSysop(messager)) {
740                        m_botAction.sendSmartPrivateMessage( messager, "BOT CONTROL:      !spawn !spawnmax !spawnauto !forcespawn !waitinglist !listbots !listonbots");
741                        m_botAction.sendSmartPrivateMessage( messager, "                  !remove !removetype !reloadconf");
742                        m_botAction.sendSmartPrivateMessage( messager, "                  !shutdowncore !smartshutdown !shutdownidlebots !shutdownallbots");
743                }
744                if(operatorList.isSmod(messager)) {
745                        m_botAction.sendSmartPrivateMessage( messager, "ACCESS CONTROL:   !updateaccess !listoperators");
746                }
747                if(operatorList.isOutsider(messager) && !operatorList.isSmod(messager))
748                        m_botAction.sendSmartPrivateMessage( messager, "SERVER TROUBLESH: !billerdown");
749                if(operatorList.isSmod(messager))
750                        m_botAction.sendSmartPrivateMessage( messager, "SERVER TROUBLESH: !billerdown !recycleserver");
751                if(operatorList.isModerator(messager)) {
752                        m_botAction.sendSmartPrivateMessage( messager, "STATUS:           !uptime !dbstatus !version");
753                }
754                        m_botAction.sendSmartPrivateMessage( messager, "-----------------------------------------------");
755                        m_botAction.sendSmartPrivateMessage( messager, "Message ::!help <command> for more information.");
756                       
757        } else {
758                // Command details
759                // !help
760                if(argument.equalsIgnoreCase("help")) {
761                        m_botAction.sendSmartPrivateMessage( messager , "Displays available commands or shows extra information when a command has been specified.");
762                        m_botAction.sendSmartPrivateMessage( messager , "Symbols used in command information: <> required  [] optional  -s[=assign] switches");
763                        m_botAction.sendSmartPrivateMessage( messager , "Access required: " + operatorList.getAccessLevelName(OperatorList.OUTSIDER_LEVEL));
764                        m_botAction.sendSmartPrivateMessage( messager , " !help [command]");
765                }
766                // ----- Bot control command details ------
767                // !spawn
768                else if (argument.equalsIgnoreCase("spawn")) {
769                        m_botAction.sendSmartPrivateMessage( messager , "Spawns a new bot of the specified bot type.");
770                        m_botAction.sendSmartPrivateMessage( messager , "Access required: " + operatorList.getAccessLevelName(OperatorList.OUTSIDER_LEVEL));
771                        m_botAction.sendSmartPrivateMessage( messager , " !spawn <bot type>");
772                       
773                }
774                // !spawnmax
775                else if (argument.equalsIgnoreCase("spawnmax")) {
776                        m_botAction.sendSmartPrivateMessage( messager , "Spawns the maximum allowed number of bots of the specified bot type.");
777                        m_botAction.sendSmartPrivateMessage( messager , "Access required: " + operatorList.getAccessLevelName(OperatorList.HIGHMOD_LEVEL));
778                        m_botAction.sendSmartPrivateMessage( messager , " !spawnmax <bot type>");
779                }
780                // !spawnauto
781                else if (argument.equalsIgnoreCase("spawnauto")) {
782                        m_botAction.sendSmartPrivateMessage( messager , "Spawns all bots of the specified bot type that should already be spawned on startup.");
783                        m_botAction.sendSmartPrivateMessage( messager , "Access required: " + operatorList.getAccessLevelName(OperatorList.HIGHMOD_LEVEL));
784                        m_botAction.sendSmartPrivateMessage( messager , " !spawnauto <bot type>");
785                }
786                // !forcespawn
787                else if (argument.equalsIgnoreCase("forcespawn")) {
788                        m_botAction.sendSmartPrivateMessage( messager , "Force-spawns a bot (ignore count) of specified bot type using the specified username and password.");
789                        m_botAction.sendSmartPrivateMessage( messager , "Access required: " + operatorList.getAccessLevelName(OperatorList.SYSOP_LEVEL));
790                        m_botAction.sendSmartPrivateMessage( messager , " !forcespawn <bot type> <username> <password>  ()");
791                }
792                // !waitinglist
793                else if (argument.equalsIgnoreCase("waitinglist")) {
794                        m_botAction.sendSmartPrivateMessage( messager , "Displays the list of bots that are waiting to be spawned.");
795                        m_botAction.sendSmartPrivateMessage( messager , "Access required: " + operatorList.getAccessLevelName(OperatorList.OUTSIDER_LEVEL));
796                        m_botAction.sendSmartPrivateMessage( messager , " !waitinglist");
797                }
798                // !listbots
799                else if (argument.equalsIgnoreCase("listbots")) {
800                        m_botAction.sendSmartPrivateMessage( messager , "Returns current spawned bot types or the spawned bots of specified bot type, including arena and who spawned it.");
801                        m_botAction.sendSmartPrivateMessage( messager , "Access required: " + operatorList.getAccessLevelName(OperatorList.OUTSIDER_LEVEL));
802                        m_botAction.sendSmartPrivateMessage( messager , " !listbots [bot type]");
803                }
804                // !remove
805                else if (argument.equalsIgnoreCase("remove")) {
806                        m_botAction.sendSmartPrivateMessage( messager , "Forces a removal of the specified bot from the zone.");
807                        m_botAction.sendSmartPrivateMessage( messager , "Note: You must use exact casing for the <botname>. For example, 'TWDBot'");
808                        m_botAction.sendSmartPrivateMessage( messager , "Access required: " + operatorList.getAccessLevelName(OperatorList.HIGHMOD_LEVEL));
809                        m_botAction.sendSmartPrivateMessage( messager , " !remove <botname>");
810                }
811                // !removetype
812                else if (argument.equalsIgnoreCase("removetype")) {
813                        m_botAction.sendSmartPrivateMessage( messager , "Forces a removal of all bots of the specified type from the zone and resets the bot's count.");
814                        m_botAction.sendSmartPrivateMessage( messager , "Access required: " + operatorList.getAccessLevelName(OperatorList.HIGHMOD_LEVEL));
815                        m_botAction.sendSmartPrivateMessage( messager , " !removetype <bottype>");
816                }
817                // !reloadconf
818                else if (argument.equalsIgnoreCase("reloadconf")) {
819                        m_botAction.sendSmartPrivateMessage( messager , "Reload the configuration for a type of bot.");
820                        m_botAction.sendSmartPrivateMessage( messager , "Access required: " + operatorList.getAccessLevelName(OperatorList.HIGHMOD_LEVEL));
821                        m_botAction.sendSmartPrivateMessage( messager , " !reloadconf <bot type>");
822                }
823                // !shutdowncore
824                else if (argument.equalsIgnoreCase("shutdowncore")) {
825                        m_botAction.sendSmartPrivateMessage( messager , "Performs a clean shutdown of all the bots and the entire core. Disable restart scripts first.");
826                        m_botAction.sendSmartPrivateMessage( messager , "Access required: " + operatorList.getAccessLevelName(OperatorList.SYSOP_LEVEL));
827                        m_botAction.sendSmartPrivateMessage( messager , " !shutdowncore");
828                }
829                // !smartshutdown
830                else if (argument.equalsIgnoreCase("smartshutdown")) {
831                        m_botAction.sendSmartPrivateMessage( messager , "Shuts down all bots as they become idle, then shuts down the core.");
832                        m_botAction.sendSmartPrivateMessage( messager , "Access required: " + operatorList.getAccessLevelName(OperatorList.SYSOP_LEVEL));
833                        m_botAction.sendSmartPrivateMessage( messager , " !smartshutdown");
834                }
835                // !shutdownidlebots
836                else if (argument.equalsIgnoreCase("shutdownidlebots")) {
837                        m_botAction.sendSmartPrivateMessage( messager , "Kills all idle bots, leaving any running bots and the hub online.");
838                        m_botAction.sendSmartPrivateMessage( messager , "Access required: " + operatorList.getAccessLevelName(OperatorList.SYSOP_LEVEL));
839                        m_botAction.sendSmartPrivateMessage( messager , " !shutdownidlebots");
840                }
841                // !shutdownallbots
842                else if (argument.equalsIgnoreCase("shutdownallbots")) {
843                        m_botAction.sendSmartPrivateMessage( messager , "Kills all running bots, leaving the hub online.");
844                        m_botAction.sendSmartPrivateMessage( messager , "Access required: " + operatorList.getAccessLevelName(OperatorList.SYSOP_LEVEL));
845                        m_botAction.sendSmartPrivateMessage( messager , " !shutdownallbots");
846                }
847                // !updateaccess
848                else if (argument.equalsIgnoreCase("updateaccess")) {
849                        m_botAction.sendSmartPrivateMessage( messager , "Rereads the moderate.txt, smod.txt, and sysop.txt server files so that all bot access levels are updated.");
850                        m_botAction.sendSmartPrivateMessage( messager , "Access required: " + operatorList.getAccessLevelName(OperatorList.SMOD_LEVEL));
851                        m_botAction.sendSmartPrivateMessage( messager , " !updateaccess");
852                }
853                // !listoperators
854                else if (argument.equalsIgnoreCase("listoperators")) {
855                        m_botAction.sendSmartPrivateMessage( messager , "Lists all registered operators on this bot and bot spawns.");
856                        m_botAction.sendSmartPrivateMessage( messager , "Access required: " + operatorList.getAccessLevelName(OperatorList.SMOD_LEVEL));
857                        m_botAction.sendSmartPrivateMessage( messager , " !listoperators");
858                }
859                // !billerdown
860                else if (argument.equalsIgnoreCase("billerdown")) {
861                        m_botAction.sendSmartPrivateMessage( messager , "Sends periodic message about biller being down. Moderators and higher are not required to enter a <password>.");
862                        m_botAction.sendSmartPrivateMessage( messager , "Specify 'off' to disable the periodic advertisement.");
863                        m_botAction.sendSmartPrivateMessage( messager , "Access required: " + operatorList.getAccessLevelName(OperatorList.OUTSIDER_LEVEL));
864                        m_botAction.sendSmartPrivateMessage( messager , " !billerdown <password>");
865                        m_botAction.sendSmartPrivateMessage( messager , " !billerdown off");
866                }
867                // !recycleserver
868                else if (argument.equalsIgnoreCase("recycleserver")) {
869                        m_botAction.sendSmartPrivateMessage( messager , "Recycles the server after correct password is given.");
870                        m_botAction.sendSmartPrivateMessage( messager , "Access required: " + operatorList.getAccessLevelName(OperatorList.SMOD_LEVEL));
871                        m_botAction.sendSmartPrivateMessage( messager , " !recycleserver <password>");
872                }
873                // !uptime
874                else if (argument.equalsIgnoreCase("uptime")) {
875                        m_botAction.sendSmartPrivateMessage( messager , "Returns the current uptime of this core.");
876                        m_botAction.sendSmartPrivateMessage( messager , "Access required: " + operatorList.getAccessLevelName(OperatorList.MODERATOR_LEVEL));
877                        m_botAction.sendSmartPrivateMessage( messager , " !uptime");
878                }
879                // !dbstatus
880                else if (argument.equalsIgnoreCase("dbstatus")) {
881                        m_botAction.sendSmartPrivateMessage( messager , "Shows status of database connections.");
882                        m_botAction.sendSmartPrivateMessage( messager , "Access required: " + operatorList.getAccessLevelName(OperatorList.MODERATOR_LEVEL));
883                        m_botAction.sendSmartPrivateMessage( messager , " !dbstatus");
884                }
885                // !version
886                else if (argument.equalsIgnoreCase("version")) {
887                        m_botAction.sendSmartPrivateMessage( messager , "Shows the revision number of this bot.");
888                        m_botAction.sendSmartPrivateMessage( messager , "Access required: " + operatorList.getAccessLevelName(OperatorList.MODERATOR_LEVEL));
889                        m_botAction.sendSmartPrivateMessage( messager , " !version");
890                }
891                else {
892                        m_botAction.sendSmartPrivateMessage( messager , "Syntax error. Please message !help <command> for more information.");
893                }
894        }
895    }
896
897    /**
898     * Spawns a bot of a given type.  User interface wrapper for spawn().
899     * @param messager Name of the player who sent the command
900     * @param message Bot type to spawn
901     */
902    public void handleSpawnMessage( String messager, String message ){
903        String className = message.trim();
904       
905        if( className.length() > 0 ){
906            m_botQueue.spawnBot( className, messager );
907        } else {
908            m_botAction.sendSmartPrivateMessage( messager, "Usage: !spawn <bot type>" );
909        }
910    }
911
912    /**
913     * Forces the spawn of a bot of a given type by manually supplying a login.
914     * @param messager Name of the player who sent the command
915     * @param message Bot to spawn and relevant login info
916     */
917    public void handleForceSpawnMessage( String messager, String message ){
918        String args[] = message.split( " " );
919        if( args.length == 3 ) {
920            String className = args[0];
921            String login = args[1];
922            String password = args[2];
923            m_botQueue.spawnBot( className, login, password, messager );
924        } else {
925            m_botAction.sendSmartPrivateMessage( messager, "Usage: !forcespawn <bot type> <login> <password>" );
926        }
927    }
928   
929    /**
930     * Spawns the maximum number of a bot of a given type.
931     * @param messager Name of the player who sent the command
932     * @param message Bot type to spawn
933     */
934    public void handleSpawnMaxMessage( String messager, String message ){
935        String bottype = message.toLowerCase().trim();
936        BotSettings botInfo = m_botAction.getCoreData().getBotConfig(bottype);
937        Integer maxBots = botInfo.getInteger("Max Bots");
938       
939        if( botInfo == null ){
940            m_botAction.sendChatMessage( 1, messager + " tried to spawn bot of type " + message + ".  Invalid bot type or missing CFG file." );
941            m_botAction.sendSmartPrivateMessage( messager, "That bot type does not exist, or the CFG file for it is missing." );
942            return;
943        }
944        if( maxBots == null ){
945            m_botAction.sendChatMessage( 1, messager + " tried to spawn bot of type " + message + ".  Invalid settings file. (MaxBots improperly defined)" );
946            m_botAction.sendSmartPrivateMessage( messager, "The CFG file for that bot type is invalid. (MaxBots improperly defined)" );
947            return;
948        }
949        if( m_botQueue.getBotCount(message.toLowerCase()) >= maxBots){
950                m_botAction.sendChatMessage( 1, messager + " tried to spawn a new bot of type " + message + ".  Maximum number already reached (" + maxBots + ")");
951                m_botAction.sendSmartPrivateMessage( messager, "Maximum number of bots of this type (" + maxBots + ") has been reached." );
952                return;
953        }
954        m_botAction.sendSmartPrivateMessage( messager, "Spawning the maximum allowed number bots of type " + message.toLowerCase());
955        m_botAction.sendChatMessage( 1, messager + " is in queue to spawn the maximum allowed number bots of type " + message.toLowerCase());
956       
957        if( bottype.length() > 0 ) {
958            while(m_botQueue.getBotCount(bottype) < maxBots)
959                m_botQueue.spawnBot( bottype, null);
960        } else {
961            m_botAction.sendSmartPrivateMessage( messager, "Usage: !spawnmax <bot type>" );
962        }
963    }
964   
965    /**
966     * Spawns all bots on the autoloader that aren't currently spawned.
967     * @param messager
968     * @param message
969     */
970    public void handleSpawnAutoMessage( String messager, String message ){
971        m_botAction.sendSmartPrivateMessage( messager, "Spawning all bots from the autoloader that are not currently spawned.");
972        m_botAction.sendChatMessage( 1, messager + " is in queue to spawn all bots from the autoloader.");
973       
974        autoSpawnBots(true);
975       
976        m_botAction.sendSmartPrivateMessage( messager, "Done spawning all bots from the autoloader.");
977    }
978   
979    /**
980     * Displays the current SQL pool status.
981     * @param messager
982     * @param message
983     */
984    public void handleDbStatus( String messager, String message ) {
985        m_botAction.smartPrivateMessageSpam( messager, m_botAction.getCoreData().getSQLManager().getPoolStatus() );
986    }
987   
988    /**
989     * Displays the revision number of this file
990     * @param messager
991     * @param message
992     */
993    public void handleVersion( String messager, String message ) {
994        // Sample output of Revision keyword: $Revision$
995        String version = "$Revision$".substring(11).replace(" $","");
996        m_botAction.sendSmartPrivateMessage( messager , "TWCore revision "+version);
997        m_botAction.sendSmartPrivateMessage( messager , "More information about the latest change on http://www.twcore.org/changeset/"+version);
998    }
999   
1000    public void displayListBots(String name, String message){
1001        //method to display the list of bots from the .txt files
1002        try {
1003           
1004            String botname = m_botAction.getBotName();
1005           
1006            if(botname.equals("TWCore")){
1007                String[] twcore = {
1008                        "------------------------------------",
1009                        "=========== TWCore =================",
1010                        "List of bots that can be spawned:",
1011                        "- Use !spawn <typebot> to spawn it -",
1012                        "------- NickName / typebot ---------",
1013                        " ",
1014                        "Staffbot - [staffbot]",
1015                        "Zonerbot - [zonerbot]",
1016                        "Robohelp - [robohelp]",
1017                        "MessageBot - [messagebot]",
1018                        "Radiobot - [radiobot]",
1019                        "Pubbot - [pubbot]",
1020                        "Pubhub - [pubhub]",
1021                        "Banner Boy - [bannerboy]"
1022                };
1023                m_botAction.remotePrivateMessageSpam(name, twcore);
1024                }
1025           
1026            else if(botname.equals("TWCore-Events")){
1027                String[] twcoreEvents = {
1028                        "------------------------------------",
1029                        "========= TWCore-Events ============",
1030                        " ",
1031                        "List of bots that can be spawned:",
1032                        " ",
1033                        "- Use !spawn <typebot> to spawn it -",
1034                        " ",
1035                        "------- NickName / typebot ---------",
1036                        " ",
1037                        "RoboBot* - [multibot]",
1038                        "TWBot1 / TWBot2 - [elim]",
1039                        "Basebot/Wbduelbot/Javduelbot/Spiderduelbot - [bwjsbot]",
1040                        "RoboBoy/RoboGirl - [purepubbot]"
1041                };
1042                m_botAction.remotePrivateMessageSpam(name, twcoreEvents);
1043            }
1044           
1045            else if(botname.equals("TWCore-League")){
1046                String[] twcoreLeague = {
1047                        "------------------------------------",
1048                        "========= TWCore-League ============",
1049                        " ",
1050                        "List of bots that can be spawned:",
1051                        " ",
1052                        "- Use !spawn <typebot> to spawn it -",
1053                        " ",
1054                        "------- NickName / typebot ---------",
1055                        "",
1056                        "DuelBot - [duelbot]",
1057                        "MatchBot* - [matchbot]",
1058                        "TWDBot - [twdbot]",
1059                        "Tournybot - [tournybot]",
1060                        "TWDBot - [twdbot]",
1061                        "TWLBot* - [twl]"
1062                };
1063                m_botAction.remotePrivateMessageSpam(name, twcoreLeague);
1064            }
1065           
1066        } catch(Exception e){
1067            e.printStackTrace();
1068            m_botAction.sendPrivateMessage(name, "Exception.");
1069        }
1070    }
1071}
Note: See TracBrowser for help on using the browser.