Games-Axmud

 view release on metacpan or  search on metacpan

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


                # Copy the contents of the other session's registries directly into this session

                # Copy data that has already been loaded from the 'otherprof' file
                $self->ivPoke('profPriorityList', $otherSession->profPriorityList);
                $self->ivPoke('templateHash', $otherSession->templateHash);
                $self->ivPoke('profHash', $otherSession->profHash);
                $self->ivPoke('cageHash', $otherSession->cageHash);
                # (Only one current profile so far - the world profile)
                $self->ivAdd('currentProfHash', $worldObj->category, $worldObj);
                $self->ivPoke('currentWorld', $worldObj);

                # Copy data that has already been loaded from the 'worldmodel' file
                $self->ivPoke('worldModelObj', $otherSession->worldModelObj);

                # Copy the other session's file object registry
                $self->ivPoke('sessionFileObjHash', $otherSession->sessionFileObjHash);

                # Copy the other session's current dictionary
                $self->ivPoke('currentDict', $otherSession->currentDict);

            # PART 6    - Load data for an existing world profile
            #
            # Mode 'start'/'set_exist':
            #   If the world profile corresponding to $worldName exists and has been a current
            #       profile before, it already has things like cages, a world model, and so on. Load
            #       these things into memory from the 'otherprof' and 'worldmodel' files
            } else {

                # Mark this world profile as the current one
                $self->ivAdd('profHash', $worldObj->name, $worldObj);
                $self->ivAdd('currentProfHash', $worldObj->category, $worldObj);
                $self->ivPoke('currentWorld', $worldObj);

                # Create two file objects for the two files objects associated with this profile,
                #   replacing the ones that we deleted earlier in this function
                $otherProfFileObj = Games::Axmud::Obj::File->new('otherprof', $worldName, $self);
                $worldModelFileObj = Games::Axmud::Obj::File->new('worldmodel', $worldName, $self);
                if (! $otherProfFileObj || ! $worldModelFileObj) {

                    # (Improper arguments error already displayed)
                    return $self->writeError(
                        'Could not set up current profiles - error creating file objects',
                        $self->_objClass . '->setupProfiles',
                    );

                } else {

                    # Add these file objects to the file object registries
                    $self->ivAdd('sessionFileObjHash', 'otherprof', $otherProfFileObj);
                    $self->ivAdd('sessionFileObjHash', 'worldmodel', $worldModelFileObj);
                    # The world profile's file object must appear in the GA::Client's registry and
                    #   the GA::Session's registry too
                    $self->ivAdd(
                        'sessionFileObjHash',
                        $worldName,
                        $axmud::CLIENT->ivShow('fileObjHash', $worldName),
                    );

                    # Load the 'otherprof' and 'worldmodel' data files (which sets IVs such as the
                    #   cage registries). If the files are big, show a 'loading...' popup
                    $otherProfPath = $axmud::DATA_DIR . $otherProfFileObj->standardPath;
                    if (
                        (-e $otherProfPath)
                        && (-s $otherProfPath) > $axmud::CLIENT->constLargeFileSize
                    ) {
                        $self->mainWin->showBusyWin();
                    }

                    if (! $otherProfFileObj->loadDataFile()) {

                        # Try loading the automatic backup, i.e. 'otherprof.axm.bu'
                        if (! $otherProfFileObj->loadDataFile(undef, undef, undef, TRUE)) {

                            # (Error not already displayed)
                            return $self->writeError(
                                'Could not set up current profiles - error loading the'
                                . ' \'otherprof\' file (file might be corrupt or missing)',
                                $self->_objClass . '->setupProfiles',
                            );

                        } else {

                            # The contents of the backup, now loaded into memory, must be saved at
                            #   some point
                            $otherProfFileObj->set_modifyFlag(TRUE);
                            # Don't overwrite the existing backup file with the faulty one
                            $otherProfFileObj->set_preserveBackupFlag(TRUE);
                        }
                    }

                    $worldModelPath = $axmud::DATA_DIR . $worldModelFileObj->standardPath;
                    if (
                        ! $axmud::CLIENT->busyWin
                        && (-e $worldModelPath)
                        && (-s $worldModelPath) > $axmud::CLIENT->constLargeFileSize
                    ) {
                        $self->mainWin->showBusyWin();
                    }

                    if (! $worldModelFileObj->loadDataFile()) {

                        # Try loading the automatic backup, i.e. 'worldmodel.axm.bu'
                        if (! $worldModelFileObj->loadDataFile(undef, undef, undef, TRUE)) {

                            # (Error not already displayed)
                            return $self->writeError(
                                'Could not set up current profiles - error loading the'
                                . ' \'worldmodel\' file (file might be corrupt or missing)',
                                $self->_objClass . '->setupProfiles',
                            );

                        } else {

                            # The contents of the backup, now loaded into memory, must be saved at
                            #   some point
                            $worldModelFileObj->set_modifyFlag(TRUE);
                            # Don't overwrite the existing backup file with the faulty one
                            $worldModelFileObj->set_preserveBackupFlag(TRUE);
                        }
                    }

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


                        $ivHash{$argName} = $argValue;
                    }

                } until (! @argList);
            }

            # We can't process the link until the closing </SEND> tag is found, so store arguments
            #   temporarily in a GA::Obj::Link object
            ($line, $offset) = $textViewObj->getInsertPosn();
            if (! defined $line) {

                $self->mxpDebug($origToken, 'Internal error while processing send', 3012);

                return @emptyList;

            } else {

                # Take account of any lines removed from the textview's Gtk3::TextBuffer
                $line += $textViewObj->nextDeleteLine;
            }

            # The position of the link will be the textview's current insert position, plus the
            #   length of any already-processed text, that hasn't been displayed in the textview
            #   object yet, which has been stored for us in ->processStripLine
            # (The -1 argument means this is an incomplete link object, not yet applied to the
            #   current textview and not yet stored in the textview object's registries)
            if ($self->processOrigLine ne '') {

                $offset += length($self->processStripLine);
            }

            $linkObj = Games::Axmud::Obj::Link->new(
                -1,
                $textViewObj,
                $line,
                $offset,
                'cmd',
            );

            if (! $linkObj) {

                $self->mxpDebug($origToken, 'Internal error while processing send', 3013);

                return @emptyList;
            }

            # Set the link object's IVs
            $linkObj->ivPoke('href', $ivHash{'href'});              # May be 'undef'
            $linkObj->ivPoke('hint', $ivHash{'hint'});              # May be 'undef'
            $linkObj->ivPoke('mxpPromptFlag', $ivHash{'prompt'});   # Never 'undef'
            $linkObj->ivPoke('expireName', $ivHash{'expire'});      # May be 'undef'
            $linkObj->ivPoke('mxpFlag', TRUE);

            $href = $linkObj->href;
            $hint = $linkObj->hint;
            if (
                $href
                && (! $hint || $href =~ m/.\|./ || $hint =~ m/.\|./)
            ) {
                # When the link is clicked, a popup menu should be displayed. Set IVs to prepare
                #   for that
                $linkObj->ivPoke('popupFlag', TRUE);

                @cmdList = split('\|', $href);
                if ($hint) {

                    @optionList = split('\|', $hint);

                    if (((scalar @cmdList) + 1) == (scalar @optionList)) {

                        # The first item in @optionList is the hint; the rest are menu items
                        $linkObj->ivPoke('hint', shift @optionList);

                    } elsif ((scalar @cmdList) > 1 && (scalar @optionList) == 1) {

                        # The only item in @optionList must be a hint, as there are more commands
                        #   than hints
                        $linkObj->ivPoke('hint', shift @optionList);

                    } elsif ((scalar @cmdList) != (scalar @optionList)) {

                        $self->mxpDebug($origToken, 'Invalid SEND menu option format', 3014);

                        return @emptyList;

                    } else {

                        $linkObj->ivPoke('hint', undef);
                    }

                } else {

                    $linkObj->ivPoke('hint', undef);
                }

                $linkObj->ivPoke('popupCmdList', @cmdList);
                $linkObj->ivPoke('popupItemList', @optionList);
            }

            # Store the current link object (the link isn't applied to the textview until the
            #   corresponding </SEND> tag is processed, although any text inside the
            #   <SEND>...</SEND> is displayed immediately, as normal)
            $self->ivPoke('mxpCurrentSend', $linkObj);

            # Also need to create a new MXP stack object and store it in the current textview
            #   object, updating the latter's IVs
            if (! $textViewObj->createMxpStackObj($self, 'SEND')) {

                $self->mxpDebug($origToken, 'Internal error while processing element', 3015);

                return @emptyList;

            } else {

                # Operation complete
                return @emptyList;
            }

        # Process the <\SEND> tag
        } else {

            # Watch out for a <SEND> ... </SEND> ... </SEND> construction
            if (! $self->mxpCurrentSend) {

                # This a second </SEND> tag after an earlier </SEND> tag
                $self->mxpDebug($origToken, '</SEND> tag does not match earlier <SEND> tag', 3021);

                return @emptyList;

            } else {

                $linkObj = $self->mxpCurrentSend;
                $self->ivUndef('mxpCurrentSend');
            }

            if (! $linkObj->text && $linkObj->type ne 'image') {

                # There were no valid text tokens (or clickable images) between the <SEND>...</SEND>
                #   tags
                $self->mxpDebug($origToken, 'Invalid <SEND>...</SEND> construction', 3022);

                return @emptyList;

            } else {

                # The incomplete link object is now complete, but we can't apply the link to the
                #   current textview yet, as there may be some text before the link which hasn't
                #   been displayed yet
                # Instead, store it temporarily in an IV, and let $self->processIncomingData call
                #   GA::Obj::TextView->add_incompleteLink as soon as it's ready
                $self->ivPush('mxpTempLinkList', $linkObj);

                # Process any entities. The MXP documentation documents the use of &text; but some
                #   MUDs might choose to use any entity in their <SEND>...</SEND> constructions
                # Don't process entities for clickable images
                $href = $linkObj->href;
                $text = $linkObj->text;
                if ($href && $text && $linkObj->type ne 'image') {

                    $href =~ s/\&text\;/$text/g;
                    $href = $self->replaceMxpEntities($href);

                    $linkObj->ivPoke('href', $href);
                }

                # Do the same, if a popup menu is to be created
                foreach my $item ($linkObj->popupCmdList) {

                    $item =~ s/\&text\;/$text/g;
                    $item = $self->replaceMxpEntities($item);

                    push (@cmdList, $item);
                }

                foreach my $item ($linkObj->popupItemList) {

                    $item =~ s/\&text\;/$text/g;
                    $item = $self->replaceMxpEntities($item);

                    push (@optionList, $item);
                }

                $linkObj->ivPoke('popupCmdList', @cmdList);
                $linkObj->ivPoke('popupItemList', @optionList);
            }

            # Close the <SEND>...</SEND> construction, if the calling function isn't doing that (the
            #   TRUE function means don't call this function back, as you normally would)
            if (! $noPopFlag) {

                return $self->popMxpStack($keyword, TRUE);

            } else {

                # Operation complete
                return @emptyList;
            }
        }
    }

    sub processMxpSoundElement {

        # Called by $self->processMxpElement
        #
        # Process an MXP sound element: <SOUND> or <MUSIC>
        #
        # Expected arguments
        #   $origToken  - The original token text, before anything was extracted
        #   $tagMode    - 'open' for <..> elements, 'close' for </..> elements, 'defn' for <!..>
        #                   elements
        #   $keyword    - The element keyword (already converted to upper case)
        #
        # Optional arguments
        #   @argList    - If the element has arguments, a list in the form
        #                    (arg_name, arg_value, arg_name, arg_value...)
        #                 ...where each 'arg_value' is 'undef' is the argument wasn't a name=value
        #                   construction
        #
        # Return values
        #   An empty list on improper arguments
        #   Otherwise returns an equivalent list of Axmud colour/style tags otherwise (may be an
        #       empty list)

        my ($self, $origToken, $tagMode, $keyword, @argList) = @_;

        # Local variables
        my (
            $token,
            @emptyList,
        );

        # Check for improper arguments
        if (! defined $origToken || ! defined $tagMode || ! defined $keyword) {

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

        # <SOUND FName V=volume L=repeats P=priority C=continue T=type U=url>
        # <MUSIC FName V=volume L=repeats P=priority C=continue T=type U=url>
        # <SOUND Off>
        # <SOUND Off U=default_url>
        # <MUSIC Off>
        # <MUSIC Off U=default_url>



( run in 1.185 second using v1.01-cache-2.11-cpan-364913b4093 )