Games-Axmud

 view release on metacpan or  search on metacpan

lib/Games/Axmud/Client.pm  view on Meta::CPAN

            # -------

            # Registry list of plugins (.pm files) that should be loaded as plugins at startup. Each
            #   item in the list is the full file path
            initPluginList              => [],          # [config]
            # Registry hash of plugins (.pm files) that have been loaded, in the form
            #   $pluginHash{plugin_name} = blessed_reference_to_plugin_object
            pluginHash                  => {},
            # Registry hash of client commands that are created when a plugin is loaded, in the form
            #   $pluginCmdHash{command_name} = plugin_name
            # ...where 'command_name' matches a key in $self->clientCmdHash (e.g. 'about') and
            #   'plugin_name' matches a key in $self->pluginHash
            # NB If a (built-in) client command of the same name already exists, it is replaced. If
            #   the plugin is later disabled, the original command is restored. If the plugin is
            #   then re-enabled, the original command is again replaced, and so on. This works very
            #   well as long as the plugins you load don't themselves have client commands of the
            #   same name, so try to avoid that
            pluginCmdHash               => {},
            # Registry hash of tasks that are added when a plugin is loaded, in the form
            #   $pluginTaskHash{task_name} = plugin_name
            # ...where 'task_name' matches the task's standard name (a key in
            #   $self->taskPackageHash) and 'plugin_name' matches a key in $self->pluginHash
            # NB Tasks with the same name as existing tasks (built-in, or from a plugin that's
            #   already been loaded) will not be added
            pluginTaskHash              => {},
            # Registry hash of 'grid' windows added by the plugin. If the plugin is disabled, the
            #   windows are closed (and, for 'main' windows, all sessions in the 'main' windows are
            #   terminated). Hash in the form
            #   $pluginGridWinHash{package_name} = plugin_name
            pluginGridWinHash           => {},
            # Registry hash of 'free' windows added by the plugin (not including 'dialogue'
            #   windows). If the plugin is disabled, the windows are closed. Hash in the form
            #   $pluginFreeWinHash{package_name} = plugin_name
            pluginFreeWinHash           => {},
            # Registry hash of strip objects added by the plugin. Strip objects are always
            #   available, even if their parent plugin is disabled. Hash in the form
            #   $pluginStripObjHash{package_name} = plugin_name
            pluginStripObjHash          => {},
            # Registry hash of table objects added by the plugin. Table objects are always
            #   available, even if their parent plugin is disabled. Hash in the form
            #   $pluginTableObjHash{package_name} = plugin_name
            pluginTableObjHash          => {},
            # Registry hash of cages that are added when a plugin is loaded, in the form
            #   $pluginCageHash{cage_name} = plugin_name
            # ...where 'cage_name' matches the cage's name (an item in $self->cageTypeList) and
            #   'plugin_name' matches a key in $self->pluginHash
            pluginCageHash              => {},
            # For cages that have been added by a plugin, a registry hash of package names in the
            #   form
            #   $pluginCagePackageHash{cage_name} = cage_package
            # ...where 'cage_name' is an item in $self->cageTypeList, and 'cage_package' is the
            #   package name of the Perl object
            pluginCagePackageHash       => {},
            # For cages that have been added by a plugin, a registry hash of 'edit' windows added by
            #   the plugin (where available)
            # Hash in the form
            #   $pluginCageEditWinHash{cage_name} = config_window_package_name
            # NB If no 'edit' window exists for a particular cage, 'edit_window_package_name' will
            #   be 'undef'
            pluginCageEditWinHash       => {},
            # Registry hash of functions to call every time a menu strip object (GA::Strip::MenuBar)
            #   creates a menu in an 'internal' window, in order to add menu menu items for the
            #   plugin. Hash in the form
            #   $pluginMenuFuncHash{plugin_name} = func_ref
            #   ...where 'func_ref' is a reference to a function within a plugin that creates menu
            #   items, when passed an existing Gtk3::Menu widget
            pluginMenuFuncHash          => {},
            # For MXP file filters that must be passed to a plugin, a registry hash of the plugin
            #   functions to call when the filter is applied to a file. Hash in the form
            #   $pluginMxpFilterHash{package_name} = reference_to_function
            pluginMxpFilterHash         => {},

            # System loops
            # ------------

            # The client time (used by various parts of the code that need a time that stays
            #   consistent for some measured period, but which is updated frequently). Set by
            #   $self->spinClientLoop, whenever the client loop spins, to the same value stored as
            #   $self->clientLoopObj->spinTime
            # (See also the corresponding session IV, GA::Session->sessionTime)
            clientTime                  => 0,
            # Each session has a session loop, also called by a Glib timer. If a Perl error is
            #   generated, the code in axmud.pl this flag to TRUE, which suspends the client loop
            #   and
            #   all session loops until the user lifts the suspension with the ';restart' command
            suspendSessionLoopFlag      => FALSE,

            # Client loop
            # -----------

            # The GA::Obj::Loop which handles the client loop
            clientLoopObj               => undef,
            # Flag set to TRUE (by GA::Obj::Loop->spinLoop) when the client loop spins, set back to
            #   FALSE when the spin is complete. The TRUE setting prevents one client loop spin from
            #   taking place if another is still being processed
            clientLoopSpinFlag          => FALSE,
            # The client loop default delay, in seconds (never changes once set; absolute minimum
            #   value is 0.01)
            clientLoopDelay             => 0.1,

            # File objects
            # When there are no file objects in GA::Client->fileObjHash whose ->modifyFlag is set to
            #   TRUE (meaning that none of them need to be saved), this flag is set to FALSE
            # When the first file object has its ->modifyFlag set to TRUE, this flag is set to TRUE
            # When the flag changes, $self->checkMainWinTitles changes the title of all 'main'
            #   windows together, with an asterisk if the flag is TRUE, and no asterisk if the flag
            #   is FALSE
            showModFlag                 => FALSE,

            # 'internal' window blinkers (not to be confused with blinking text in textviews)
            # Blinkers in GA::Strip::ConnectInfo objects (in 'internal' windows) are handled by the
            #   client loop. Each session has its own ->blinkerStateHash, which specifies the
            #   current state of each blinker when that session is the window's visible session
            #   ('off' or 'on' for some specified time)
            # This IV specifies the blinker delay - how many seconds until the blinker, having been
            #   turned on, should be turned off
            blinkerDelay                => 0.25,

            # Blinking text in textviews (not to be confused with 'internal' window blinkers)
            # The time per blink for 'blink_slow' text, in seconds
            blinkSlowTime               => 1,       # 60 blinks per minute
            # The time (matches $self->clientTime) at which the 'blink_slow' text should next appear
            #   or disappear (one blink = one appearance and disappearance)
            blinkSlowCheckTime          => undef,
            # Flag set to TRUE when 'blink_slow' text is visible, FALSE when 'blink_slow' text is
            #   invisible
            blinkSlowFlag               => undef,

lib/Games/Axmud/Client.pm  view on Meta::CPAN

            #   of new sessions
            constSessionMax             => 1024,
            # The current number of sessions allowed (ignored when $axmud::BLIND_MODE_FLAG is TRUE,
            #   when only one session is allowed)
            sessionMax                  => 16,          # [config]
            # The current session is set whenever a session's default tab becomes the visible tab in
            #   a 'main' window, and is set back to 'undef' when there are no sessions running
            # Set/reset by $self->setCurrentSession
            currentSession              => undef,
            # Flag set to TRUE when Axmud should be shut down. The END() function in axmud.pl checks
            #   this flag and, if it's still set to FALSE, calls GA::Client->stop() before
            #   terminating the script. If it's set to TRUE, GA::Client->stop() has already been
            #   called, and we don't need to call it again
            shutdownFlag                => FALSE,
            # Flag set to TRUE when $self->stop is first called, to prevent multiple concurrent
            #   calls to that function
            terminatingFlag             => FALSE,
            # Flag that determines how a session deals with a disconnection from a world (i.e. when
            #   its ->status is 'connected'). FALSE if it should switch to 'disconnected' mode, TRUE
            #   if it should switch to 'offline' mode (as if the user had clicked the 'Connect
            #   offline' button in the Connections window)
            offlineOnDisconnectFlag     => FALSE,       # [config]

            # The way in which text on each session's tab label (if it's visible) is displayed:
            #   'bracket'   - displayed as 'deathmud (Gandalf)'
            #   'hyphen'    - 'deathmud - Gandalf'
            #   'world'     - 'deathmud'
            #   'char'      - 'gandalf'
            # NB If $self->xTermTitleFlag is TRUE and an xterm title is received, that title is
            #   displayed instead
            # NB If $self->longTitleFlag is TRUE, the world's long name (rather than the world's
            #   profile name) is used
            sessionTabMode              => 'bracket',   # [config]
            # Flag set to TRUE if xterm titles (in the form ESC]0;stringBEL ) should be displayed
            #   in a 'main' window tab's title (if the tab is visible) when they are received from
            #   the world; set to FALSE if the normal text (specified by
            #   GA::Session->checkTabLabels) should be displayed there (if the tab is visible)
            # NB If set to TRUE, the normal text is displayed until the first xterm title is
            #   received
            xTermTitleFlag              => TRUE,        # [config]
            # Flag set to TRUE if the tab label (if it's visible) should use the world's long name,
            #   FALSE if the tab label should use the profile name
            longTabLabelFlag            => TRUE,        # [config]
            # Flag set to TRUE if a so-called 'simple tab' (a standalone Gtk3::TextView, rather than
            #   a tab in a Gtk3::Notebook) should be displayed when only a single session is open
            #   in a 'main' window (it's replaced with a Gtk3::Notebook when a second session is
            #   opened in the same 'main' window)
            # Flag set to FALSE if a Gtk3::Notebook should always be used
            # NB This IV only applies to pane objects used for sessions' default tabs
            simpleTabFlag               => FALSE,       # [config]
            # Flag set to TRUE if the user should be prompted for a confirmation if they try to
            #   close a 'main' window by clicking on its 'X' widget, and any of the sessions using
            #   the window are connected to a world
            confirmCloseMainWinFlag     => TRUE,        # [config]
            # Flag set to TRUE if the user should be prompted for a confirmation if they try to
            #   close a tab by clicking on its 'X' widget, and the session is connected to a world
            confirmCloseTabFlag         => TRUE,        # [config]
            # Equivalent flag set to TRUE if the user should be prompted for a confirmation if they
            #   try to stop the session by clicking the main window menu, and the session is
            #   connected to a world
            confirmCloseMenuFlag  => TRUE,              # [config]
            # Equivalent flag set to TRUE if the user should be prompted for a confirmation if they
            #   try to stop the session by clicking the main window toolbutton, and the session is
            #   connected to a world
            confirmCloseToolButtonFlag  => TRUE,        # [config]

            # The default character set to use. Must be one of the character sets available with the
            #   Perl Encode module
            constCharSet                => 'iso-8859-1',
            # The current character set. For each individual session, if the current world's
            #   ->worldCharSet IV is set, that character set is used instead
            charSet                     => undef,       # [config] Set below
            # Ordered list of available character sets (from the Perl 'encode' module)
            charSetList                 => [],          # Set below

            # Flag set to TRUE if details about every connection to a world should be stored in the
            #   world profile, FALSE if not
            connectHistoryFlag          => TRUE,        # [config]

            # Client commands
            # ---------------

            # All client command objects are stored in the following hash. Each command object
            #   inherits from GA::Generic::Cmd
            # (Actually, there are two types of client command: 'built-in' commands which exist in
            #   every copy of Axmud, and commands loaded from plugins which Axmud treats in almost
            #   exactly the same way. If plugin client commands have the same name as built-in
            #   client commands, then the built-in command is not available for as long as the
            #   plugin is enabled)
            #
            # Registry hash of client command objects, in the form
            #   $clientCmdHash{command_name} = blessed_reference_to_command_object
            #       e.g. $clientCmdHash{'about'} = blessed_reference_to_command_object
            clientCmdHash               => {},
            # When a plugin adds a command with same 'command_name' as an existing client
            #   command, the existing command is moved out of ->clientCmdHash and into this hash.
            #   Later, if the plugin is disabled, the original command is moved back into
            #   ->clientCmdHash, and the plugin command is moved into this hash - and so on,
            #   ad infinitum
            replaceClientCmdHash        => {},
            # A constant list of built-in client commands, grouped thematically and in a pre-defined
            #   order. Elements beginning with the @ character are group headings; everything else
            #   is a built-in client command
            constClientCmdPrettyList    => [
                '@Debug commands',
                    'Test', 'HelpTest', 'DumpAscii', 'TestColour', 'TestXTerm', 'TestFile',
                        'TestModel', 'TestPattern',
                    'QuickInput',
                    'SimulateWorld', 'SimulatePrompt', 'SimulateCommand', 'SimulateHook',
                    'DebugToggle', 'DebugConnection', 'Restart', 'Peek', 'Poke', 'PeekHelp',
                '@Client commands',
                    'Help', 'Hint', 'QuickHelp', 'SearchHelp', 'Blind', 'ListReserved',
                    'About', 'OpenAboutWindow', 'CloseAboutWindow',
                    'EditQuick', 'EditClient', 'EditSession',
                    'SwitchSession', 'MaxSession', 'ListSession', 'SetSession',
                    'Connect', 'Reconnect', 'XConnect', 'Telnet', 'SSH', 'SSL',
                    'Login',
                    'Quit', 'Qquit', 'QuitAll', 'Exit', 'Xxit', 'ExitAll',
                        'AbortSelfDestruct', 'StopSession', 'StopClient', 'Panic',
                    'AwayFromKeys', 'SetReminder', 'SetCountdown', 'SetCountup',
                    'SetLookup', 'ResetLookup', 'ForceLookup', 'ListLookup',

lib/Games/Axmud/Client.pm  view on Meta::CPAN

            # A set of Gtk3::Gdk::Cursors, one for when the mouse is hovering over a normal part of
            #   a textview, and others when it is hovering over various kinds of clickable link
            constNormalCursor           => Gtk3::Gdk::Cursor->new('xterm'),
            constWWWCursor              => Gtk3::Gdk::Cursor->new('hand1'),
            constPromptCursor           => Gtk3::Gdk::Cursor->new('sb_down_arrow'),
            constPopupCursor            => Gtk3::Gdk::Cursor->new('target'),
            constCmdCursor              => Gtk3::Gdk::Cursor->new('mouse'),
            constMailCursor             => Gtk3::Gdk::Cursor->new('pencil'),
            constTelnetCursor           => Gtk3::Gdk::Cursor->new('trek'),
            # Another set of Gtk3::Gdk::Cursors for the automapper window's free click mode
            constMapCursor              => Gtk3::Gdk::Cursor->new('arrow'),
            constMapAddCursor           => Gtk3::Gdk::Cursor->new('plus'),
            constMapConnectCursor       => Gtk3::Gdk::Cursor->new('crosshair'),
            constMapMergeCursor         => Gtk3::Gdk::Cursor->new('target'),

            # Icon file paths (relative to the main directory) for the 'internal' window strip
            #   object, GA::Strip::SearchBox
            constUpIconPath             => '/icons/search/arrow_up.png',
            constDownIconPath           => '/icons/search/arrow_down.png',
            constResetIconPath          => '/icons/search/broom.png',
            constCaseIconPath           => '/icons/search/capitalization.png',
            constRegexIconPath          => '/icons/search/token_shortland_character.png',
            constDivideIconPath         => '/icons/search/application_tile_vertical.png',
            # Icon file paths (relative to the main directory) for the 'internal' window strip
            #   object, GA::Strip::Entry
            constWipeIconPath           => '/icons/button/broom.png',
            constAddIconPath            => '/icons/button/textfield_add.png',
            constEmptyIconPath          => '/icons/button/console.png',
            constSystemIconPath         => '/icons/button/console_system.png',
            constDebugIconPath          => '/icons/button/console_debug.png',
            constErrorIconPath          => '/icons/button/console_error.png',
            constMultiIconPath          => '/icons/button/toggle_expand.png',
            constSearchIconPath         => '/icons/button/search.png',
            constCancelIconPath         => '/icons/button/wall.png',
            constSwitchIconPath         => '/icons/button/switch_windows.png',
            constSplitIconPath          => '/icons/button/application_tile_vertical.png',
            constRestoreIconPath        => '/icons/button/application.png',
            constScrollIconPath         => '/icons/button/lock_open.png',
            constLockIconPath           => '/icons/button/lock.png',

            # The sizes of icon provided for Axmud (icon files are in /icons/win/
            # Constant list of icon sizes (these values never change; in pixels)
            constIconSizeList           => [16, 32, 48, 64, 128],

            # Standard shadow type for Gtk3::Frame and Gtk3::ScrolledWindows (possible values are
            #   'in', 'out', 'etched-in', 'etched-out' or 'none')
            constShadowType             => 'in',

            # 'Internal' windows
            # ------------------

            # Axmud keeps two lists of strip objects - one for Axmud's built-in strip objects, and
            #   another for all strip objects (built-in objects and custom objects added via a
            #   plugin, which should inherit from GA::Strip::Custom)
            #
            # The constant registry of strip objects (these values never change). A hash in the form
            #   $constStripHash{package_name} = pretty_name
            # NB Both 'package_name' and 'pretty_name' should be unique. To avoid problems, use the
            #   plugin name in 'pretty_name', e.g. 'Myplugin toolbar'
            constStripHash              => {
                'Games::Axmud::Strip::MenuBar'
                                        => $axmud::SCRIPT . ' menu bar',
                'Games::Axmud::Strip::Toolbar'
                                        => $axmud::SCRIPT . ' toolbar',
                'Games::Axmud::Strip::Table'
                                        => $axmud::SCRIPT . ' table',
                'Games::Axmud::Strip::GaugeBox'
                                        => $axmud::SCRIPT . ' gauge box',
                'Games::Axmud::Strip::SearchBox'
                                        => $axmud::SCRIPT . ' search box',
                'Games::Axmud::Strip::Entry'
                                        => $axmud::SCRIPT . ' command entry box',
                'Games::Axmud::Strip::ConnectInfo'
                                        => $axmud::SCRIPT . ' connection info box',
            },
            # The customisable registry hash of strip objects, in the form
            #   $customStripHash{package_name} = description
            customStripHash             => {},      # Set below

            # Likewise, Axmud keeps two lists of table objects - one for Axmud's built-in table
            #   objects, and another for all table objects (built-in objects and custom objects
            #   added via a plugin, which should inherit from GA::Table::Custom)
            #
            # The constant registry of table objects (these values never change). A hash in the form
            #   $constTableHash{package_name} = pretty-name
            # NB Both 'package_name' and 'pretty_name' should be unique. To avoid problems, use the
            #   plugin name in 'pretty_name', e.g. 'Myplugin button'
            constTableHash              => {
                'Games::Axmud::Table::Holder'
                                        => $axmud::SCRIPT . ' holder',
                'Games::Axmud::Table::Container'
                                        => $axmud::SCRIPT . ' generic container',
                'Games::Axmud::Table::MiniTable'
                                        => $axmud::SCRIPT . ' mini-table',
                'Games::Axmud::Table::Label'
                                        => $axmud::SCRIPT . ' label',
                'Games::Axmud::Table::Button'
                                        => $axmud::SCRIPT . ' button',
                'Games::Axmud::Table::CheckButton'
                                        => $axmud::SCRIPT . ' check button',
                'Games::Axmud::Table::RadioButton'
                                        => $axmud::SCRIPT . ' radio button',
                'Games::Axmud::Table::Entry'
                                        => $axmud::SCRIPT . ' entry box',
                'Games::Axmud::Table::ComboBox'
                                        => $axmud::SCRIPT . ' combobox',
                'Games::Axmud::Table::SimpleList'
                                        => $axmud::SCRIPT . ' simple list',
                'Games::Axmud::Table::TextView'
                                        => $axmud::SCRIPT . ' simple textview',
                'Games::Axmud::Table::Pane'
                                        => $axmud::SCRIPT . ' window pane',
                'Games::Axmud::Table::PseudoWin'
                                        => $axmud::SCRIPT . ' pseudo-window',
            },
            # The customisable registry hash of table objects, in the form
            #   $customTableHash{package_name} = description
            customTableHash             => {},      # Set below

            # Constant registry list used to initialise the default set of toolbar buttons used in
            #   'internal' windows (usually only 'main' windows), when required. List in groups of

lib/Games/Axmud/Client.pm  view on Meta::CPAN

                        foreach my $session ($self->ivValues('sessionHash')) {

                            if (
                                $session->initWorld eq $worldName
                                && $session->initChar
                                && $session->initChar eq $thisChar
                            ) {
                                next INNER;
                            }
                        }

                        # Get connection details for this world
                        ($host, $port, $char, $password, $account)
                            = $worldObj->getConnectDetails($thisChar);

                        # Connect with a character
                        if (
                            $self->startSession(
                                $worldName,
                                $host,
                                $port,
                                $char,
                                $password,
                                $account
                            )
                            && $axmud::BLIND_MODE_FLAG
                        ) {
                            # In blind mode, stop after the first successful connection
                            last OUTER;
                        }
                    }
                }
            }

            # During this process, if no connections were actually initialised, open the Connections
            #   window as normal (except in Axmud blind mode)
            if (! $self->sessionHash) {

                if ($axmud::BLIND_MODE_FLAG) {
                    $self->connectBlind();
                } else {
                    $self->mainWin->quickFreeWin('Games::Axmud::OtherWin::Connect');
                }
            }

        } else {

            # Open the Connections window. If the user wants to connect to a world, it calls
            #   GA::Client->startSession
            $self->mainWin->quickFreeWin('Games::Axmud::OtherWin::Connect');
        }

        return 1;
    }

    sub stop {

        # Called by axmud.pl on shutdown
        # Also called by $self->stopSession, GA::Cmd::StopClient->do, GA::Cmd::Panic->do,
        #   GA::Cmd::RestoreWorld->do, GA::Win::Internal->setDeleteEvent and
        #   GA::Strip::MenuBar->drawWorldColumn
        # Stops the client
        #
        # Expected arguments
        #   (none besides $self)
        #
        # Return values
        #   'undef' on improper arguments
        #   1 otherwise

        my ($self, $check) = @_;

        # Local variables
        my $tempDir;

        # Check for improper arguments
        if (defined $check) {

             return $axmud::CLIENT->writeImproper($self->_objClass . '->stop', @_);
        }

        # The END() function will call this function again, before terminating the script, unless
        #   we set this flag
        # (The TRUE value also gives GA::Obj::WorkspaceGrid->stop to destroy a shared 'main'
        #   window, rather than just disengaging it)
        $self->ivPoke('shutdownFlag', TRUE);

        # This flag prevents multiple concurrent calls to this function if, for example, the user
        #   is repeatedly clicking the 'main' window's close button
        if ($self->terminatingFlag) {

            return undef;

        } else {

            $self->ivPoke('terminatingFlag', TRUE);
        }

        # If any text is being convertd to speech right now, interrupt it
        $self->ttsInterruptJob();

        # Perform an auto-backup of Axmud's data directory, if required
        if (
            $self->autoBackupMode eq 'all_stop'
            || (
                $self->autoBackupMode eq 'interval_stop' && $self->checkBackupInterval()
            )
        ) {
            $self->doAutoBackup();
        }

        # Fire any hooks in any session that are using the 'close_disconnect' hook event
        foreach my $sessionObj ($self->listSessions()) {

            $sessionObj->checkHooks('close_disconnect');
        }

        # Stop every current session
        if ($self->sessionHash && ! $self->stopAllSessions()) {

            return $self->writeError(

lib/Games/Axmud/Client.pm  view on Meta::CPAN

                $session->currentWorld->name eq $world
                && $session->currentChar && $session->currentChar->name eq $char
                && (
                    ! $ignoreFlag
                    || ($ignoreFlag && $session->status ne 'disconnected')
                )
            ) {
                $count++;
            }
        }

        return $count;
    }

    sub findSessions {

        # Called by GA::Session->setupProfiles
        # Compiles a list of sessions whose current world matches a specified world, and returns
        #   the list (in the order in which the sessions were created)
        #
        # Expected arguments
        #   $worldName      - The name of a world profile
        #
        # Optional arguments
        #   $ignoreSession  - If specified, ignore this session
        #
        # Return values
        #   An empty list on improper arguments or if no session is using $name as its current world
        #   Otherwise, returns the list of matching sessions

        my ($self, $worldName, $ignoreSession, $check) = @_;

        # Local variables
        my (@emptyList, @returnArray);

        # Check for improper arguments
        if (defined $check) {

            $axmud::CLIENT->writeImproper($self->_objClass . '->findSessions', @_);
            return @emptyList;
        }

        foreach my $session ($self->listSessions()) {

            if (
                (! $ignoreSession || $ignoreSession ne $session)
                && $session->currentWorld
                && $session->currentWorld->name eq $worldName
            ) {
                # This is a matching GA::Session
                push (@returnArray, $session);
            }
        }

        # Return the list of matching sessions (may be empty)
        return @returnArray;
    }

    sub checkSessions {

        # Called by GA::Strip::MenuBar->drawWorldColumn just before doing the ';stopsession' or
        #   ';stopclient' commands
        # Checks every session to see whether any of them are connected, and whether there are any
        #   unsaved files at all (if not, the 'main' window doesn't have to prompt the user for
        #   confirmation, before stopping the session/client).
        #
        # Expected arguments
        #   (none besides $self)
        #
        # Optional arguments
        #   $session    - If specified, ignore other GA::Session objects (but still check the
        #                   client's file objects)
        #
        # Return values
        #   'undef' on improper arguments or if there are any connected sessions or unsaved files
        #   1 if there are absolutely no connected sessions or unsaved files

        my ($self, $session, $check) = @_;

        # Check for improper arguments
        if (defined $check) {

            return $axmud::CLIENT->writeImproper($self->_objClass . '->checkSessions', @_);
        }

        # Check GA::Client file objects
        foreach my $fileObj ($self->ivValues('fileObjHash')) {

            if ($fileObj->modifyFlag) {

                return undef;
            }
        }

        # Check each session in turn
        foreach my $otherSession ($self->listSessions()) {

            if ($session && $session ne $otherSession) {

                # Ignore this session
                next OUTER;
            }

            # Check the session's connection status
            if ($otherSession->status ne 'disconnected' && $otherSession->status ne 'offline') {

                return undef;
            }

            # Check GA::Session file objects
            foreach my $fileObj ($otherSession->ivValues('sessionFileObjHash')) {

                if ($fileObj->modifyFlag) {

                    return undef;
                }
            }
        }

        # There are no connected sessions or unsaved files
        return 1;

lib/Games/Axmud/Client.pm  view on Meta::CPAN


                } elsif (! $cageType) {

                    return $self->writeError(
                        'Could not add cage (no cage type specified)',
                        $self->_objClass . '->addPluginCages',
                    );
                }

                # Check that $cageType is not too long
                if (length $cageType > 8) {

                    return $self->writeError(
                        'Cage type \'' . $cageType . '\' is too long (max 8 characters)',
                        $self->_objClass . '->addPluginCages',
                    );
                }

                # Check that the cage type doesn't already exist
                foreach my $item (@cageTypeList) {

                    if ($item eq $cageType) {

                        return $self->writeError(
                            'The cage type \'' . $cageType . '\' already exists',
                            $self->_objClass . '->addPluginCages',
                        );
                    }
                }

                # Add the cage
                $count++;
                push (@cageTypeList, $cageType);
                $pluginCageHash{$cageType} = $plugin;
                $pluginCagePackageHash{$cageType} = $packageName;
                $pluginCageEditWinHash{$cageType} = $editWinPackage;

            } until (! @list);
        }

        # No errors, so we can now update the GA::Client IVs (if any cages were actually added)
        if ($count) {

            $self->ivPoke('cageTypeList', @cageTypeList);
            $self->ivPoke('pluginCageHash', %pluginCageHash);
            $self->ivPoke('pluginCagePackageHash', %pluginCagePackageHash);
            $self->ivPoke('pluginCageEditWinHash', %pluginCageEditWinHash);

            # Update existing profiles
            foreach my $session ($self->listSessions()) {

                # The TRUE argument means 'don't display a message for each cage created/destroyed'
                $session->updateCages(TRUE);
            }
        }

        # Operation complete
        return $count;
    }

    sub addPluginMenus {

        # Called by any Axmud plugin
        # Adds menu items defined in the plugin to any menu strip object (GA::Strip::MenuBar)
        #   displayed in any 'internal' window while the client is running (and the plugin is
        #   enabled)
        #
        # Expected arguments
        #   $plugin     - The plugin's main package (declared in the file header)
        #
        # Optional arguments
        #   $funcRef    - Reference to a function which contain the code to add menu items to a
        #                   Gtk3::Menu widget, pre-existing or created by this function. The
        #                   referenced function must accept the strip object and Gtk3::Menu as
        #                   arguments, and return 'undef' on failure or 1 on success
        #
        # Return values
        #   'undef' on improper arguments or if the menu items can't be added
        #   1 otherwise

        my ($self, $plugin, $funcRef, $check) = @_;

        # Local variables
        my ($pluginObj, $subMenu);

        # Check for improper arguments
        if (! defined $plugin || ! defined $funcRef || defined $check) {

             return $axmud::CLIENT->writeImproper($self->_objClass . '->addPluginWidgets', @_);
        }

        # Find the plugin object
        $pluginObj = $self->ivShow('pluginHash', $plugin);
        if (! $pluginObj) {

            # Plugin not found - a very unlikely occurrence for this function, but it's worth
            #   checking anyway
            return undef;
        }

        # Each plugin can only call this function once
        if ($self->ivExists('pluginMenuFuncHash', $plugin)) {

            return undef;

        } else {

            $self->ivAdd('pluginMenuFuncHash', $plugin, $funcRef);
        }

        # Any 'internal' windows which already exist and which have a menu strip object should add a
        #   sub-menu for this plugin now; any new 'internal' windows created from now will
        #   automatically call the referenced function to add their own sub-menus
        foreach my $winObj ($self->desktopObj->ivValues('gridWinHash')) {

            my ($stripObj, $subMenu);

            if (
                $winObj->winType eq 'main'
                || $winObj->winType eq 'protocol'
                || $winObj->winType eq 'custom'
            ) {
                $stripObj = $winObj->ivShow('firstStripHash', 'Games::Axmud::Strip::MenuBar');
                if ($stripObj) {

                    $subMenu = $stripObj->addPluginWidgets($plugin);
                    if (! $subMenu) {

                        return undef;
                    }

                    # Call the referenced function to add menu items to this sub-menu
                    if (! &$funcRef($stripObj, $subMenu)) {

                        return undef;
                    }

                    # Update the window to show the new menu items
                    $winObj->winShowAll($self->_objClass . '->addPluginMenus');
                }
            }
        }

        return 1;
    }

    sub addPluginMxpFilters {

        # Called by any Axmud plugin
        # Adds the plugin function that's used to apply MXP file filters
        #
        # Expected arguments
        #   $plugin     - The plugin's main package (declared in the file header)
        #   $funcRef    - Reference to the function that does the conversion
        #
        # Return values
        #   'undef' on improper arguments
        #   1 otherwise

        my ($self, $plugin, $funcRef, $check) = @_;

        # Local variables
        my $pluginObj;

        # Check for improper arguments
        if (! defined $plugin || ! defined $funcRef || defined $check) {

             return $axmud::CLIENT->writeImproper($self->_objClass . '->addPluginMxpFilters', @_);
        }

        # Find the plugin object
        $pluginObj = $self->ivShow('pluginHash', $plugin);
        if (! $pluginObj) {

            # Plugin not found - a very unlikely occurrence for this function, but it's worth
            #   checking anyway
            return undef;
        }

        # Update IVs
        $self->ivAdd('pluginMxpFilterHash', $plugin, $funcRef);

        # Operation complete
        return 1;
    }

    sub addPluginMcpPackages {

        # Called by any Axmud plugin
        # Adds the MCP package object (inheriting from GA::Generic::Mcp) defined by the plugin
        #
        # Expected arguments
        #   $plugin         - The plugin's main package (declared in the file header)
        #   $name           - The name of the MCP package, e.g. 'mcp-negotiate-can'. Must conform to
        #                       MCP's package name rules (see the MCP spec for more information);
        #                       this function won't allow you to add 'official' MCP packages whose
        #                       name starts 'mcp-'
        #   $perlPackage    - The Perl package for the object, e.g. Games::Axmud::Mcp::MyPackage
        #   $minVersion     - The minimum package version supported (e.g. '1.0', '2.0' etc). Should

lib/Games/Axmud/Client.pm  view on Meta::CPAN

            return undef;

        } elsif (! $self->ttsFestivalSocket->print($cmd)) {

            # Socket has closed; go back to using the command line engine
            $self->ivPoke('ttsFestivalServerMode', 'cmd_line');
            $self->ivPoke('ttsFestivalConnectMode', 'cmd_line');
            $self->ivUndef('ttsFestivalSocket');

            return undef;

        } else {

            return 1;
        }
    }

    # External applications

    sub openFileInBrowser {

        # Called by GA::Cmd::Blind->do or any other function
        # Opens a file in an external web browser (if allowed)
        #
        # Expected arguments
        #   $path   - The file path to open
        #
        # Return values
        #   'undef' on improper arguments or if the path can't be opened
        #   1 otherwise

        my ($self, $path, $check) = @_;

        # Local variables
        my $cmd;

        # Check for improper arguments
        if (! defined $path || defined $check) {

            return $axmud::CLIENT->writeImproper($self->_objClass . '->openFileInBrowser', @_);
        }

        if (! $self->browserCmd || ! ($self->browserCmd =~ m/%s/)) {

            # No browser command set, or it doesn't contain a %s (which is substituted for the path)
            return undef;

        } else {

            $cmd = $self->browserCmd;
            $cmd =~ s/%s/$path/;

            system $cmd;

            return 1;
        }
    }

    sub openURL {

        # Called by GA::Strip::MenuBar->drawHelpColumn, GA::Obj::TextView->setButtonPressEvent,
        #   GA::OtherWin::Connect->createTableWidgets or any other function
        # Opens a URL link in an external web browser (if allowed)
        #
        # Expected arguments
        #   $link   - The URL to open
        #
        # Return values
        #   'undef' on improper arguments or if the link can't be opened
        #   1 otherwise

        my ($self, $link, $check) = @_;

        # Local variables
        my $cmd;

        # Check for improper arguments
        if (! defined $link || defined $check) {

            return $axmud::CLIENT->writeImproper($self->_objClass . '->openURL', @_);
        }

        if (! $self->browserCmd || ! ($self->browserCmd =~ m/%s/)) {

            # No browser command set, or it doesn't contain a %s (which is substituted for the link)
            return undef;

        } else {

            $cmd = $self->browserCmd;
            $cmd =~ s/%s/$link/;

            system $cmd;

            return 1;
        }
    }

    sub openEmail {

        # Called by GA::Obj::TextView->setButtonPressEvent or by any other function
        # Opens an email link in an external email application (if allowed)
        #
        # Expected arguments
        #   $link   - The email address to open
        #
        # Return values
        #   'undef' on improper arguments or if the link can't be opened
        #   1 otherwise

        my ($self, $link, $check) = @_;

        # Local variables
        my $cmd;

        # Check for improper arguments
        if (! defined $link || defined $check) {

            return $axmud::CLIENT->writeImproper($self->_objClass . '->openEmail', @_);
        }

lib/Games/Axmud/Client.pm  view on Meta::CPAN

        }

        return $self->ivIncrement('sessionCount');
    }

    sub set_sessionMax {

        my ($self, $num, $check) = @_;

        # Check for improper arguments
        if (
            ! defined $num
            || $num > $self->constSessionMax
            || defined $check
        ) {
            return $axmud::CLIENT->writeImproper($self->_objClass . '->set_sessionMax', @_);
        }

        $self->ivPoke('sessionMax', $num);

        # The data stored in this IV is saved in the 'config' file
        $self->setModifyFlag('config', TRUE, $self->_objClass . '->set_sessionMax');

        return 1;
    }

    sub toggle_sessionFlag {

        my ($self, $type, $check) = @_;

        # Local variables
        my $iv;

        # Check for improper arguments
        if (
            ! defined $type
            || (
                $type ne 'xterm' && $type ne 'long' && $type ne 'simple' && $type ne 'close_main'
                && $type ne 'close_tab' && $type ne 'close_menu' && $type ne 'close_toolbutton'
                && $type ne 'switch_offline'
            )
        ) {
            return $axmud::CLIENT->writeImproper($self->_objClass . '->toggle_sessionFlag', @_);
        }

        if ($type eq 'xterm') {
            $iv = 'xTermTitleFlag';
        } elsif ($type eq 'long') {
            $iv = 'longTabLabelFlag';
        } elsif ($type eq 'simple') {
            $iv = 'simpleTabFlag';
        } elsif ($type eq 'close_main') {
            $iv = 'confirmCloseMainWinFlag';
        } elsif ($type eq 'close_tab') {
            $iv = 'confirmCloseTabFlag';
        } elsif ($type eq 'switch_offline') {
            $iv = 'offlineOnDisconnectFlag';
        } elsif ($type eq 'close_menu') {
            $iv = 'confirmCloseToolButtonFlag';
        } elsif ($type eq 'close_toolbutton') {
            $iv = 'confirmCloseMenuFlag';
        }

        if ($self->$iv) {
            $self->ivPoke($iv, FALSE);
        } else {
            $self->ivPoke($iv, TRUE);
        }

        # Redraw the tab title in every session
        if ($type ne 'switch_offline') {

            foreach my $session ($self->listSessions()) {

                # The TRUE argument means 'definitely update'
                $session->checkTabLabels(TRUE);
            }
        }

        # The data stored in these IVs are saved in the 'config' file
        $self->setModifyFlag('config', TRUE, $self->_objClass . '->toggle_sessionFlag');

        return 1;
    }

    sub set_sessionTabMode {

        my ($self, $mode, $check) = @_;

        # Check for improper arguments
        if (
            defined $check
            || ($mode ne 'bracket' && $mode ne 'hyphen' && $mode ne 'world' && $mode ne 'char')
        ) {
            return $axmud::CLIENT->writeImproper($self->_objClass . '->set_sessionTabMode', @_);
        }

        # Update IVs
        $self->ivPoke('sessionTabMode', $mode);

        # Redraw the tab title in every session
        foreach my $session ($self->listSessions()) {

            # The TRUE argument means 'definitely update'
            $session->checkTabLabels(TRUE);
        }

        # The data stored in this IV is saved in the 'config' file
        $self->setModifyFlag('config', TRUE, $self->_objClass . '->set_sessionTabMode');

        return 1;
    }

    sub set_shareMainWinFlag {

        # Should only be called by GA::WizWin::Setup->saveChanges. Everything else should call
        #   $self->set_restartShareMainWinMode

        my ($self, $flag, $check) = @_;

        # Check for improper arguments

lib/Games/Axmud/Client.pm  view on Meta::CPAN


    sub autoSaveFlag
        { $_[0]->{autoSaveFlag} }
    sub autoSaveWaitTime
        { $_[0]->{autoSaveWaitTime} }
    sub autoRetainFileFlag
        { $_[0]->{autoRetainFileFlag} }

    sub autoBackupMode
        { $_[0]->{autoBackupMode} }
    sub autoBackupDir
        { $_[0]->{autoBackupDir} }
    sub autoBackupInterval
        { $_[0]->{autoBackupInterval} }
    sub autoBackupDate
        { $_[0]->{autoBackupDate} }
    sub autoBackupFileType
        { $_[0]->{autoBackupFileType} }
    sub autoBackupAppendFlag
        { $_[0]->{autoBackupAppendFlag} }

    sub fileObjHash
        { my $self = shift; return %{$self->{fileObjHash}}; }
    sub configFileObj
        { $_[0]->{configFileObj} }
    sub configWorldProfList
        { my $self = shift; return @{$self->{configWorldProfList}}; }

    sub constLargeFileSize
        { $_[0]->{constLargeFileSize} }

    sub allowModelSplitFlag
        { $_[0]->{allowModelSplitFlag} }
    sub constModelSplitSize
        { $_[0]->{constModelSplitSize} }
    sub modelSplitSize
        { $_[0]->{modelSplitSize} }

    sub initPluginList
        { my $self = shift; return @{$self->{initPluginList}}; }
    sub pluginHash
        { my $self = shift; return %{$self->{pluginHash}}; }
    sub pluginCmdHash
        { my $self = shift; return %{$self->{pluginCmdHash}}; }
    sub pluginTaskHash
        { my $self = shift; return %{$self->{pluginTaskHash}}; }
    sub pluginGridWinHash
        { my $self = shift; return %{$self->{pluginGridWinHash}}; }
    sub pluginFreeWinHash
        { my $self = shift; return %{$self->{pluginFreeWinHash}}; }
    sub pluginStripObjHash
        { my $self = shift; return %{$self->{pluginStripObjHash}}; }
    sub pluginTableObjHash
        { my $self = shift; return %{$self->{pluginTableObjHash}}; }
    sub pluginCageHash
        { my $self = shift; return %{$self->{pluginCageHash}}; }
    sub pluginCagePackageHash
        { my $self = shift; return %{$self->{pluginCagePackageHash}}; }
    sub pluginCageEditWinHash
        { my $self = shift; return %{$self->{pluginCageEditWinHash}}; }
    sub pluginMenuFuncHash
        { my $self = shift; return %{$self->{pluginMenuFuncHash}}; }
    sub pluginMxpFilterHash
        { my $self = shift; return %{$self->{pluginMxpFilterHash}}; }

    sub clientTime
        { $_[0]->{clientTime} }
    sub suspendSessionLoopFlag
        { $_[0]->{suspendSessionLoopFlag} }

    sub clientLoopObj
        { $_[0]->{clientLoopObj} }
    sub clientLoopSpinFlag
        { $_[0]->{clientLoopSpinFlag} }
    sub clientLoopDelay
        { $_[0]->{clientLoopDelay} }

    sub showModFlag
        { $_[0]->{showModFlag} }

    sub blinkerDelay
        { $_[0]->{blinkerDelay} }

    sub blinkSlowTime
        { $_[0]->{blinkSlowTime} }
    sub blinkSlowCheckTime
        { $_[0]->{blinkSlowCheckTime} }
    sub blinkSlowFlag
        { $_[0]->{blinkSlowFlag} }
    sub blinkFastTime
        { $_[0]->{blinkFastTime} }
    sub blinkFastCheckTime
        { $_[0]->{blinkFastCheckTime} }
    sub blinkFastFlag
        { $_[0]->{blinkFastFlag} }

    sub paneDelay
        { $_[0]->{paneDelay} }
    sub paneRestoreHash
        { my $self = shift; return %{$self->{paneRestoreHash}}; }

    sub systemMsgList
        { my $self = shift; return @{$self->{systemMsgList}}; }

    sub sessionHash
        { my $self = shift; return %{$self->{sessionHash}}; }
    sub sessionCount
        { $_[0]->{sessionCount} }
    sub constSessionMax
        { $_[0]->{constSessionMax} }
    sub sessionMax
        { $_[0]->{sessionMax} }
    sub currentSession
        { $_[0]->{currentSession} }
    sub shutdownFlag
        { $_[0]->{shutdownFlag} }
    sub terminatingFlag
        { $_[0]->{terminatingFlag} }
    sub offlineOnDisconnectFlag
        { $_[0]->{offlineOnDisconnectFlag} }

    sub sessionTabMode
        { $_[0]->{sessionTabMode} }
    sub xTermTitleFlag
        { $_[0]->{xTermTitleFlag} }
    sub longTabLabelFlag
        { $_[0]->{longTabLabelFlag} }
    sub simpleTabFlag
        { $_[0]->{simpleTabFlag} }
    sub confirmCloseMainWinFlag
        { $_[0]->{confirmCloseMainWinFlag} }
    sub confirmCloseTabFlag
        { $_[0]->{confirmCloseTabFlag} }
    sub confirmCloseMenuFlag
        { $_[0]->{confirmCloseMenuFlag} }
    sub confirmCloseToolButtonFlag
        { $_[0]->{confirmCloseToolButtonFlag} }

    sub constCharSet
        { $_[0]->{constCharSet} }
    sub charSet
        { $_[0]->{charSet} }
    sub charSetList
        { my $self = shift; return @{$self->{charSetList}}; }

    sub connectHistoryFlag
        { $_[0]->{connectHistoryFlag} }

    sub clientCmdHash
        { my $self = shift; return %{$self->{clientCmdHash}}; }
    sub replaceClientCmdHash
        { my $self = shift; return %{$self->{replaceClientCmdHash}}; }
    sub constClientCmdPrettyList
        { my $self = shift; return @{$self->{constClientCmdPrettyList}}; }
    sub clientCmdPrettyList
        { my $self = shift; return @{$self->{clientCmdPrettyList}}; }
    sub clientCmdList
        { my $self = shift; return @{$self->{clientCmdList}}; }
    sub clientCmdReplacePrettyHash
        { my $self = shift; return %{$self->{clientCmdReplacePrettyHash}}; }

    sub constUserCmdHash
        { my $self = shift; return %{$self->{constUserCmdHash}}; }
    sub userCmdHash
        { my $self = shift; return %{$self->{userCmdHash}}; }

    sub constClientSigil
        { $_[0]->{constClientSigil} }
    sub constForcedSigil
        { $_[0]->{constForcedSigil} }
    sub constEchoSigil
        { $_[0]->{constEchoSigil} }
    sub constPerlSigil
        { $_[0]->{constPerlSigil} }
    sub constScriptSigil
        { $_[0]->{constScriptSigil} }
    sub constMultiSigil
        { $_[0]->{constMultiSigil} }
    sub constSpeedSigil
        { $_[0]->{constSpeedSigil} }
    sub constBypassSigil
        { $_[0]->{constBypassSigil} }

    sub echoSigilFlag
        { $_[0]->{echoSigilFlag} }
    sub perlSigilFlag
        { $_[0]->{perlSigilFlag} }
    sub scriptSigilFlag
        { $_[0]->{scriptSigilFlag} }
    sub multiSigilFlag
        { $_[0]->{multiSigilFlag} }
    sub speedSigilFlag
        { $_[0]->{speedSigilFlag} }
    sub bypassSigilFlag
        { $_[0]->{bypassSigilFlag} }



( run in 2.831 seconds using v1.01-cache-2.11-cpan-140bd7fdf52 )