Games-Axmud

 view release on metacpan or  search on metacpan

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

            #   ->tagHash{tag} = reference_to_list_of_offsets_where_tags_occur
            tagHash                     => {%$tagHashRef},
            # Hash of 'mxpm_mode' tags that appear anywhere on this line, in the form
            #   $mxpModeHash{mode} = undef
            # ...where 'mode' is a number in the range 10-12, 19, 20-99
            mxpModeHash                 => {},

            # List of Axmud colour/style tags that were applied to the first character of this line,
            #   when it was displayed in the 'main' window
            # e.g. if the previous line used a 'blue' tag, but no 'attribs_off' after it, and if
            #   this line has no tags at all at offset 0, then the 'blue' tag still applies, and it
            #   exists in this list
            # e.g. if this line has a 'red' tag at offset 0, then that tag exists in this list,
            #   rather than the 'blue' tag that applied at the end of the previous line
            initialTagList              => [@$initialListRef],
            # List of Axmud colour/style tags that applied at the end of this line (i.e. the tags
            #   that will apply to the beginning of the next line, BEFORE any of the next line's
            #   tags are processed)
            finalTagList                => [],                  # Set below
            # List of Axmud colour/style tags that applied at the end of the previous line (copied
            #   from the buffer object's ->finalTagList from the previous line)
            previousTagList             => [],                  # Set below

            # MXP custom elements can define tag properties, e.g. from the MXP spec,
            #   <RName>...</RName>
            # If a closing tag has been processed on this line, and if the element defines tag
            #   properties, the text between the matching tags is stored in this buffer object
            # (If the text between the two matching tags contained newline characters, they have
            #   been removed)
            # Hash in the form
            #   $mxpFlagHash{tag_property} = text
            mxpFlagTextHash             => {%$mxpFlagHashRef},
        };

        # Bless the object into existence
        bless $self, $class;

        # If we've got a complete line, we can set the final tag list (otherwise, we must wait until
        #   the call to $self->update)
        if ($newLineFlag) {

            $self->{finalTagList} = [$session->currentTabObj->textViewObj->listColourStyleTags()];
        }

        # If this isn't the first buffer line, we can also set the previous tag list
        $prevBufferObj = $session->ivShow('displayBufferHash', ($number - 1));
        if ($prevBufferObj) {

            $self->{previousTagList} = [$prevBufferObj->finalTagList];
        }

        # Set the contents of $self->mxpModeHash, using any 'mxpm_mode' tags found in ->offsetHash
        $self->updateModes();

        return $self;
    }

    ##################
    # Methods

    sub update {

        # Called by GA::Session->updateDisplayBuffer when this object stores the most
        #   recently-displayed line of text from the world, and that line hasn't yet been terminated
        #   with a newline character
        # Updates the stored IVs
        #
        # Expected arguments
        #   $line           - The original line of text received from the world
        #   $stripLine      - $line after being stripped of escape sequences
        #   $modLine        - $stripLine after being modified by any matching interfaces (identical
        #                       to $stripLine if none match)
        #   $newLineFlag    - Flag set to TRUE if the line ends with a newline character; FALSE if
        #                       not
        #   $offsetHashRef  - Hash of Axmud colour/style tags in the form
        #                       $offsetHash{$offset} = reference_to_list_of_Axmud_colour_style_tags
        #                   - Each offset represents the position of a character in $modLine,
        #                       immediately before which the equivalent  escape sequence was
        #                       received (see the comments in GA::Session->updateDisplayBuffer)
        #   $tagHashRef     - Hash of Axmud colour/style tags in the form
        #                       $tagHash{tag} = reference_to_list_of_offsets_where_tags_occur
        #   $mxpFlagHashRef - Hash of text appearing between matching custom elements which define
        #                       tag properties in the form
        #                       $mxpFlagHash{tag_property} = string
        #
        # Return values
        #   'undef' on improper arguments
        #   1 on success

        my (
            $self, $line, $stripLine, $modLine, $newLineFlag, $offsetHashRef, $tagHashRef,
            $mxpFlagHashRef,
            $check,
        ) = @_;

        # Local variables
        my (
            $size,
            %newTagHash, %newOffsetHash,
        );

        # Check for improper arguments
        if (
            ! defined $line || ! defined $stripLine || ! defined $modLine || ! defined $newLineFlag
            || ! defined $offsetHashRef || ! defined $tagHashRef || defined $check
        ) {
            return $axmud::CLIENT->writeImproper($self->_objClass . '->update', @_);
        }

        # The contents of $tagHashRef must be merged with the existing contents of $self->tagHash
        # At the same time, we must modify all the offsets in $tagHashRef; e.g. if the tag 'red'
        #   has the list of offsets [0, 4, 9], and if $self->modLine already contains 50
        #   characters, the offsets should be stored as [50, 54, 59]

        # Get the existing size of $self->modLine
        $size = length ($self->modLine);

        # Import the current tag hash for speed...
        %newTagHash = $self->tagHash;
        # ...and then update it with the new data
        foreach my $tag (keys %$tagHashRef) {

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

        }

        # MXP tag properties for custom elements are rarer, so we don't need to import anything for
        #   speed
        foreach my $key (keys %$mxpFlagHashRef) {

            my $value = $$mxpFlagHashRef{$key};

            # (Guard against possibly that two sets of tags, e.g. <RName>...</RName>, appear on the
            #   same line
            if (! $self->ivExists('mxpFlagTextHash', $key)) {

                $self->ivAdd('mxpFlagTextHash', $key, $value);

            } else {

                $self->ivAdd(
                    'mxpFlagTextHash',
                    $key,
                    $self->ivShow('mxpFlagTextHash', $key) . $value,
                );
            }
        }

        # Update IVs. If $line is an empty string, it's because a packet beginning with a newline
        #   character was processed (otherwise, $line is a string whose initial portion matches the
        #   contents of $self->line)
        if (length ($line) > length ($self->line)) {

            $self->ivPush('partList', substr($line, length($self->line)));
        }

        $self->ivPoke('line', $self->line . $line);
        $self->ivPoke('stripLine', $self->stripLine . $stripLine);
        $self->ivPoke('modLine', $self->modLine . $modLine);
        $self->ivPoke('newLineFlag', $newLineFlag);

        if ($self->modLine =~ m/^\s*[\n\r]*$/) {
            $self->ivPoke('emptyFlag', TRUE);
        } else {
            $self->ivPoke('emptyFlag', FALSE);
        }

        $self->ivPoke('offsetHash', %newOffsetHash);
        $self->ivPoke('tagHash', %newTagHash);

        if ($newLineFlag) {

            $self->ivPoke(
                'finalTagList',
                $self->session->currentTabObj->textViewObj->listColourStyleTags(),
            );
        }

        # Update the ->mxpModeHash IV
        $self->updateModes();

        return 1;
    }

    sub updateModes {

        # Called by $self->new and $self->update
        # $self->mxpModeHash stores all the MXP modes (but only those in the range 10-12, 19, 20-99)
        #   that apply to this line
        # Update the hash
        #
        # Expected arguments
        #   (none besides $self)
        #
        # Return values
        #   'undef' on improper arguments
        #   1 on success

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

        # Local variables
        my (%offsetHash, %modeHash);

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

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

        # Import IVs (for convenience)
        %offsetHash = $self->offsetHash;
        %modeHash = $self->mxpModeHash;

        foreach my $offset (keys %offsetHash) {

            my ($listRef, $mode);

            $listRef = $offsetHash{$offset};

            foreach my $tag (@$listRef) {

                if (substr($tag, 0, 5) eq 'mxpm_') {

                    $mode = substr($tag, 5);
                    $modeHash{$mode} = undef;
                }
            }
        }

        # Update the IV
        $self->ivPoke('mxpModeHash', %modeHash);

        return 1;
    }

    sub copyLine {

        # Can be called by anything (for example, called by the Channels task)
        # Copies the contents of the line stored in this object into another textview, preserving
        #   the colour and style of the original line
        # Normal links (e.g. a line containing 'http://mywebsite.com') are clickable, but MXP links
        #   and so on are not
        #
        # Expected arguments
        #   $textViewObj    - The textview object (GA::Obj::TextView) into which the line is copied



( run in 0.940 second using v1.01-cache-2.11-cpan-75ffa21a3d4 )