Working with the line

Posted by Tesagk on Mon 05 Sep 2016 07:50 PM — 43 posts, 136,334 views.

#0
I'm having trouble finding out if there is a global "line" variable in MUSHclient accessible by Lua. In pursuit of that, I have also tried to find a "lua alias" to allow me to run simple scripts from the command-line, but have been unable to locate that as well.

What I am trying to accomplish is to use a trigger to replace text in the line using the "Replace" function, that way I can gather information from the line to store into a variable, and then replace a portion of that line so that I can effectively gag it.

In specific concept, there are two scenarios I am trying to work with:

1) Capture nospoof data, save it, and then remove the nospoof from the line so that I see it as though I didn't have nospoof on at all.

2) To take a prompt from a MUD, parse what I gather into a table, and then replace it with a neater version of the prompt, or with nothing at all.
Australia Forum Administrator #1
Quote:

In pursuit of that, I have also tried to find a "lua alias" to allow me to run simple scripts from the command-line, but have been unable to locate that as well.


In Scripting configuration, put something in the "Script Prefix" box. I usually use "/", others use something like "\\\".

Then you can type in the command window:


/ print "hello"





Quote:

I'm having trouble finding out if there is a global "line" variable in MUSHclient accessible by Lua.


The current line in the output window? Not as such. See http://www.gammon.com.au/scripts/doc.php?function=GetLineInfo - you can get the most recent line easily enough.

Quote:

1) Capture nospoof data, save it, and then remove the nospoof from the line so that I see it as though I didn't have nospoof on at all.


What you usually do here is make a trigger to capture the line. Set the trigger to omit it from output. Then Note or ColourNote the line after making desired modifications.
Amended on Mon 05 Sep 2016 08:42 PM by Nick Gammon
#2
Nick Gammon said:

What you usually do here is make a trigger to capture the line. Set the trigger to omit it from output. Then Note or ColourNote the line after making desired modifications.


I was worried about this option because it would strip all of the ansi in the line, no? I'd prefer to preserve the line without cutting up too much.
#3
In attempting what was suggested, I discovered the following issues:

+ Using either Note() or print() had an output which, since it is from the client, as opposed to the MU*, that was highlighted in blue. Is there a function for displaying as if by the MU*?

+ Having difficulty parsing the nospoof stuff out of it, but this is mostly my own lack of expertise. I've been trying to use the capture information to remove content from the whole line string. I may need to simply use a different pattern altogether.
Australia Forum Administrator #4
See:

Template:faq=23
Please read the MUSHclient FAQ - point 23.


That doesn't directly answer you, but it is possible to keep the style runs (colours) from the input line. Trigger scripts have access to the table of style runs, and using code similar to that FAQ you can output them again. Of course, you need to make changes as required (the spoofing stuff) and it would be helpful if it doesn't cross a style run.

Here is one example from a recent post:

http://www.gammon.com.au/forum/?id=13417&reply=3#reply3
#5
Thanks. I will take a look at it and see what I can do.
#6

<triggers>
  <trigger
   group="global"
   keep_evaluating="y"
   match="(\[([\w'\-\s\d]+)\(#(\d+)\)(?:\{(\w+)\})?(?:&lt;\-\(#([\d-]+)\))?(?:,(\w+))?\]\s)"
   name="triNoSpoofCapture"
   omit_from_output="y"
   regexp="y"
   send_to="14"
   sequence="100"
  >
  <send>local noSpoof = "%1"
for k,v in ipairs(TriggerStyleRuns) do
  text = string.gsub(v.text, noSpoof, "")
  ColourTell(RGBColourToName(v.textcolour),RGBColourToName(v.backcolour),text)
end
Note(text)</send>
  </trigger>
</triggers>


So, in attempting to do what you suggested...

This:

[Barrabus(#9443){Shawn}<-(#10322)] As you enter, Barrabus lifts a hand in greeting. "Welcome t' th' Fighters Guild! If yer new here, I c'n answer some questions! (OOC: Information is available via '+fg/info'. '+fg/help' will give you help on commands that work on the Guild grounds).


turns into this:


[Barrabus(#9443){Shawn}<-(#10322)] Ayoenter, Barrabulifthand igreeting. "Welcome t' th' FighterGuild! If yenehere, I c'answesome questions! (OOC: Informatioiavailable vi'+fg/info'. '+fg/help' will give yohelp ocommandthat work othe Guild grounds).' will give yohelp ocommandthat work othe Guild grounds).


[EDIT] Fixed up square brackets.
Amended on Wed 07 Sep 2016 04:09 AM by Nick Gammon
Australia Forum Administrator #7
What is in the "noSpoof" variable?

Never mind, I spotted it.
Australia Forum Administrator #8
You had me going for a minute because "enabled" was not set to "y".

Testing it at Regular Expressions 101 I get:


Match information

1.	[0-35]	`[Barrabus(#9443){Shawn}<-(#10322)] `
2.	[1-9]	`Barrabus`
3.	[11-15]	`9443`
4.	[17-22]	`Shawn`
5.	[27-32]	`10322`


Now match 1 there (which you are using for noSpoof) is considered a (Lua) regular expression, so it looks like something that matches any of the things inside the square brackets, not the whole thing.

So, you need to fixup the %1 pattern first, using another string.gsub, like this:


<triggers>
  <trigger
   enabled="y"
   group="global"
   keep_evaluating="y"
   match="(\[([\w'\-\s\d]+)\(#(\d+)\)(?:\{(\w+)\})?(?:&lt;\-\(#([\d-]+)\))?(?:,(\w+))?\]\s)"
   name="triNoSpoofCapture"
   omit_from_output="y"
   regexp="y"
   send_to="14"
   sequence="100"
  >
  <send>

local noSpoof = string.gsub ("%1", "[%%^%%$%%(%%)%%%%%%.%%[%%]%%*%%+%%-%%?]", "%%%%%%1")

for k,v in ipairs(TriggerStyleRuns) do
  text = string.gsub(v.text, noSpoof, "")
  ColourTell(RGBColourToName(v.textcolour),RGBColourToName(v.backcolour),text)
end

Note("")  -- finish off line

</send>
  </trigger>
</triggers>



I had to double the % symbols because of the way they work inside triggers (sigh). If you used a script file instead you wouldn't need as many percents.

Basically the string.gsub finds the following things and puts a % in front of them:

Quote:

Magic characters

There are some "magic characters" (such as %) that have special meanings. These are:

^ $ ( ) % . [ ] * + - ?


A debugging print (since removed) shows the noSpoof variable is now:


%[Barrabus%(#9443%){Shawn}<%-%(#10322%)%] 


Now that correctly matches. My output from your test string was:


As you enter, Barrabus lifts a hand in greeting. "Welcome t' th' Fighters Guild! If yer new here, I c'n answer some questions!
(OOC: Information is available via '+fg/info'. '+fg/help' will give you help on commands that work on the Guild grounds).


(Added a newline to make the post look better).
Amended on Wed 07 Sep 2016 06:18 AM by Nick Gammon
Australia Forum Administrator #9
Note that this assumes that the nospoof stuff is all inside one style run.
#10
I do need to work with script files more, so, cutting down on the % escapes is definitely a motivator.

Sorry about the "not-enabled" bit. Because of how it was garbling things, I needed it off to read anything.

Thanks for the help!
Australia Forum Administrator #11
This is that line with the %s halved:


local noSpoof = string.gsub ("%1", "[%^%$%(%)%%%.%[%]%*%+%-%?]", "%%%1")


It is basically a "%" in front of each of the magic characters (including % itself which is why you see 3 in a row at one point). Then the replacement is another % (which has to be doubled) followed by %1 (which is the character it found).
Amended on Wed 07 Sep 2016 08:41 PM by Nick Gammon
#12
Quick follow-up question: How do I interact with triggers through a script file? Do I utilize callbacks? I would like to turn this into a script file so that I can get started on that process, as well as extending the script to its full purpose (gathering and sometimes displaying nospoof information).
Australia Forum Administrator #13
Don't "send to script" (send to world and leave the send box empty).

Put a function in your script file.

Put its name in the "Script" box.

The function looks like this:


function myTriggerHandler (name, line, wildcards, styles)

end -- function


In that function wildcards [1] will contain what %1 previously did.

"styles" will be a table of styles, like TriggerStyleRuns.

You don't need to double "%" symbols.
#14
When I put the function in the script box, do I pass the parameters? If so, how? Do I just pass them with the values in your example?


dslpnp.statusbar.promptHandler(name, line, wildcards, styles) ?


Or, do I do:

dslpnp.statusbar.promptHandler(trigger_label, ??, ??, TriggerRunStyles)
Australia Forum Administrator #15
You just put:


dslpnp.statusbar.promptHandler


Look at some of the examples. The client supplies the arguments automatically in the order I gave.

You are giving the name of the function to call. You aren't writing a line of code to call it.
#16
Nick Gammon said:

You just put:


dslpnp.statusbar.promptHandler


Look at some of the examples. The client supplies the arguments automatically in the order I gave.

You are giving the name of the function to call. You aren't writing a line of code to call it.


OK. That's what I figured.

Now, strangely, on the nospoof thing, this is what I made for my script file:


pnp.nospoof = dslpnp.nospoof or {}

function pnp.nospoof.gather(name, line, wildcards, styles)
    local noSpoof = string.gsub (wildcards[1], "[%^%$%(%)%%%.%[%]%*%+%-%?]", "%%%1")
    
    for k,v in ipairs(styles) do
        text = string.gsub(v.text, noSpoof, "")
        ColourTell(RGBColourToName(v.textcolour), RGBColourToName(v.backcolour), text)
    end 
    
    Note("")
end


I saved it in MUSHclient\Scripts\pnp_nospoof.lua

I set the trigger as follows:

Regex:

([([\w'\-\s\d]+)\(#(\d+)\)(?:\{(\w+)\})?(?:<\-\(#([\d-]+)\))?(?:,(\w+))?]\s)

* Still having some issues with this matching every single nospoof instance.

Enabled: Checked
Omit from output: Checked
Keep evaluating: Checked
Regular expression: Checked

Send to: World
Squence: 100
Label: triNoSpoofCapture
Script: pnp.nospoof.gather
Group: global

The error I get upon closing the trigger is:
Quote:

You have not specified a script file name:

The trigger (triNoSpoofCapture) subroutine named "pnp.nospoof.gather" could not be found.


The XML:

<triggers>
  <trigger
   enabled="y"
   group="global"
   keep_evaluating="y"
   match="([([\w'\-\s\d]+)\(#(\d+)\)(?:\{(\w+)\})?(?:&lt;\-\(#([\d-]+)\))?(?:,(\w+))?]\s)"
   name="triNoSpoofCapture"
   omit_from_output="y"
   regexp="y"
   script="pnp.nospoof.gather"
   sequence="100"
  >
  </trigger>
</triggers>
#17
Right now, I still haven't been able to figure out the error. I'd really like to begin working on more scripts for MUSHclient, but this is part of doing that.
Australia Forum Administrator #18
Quote:

The trigger (triNoSpoofCapture) subroutine named "pnp.nospoof.gather" could not be found.


Well, is it there or not? You should be able to prove that by typing at the command line (assuming you set "/" to be the scripting prefix):


/ print (type (pnp.nospoof.gather))


If you don't see "function" printed then something is wrong in the way you are setting up your script.
#19
So... funny story.

I didn't realize I had to "load" the script in. For some reason I assumed scripts in a certain folder would auto-load in. Whoops.

Worse, I assumed / was the default Lua. Nope, there isn't one. So, while I tried to troubleshoot using Lua from the command-line, it didn't work.

Now I know that I have to load scripts in (with all the options that go along with it.

Unfortunately, having some minor issues with my regex pattern not working 100%.

Thanks for the help!
Australia Forum Administrator #20
Quote:

Worse, I assumed / was the default Lua. Nope, there isn't one.


Yes, the command line is, by default, sent to the MUD. The scripting prefix changes that to send to the current script engine.
#21
In terms of matching the line and pulling things out of it in the MU* I am testing on, everything is almost perfect (Still working through issues on the prompt replacement for the MUD).

Back to the MU*, the following lines are still not being edited out by the gsub. However, since the ultimate goal is to be able to pull the nospoof apart for data, I really need to better understand the gsub so that I can grab information from it for the various nospoof patterns that I need to parse.

Quote:

[bbpocket(#21){Core}<-(#20)] (New BB message (4/46) posted to 'IC Requests' by Jessamyn: Looking for a knight)
[SGP - Main Globals(#6){Core}<-(#9256)] Ceel goes OOC.


One of the other things I've noticed is that all of the replaced lines are offset by a single character. Indent paragraphs isn't checked.

Trigger:

<triggers>
  <trigger
   custom_colour="2"
   enabled="y"
   group="Global"
   keep_evaluating="y"
   match="(\[([^\]]*)\])"
   name="triNoSpoofCapture"
   omit_from_output="y"
   regexp="y"
   script="pnp.nospoof.gather"
   sequence="100"
  >
  </trigger>
</triggers>


Script:

pnp = pnp or {}
pnp.nospoof = pnp.nospoof or {}

function pnp.nospoof.gather(name, line, wildcards, styles)
    --print(wildcards[1])
    local noSpoof = string.gsub(wildcards[1], "[%^%$%(%)%%%.%{%}%[%]%*%+%-%?]", "%%%1")
    noSpoof = string.gsub(noSpoof, "^%s", "")
    for k,v in ipairs(styles) do
        text = string.gsub(v.text, noSpoof, "")
        ColourTell(RGBColourToName(v.textcolour), RGBColourToName(v.backcolour), text)
    end 
    
    Note()
end


So my question is two-fold:

1) What's with the unnecessary indent?

2) Why aren't the quoted lines matching the gsub?
Amended on Wed 21 Sep 2016 02:21 AM by Nick Gammon
Australia Forum Administrator #22
Quote:

1) What's with the unnecessary indent?


The indent is because you don't get rid of the space after the spoof stuff. If you tprint the style runs you see this:


1:
  "textcolour"=8454143
  "backcolour"=0
  "length"=34
  "style"=0
  "text"="[Barrabus(#9443){Shawn}<-(#10322)]"
2:
  "textcolour"=12632256
  "backcolour"=0
  "length"=249
  "style"=0
  "text"=" As you enter, Barrabus lifts a hand in greeting. "Welcome t' th' Fighters Guild! If yer new here, I c'n answer some questions! (OOC: Information is available via '+fg/info'. '+fg/help' will give you help on commands that work on the Guild grounds)."


Notice the space at the start of style #2?

One approach would be to omit a leading space at the start of the second style, if you know it is style #2, like this:


    for k,v in ipairs(styles) do
        text = string.gsub(v.text, noSpoof, "")
        if k == 2 then
          text = string.gsub (text, "^ ", "")
        end -- leading space on first style run
        ColourTell(RGBColourToName(v.textcolour), RGBColourToName(v.backcolour), text)
    end 


If it isn't always style #2 you might have to have a flag which checks if you have output anything yet, and if not trim the first space, eg.


function pnp.nospoof.gather(name, line, wildcards, styles)
    --print(wildcards[1])
    local noSpoof = string.gsub(wildcards[1], "[%^%$%(%)%%%.%{%}%[%]%*%+%-%?]", "%%%1")
    noSpoof = string.gsub(noSpoof, "^%s", "")
    local outputted = false
    for k,v in ipairs(styles) do
        text = string.gsub(v.text, noSpoof, "")
        if not outputted then
          text = string.gsub (text, "^ ", "")
        end -- leading space on first output
        if #text > 0 then
          outputted = true
        end  -- if
        ColourTell(RGBColourToName(v.textcolour), RGBColourToName(v.backcolour), text)
    end 
    
    Note()
end
Amended on Wed 21 Sep 2016 02:33 AM by Nick Gammon
Australia Forum Administrator #23
Quote:

Back to the MU*, the following lines are still not being edited out by the gsub


What are you expecting to happen? When I tested it the spoof stuff was gone:


(New BB message (4/46) posted to 'IC Requests' by Jessamyn: Looking for a knight)
#24
Nick Gammon said:

Quote:

1) What's with the unnecessary indent?


The indent is because you don't get rid of the space after the spoof stuff. If you tprint the style runs you see this:


1:
  "textcolour"=8454143
  "backcolour"=0
  "length"=34
  "style"=0
  "text"="[Barrabus(#9443){Shawn}<-(#10322)]"
2:
  "textcolour"=12632256
  "backcolour"=0
  "length"=249
  "style"=0
  "text"=" As you enter, Barrabus lifts a hand in greeting. "Welcome t' th' Fighters Guild! If yer new here, I c'n answer some questions! (OOC: Information is available via '+fg/info'. '+fg/help' will give you help on commands that work on the Guild grounds)."


Notice the space at the start of style #2?


Yes. I should have realized that was what was happening, damn.

Also, I was trying several ways yesterday to print the styles table so I could get a better idea of what was going on. Tried searching the site for a "tables" display. Didn't find tprint, it feels so obvious in retrospect, to see if there was a t-something.

Nick Gammon said:

One approach would be to omit a leading space at the start of the second style, if you know it is style #2, like this:


    for k,v in ipairs(styles) do
        text = string.gsub(v.text, noSpoof, "")
        if k == 2 then
          text = string.gsub (text, "^ ", "")
        end -- leading space on first style run
        ColourTell(RGBColourToName(v.textcolour), RGBColourToName(v.backcolour), text)
    end 


If it isn't always style #2 you might have to have a flag which checks if you have output anything yet, and if not trim the first space, eg.


function pnp.nospoof.gather(name, line, wildcards, styles)
    --print(wildcards[1])
    local noSpoof = string.gsub(wildcards[1], "[%^%$%(%)%%%.%{%}%[%]%*%+%-%?]", "%%%1")
    noSpoof = string.gsub(noSpoof, "^%s", "")
    local outputted = false
    for k,v in ipairs(styles) do
        text = string.gsub(v.text, noSpoof, "")
        if not outputted then
          text = string.gsub (text, "^ ", "")
        end -- leading space on first output
        if #text > 0 then
          outputted = true
        end  -- if
        ColourTell(RGBColourToName(v.textcolour), RGBColourToName(v.backcolour), text)
    end 
    
    Note()
end



This code

    noSpoof = string.gsub(noSpoof, "^%s", "")


Was intended to get rid of the space. I assume it didn't work since the line was not yet split. Which simply indicates that I need to understand how style runs work better first.

Question...

If the first gsub isn't clearing out the nospoof stuff, what IS it doing?
Australia Forum Administrator #25
The noSpoof stuff didn't have a space in it (certainly not a leading space).

A style run is neither more nor less than a bunch of text, with associated colour information (plus underline etc.).

So something like:

Text: foo
Colour: red
Background: green
Bold: yes

And a line is simply one or more of those style runs.
#26
So, what exactly is the purpose of the first gsub then?
Australia Forum Administrator #27
In reply #8? That is to convert the noSpoof stuff so that it is a regular expression with all the "magic" characters escaped out.
#28
Nick Gammon said:

In reply #8? That is to convert the noSpoof stuff so that it is a regular expression with all the "magic" characters escaped out.


OK. Sorry for the "newbie" questions, but what's the point of turning it back into a regular expression?

Also,

[bbpocket(#21){Core}<-(#20)] (New BB message (4/46) posted to 'IC Requests' by Jessamyn: Looking for a knight)
[SGP - Main Globals(#6){Core}<-(#9256)] Ceel goes OOC.


For some reason, these don't end up matching. Not entirely certain why, as the new trigger pattern is quite open, and the gsub accounts for all of the special characters that might be found in the line.
Amended on Sat 24 Sep 2016 10:15 PM by Nick Gammon
Australia Forum Administrator #29
Quote:

what's the point of turning it back into a regular expression?


OK, take this spoof stuff you want to get rid of:


[bbpocket(#21){Core}<-(#20)] 


As it stands when used in string.gsub on its own, it is just a "set". That is, it matches a single character, where that character can be any one of:

  • b
  • b
  • p
  • o
  • c
  • k
  • e
  • t
  • (
  • #
  • 2
  • 1
  • )
  • {
  • C
  • o
  • r
  • e
  • }
  • < to (
  • #
  • 2
  • 0
  • )


That's how sets work. It just looks for any one of the thing in the square brackets.

Now obviously we don't want that, so we have to "escape" out things like square brackets so they don't have their special meaning. That's what the first string.gsub does.
Australia Forum Administrator #30
Quote:

For some reason, these don't end up matching.


It matched when I tested it. Maybe another trigger matched it first. Turn on Trace under the Game menu to find out what is happening.
#31
Quote:

[bbpocket(#21){Core}<-(#20)] (New BB message (3/49) posted to 'OOC Discussion' by Trino Valve: RE: The Map...)
TRACE: Matched trigger triNoSpoofCapture
TRACE: Executing trigger script "pnp.nospoof.gather"
[bbpocket(#21){Core}<-(#20)] (New BB message (3/49) posted to 'OOC Discussion' by Trino Valve: RE: The Map...)


Upon a second look, I do believe that < isn't in the gsub, but I also don't believe it's a special character. So, I admit to being a little flummoxed. The trigger clearly sees it, but then doesn't remove it in the script.


pnp = pnp or {}
pnp.nospoof = pnp.nospoof or {}

function pnp.nospoof.gather(name, line, wildcards, styles)
    --print(wildcards[1])
    local noSpoof = string.gsub(wildcards[1], "[%^%$%(%)%%%.%{%}%[%]%*%+%-%?]", "%%%1")
    local outputted = false
    for k,v in ipairs(styles) do
        text = string.gsub(v.text, noSpoof, "")
        if not outputted then
          text = string.gsub (text, "^ ", "")
        end -- leading space on first output
        if #text > 0 then
          outputted = true
        end  -- if
        ColourTell(RGBColourToName(v.textcolour), RGBColourToName(v.backcolour), text)
    end 
    
    Note()
end


As a secondary issue. I keep having to uncheck "omit from output" because the omission seems to east the redisplayed lines as well as the original.
Amended on Mon 26 Sep 2016 07:27 PM by Tesagk
Australia Forum Administrator #32
Template:version
Please help us by advising the version of MUSHclient you are using. Use the Help menu -> About MUSHclient.
#33
Nick Gammon said:

(version)


5.02
#34
Quote:

Testrin Sidle has arrived.
TRACE: Matched trigger triNoSpoofCapture
TRACE: Executing trigger script "pnp.nospoof.gather"
[SGP - Main Globals(#6){Core}<-(#30827)] GAME> Testrin Sidle goes IC.
@emit %[SGP - Main Globals(#6){Core}<-(#30827)%] GAME> Mathesan Madaur goes IC.
TRACE: Matched trigger triNoSpoofCapture
TRACE: Executing trigger script "pnp.nospoof.gather"
GAME> Mathesan Madaur goes IC.


Now this is particularly strange. When I try replicating the output from the game that doesn't match, IN THE GAME, it is parsed out just fine.

I'm completely lost.
Australia Forum Administrator #35
Quote:

When I try replicating the output from the game that doesn't match, IN THE GAME, it is parsed out just fine.


I don't understand what you are saying here. What does "parsed out just fine" mean? I'm not clear what is and isn't working and under what circumstances.
#36
Nick Gammon said:

Quote:

When I try replicating the output from the game that doesn't match, IN THE GAME, it is parsed out just fine.


I don't understand what you are saying here. What does "parsed out just fine" mean? I'm not clear what is and isn't working and under what circumstances.


It's all in the quote.

Using @emit, I can simulate output from the game (since @emit doesn't show nospoof data for my character's stuff).

In every instance of it not capturing (shared in previous posts, usually around lines containing "{Core}<-"), it captures just fine if the same line comes from the MU* through my own character's @emit. It redisplays the line, stripping out the "nospoof" data.
#37

pnp = pnp or {}
pnp.nospoof = pnp.nospoof or {}

function pnp.nospoof.gather(name, line, wildcards, styles)
    --print(wildcards[1])
    local noSpoof = string.gsub(wildcards[1], "[%^%<%$%(%)%%%.%{%}%[%]%*%+%-%?]", "%%%1")
    local outputted = false
    for k,v in ipairs(styles) do
        text = string.gsub(v.text, noSpoof, "")
        if not outputted then
          text = string.gsub (text, "^ ", "")
        end -- leading space on first output
        if #text > 0 then
          outputted = true
        end  -- if
        ColourTell(RGBColourToName(v.textcolour), RGBColourToName(v.backcolour), text)
    end 
    
    Note()
end


One thing I've noted, upon review, is that the lines that aren't parsing the nospoof stuff out still have the timestamp indicator that ColourTell() is sending them. Which means it's something in the code that's failing.

I noticed that text is not a variable passed through the function and it's not declared in the function. Is it a global?

Quote:

pnp.nospoof.gather>
pnp.nospoof.gather> Mathesan Madaur has joined this channel.
Mathesan Madaur has joined this channel.
Channel Roleplay added with alias rp.
pnp.nospoof.gather>[SGP - Main Globals(#6){
[SGP - Main Globals(#6){pnp.nospoof.gather>Core
Corepnp.nospoof.gather>}<-(#21501)]
}<-(#21501)]pnp.nospoof.gather> <OOC> Trino Valve says, "So... I dunno."
<OOC> Trino Valve says, "So... I dunno."


Here you see some of the output I get when I add

print("pnp.nospoof.gather>"..text)


immediately after

text = string.gsub(v.text, noSpoof, "")
Amended on Mon 26 Sep 2016 07:26 PM by Tesagk
Australia Forum Administrator #38
Can you post a "packet debug" of the line in question? It might be that it has embedded colour codes and spans two styles.
#39
Nick Gammon said:

Can you post a "packet debug" of the line in question? It might be that it has embedded colour codes and spans two styles.


Is that an extra trace feature?

[EDIT]

Incoming packet: 61 (79 bytes) at Monday, September 26, 2016, 6:35:00 PM

[SGP - Main Glob   5b 53 47 50 20 2d 20 4d 61 69 6e 20 47 6c 6f 62
als(#6){.[1mCore   61 6c 73 28 23 36 29 7b 1b 5b 31 6d 43 6f 72 65
.[0m}<-(#21501)]   1b 5b 30 6d 7d 3c 2d 28 23 32 31 35 30 31 29 5d
 GAME> Trino Va   20 47 41 4d 45 3e 20 47 72 65 6e 69 6e 20 53 74
lve goes OOC...    72 69 6b 20 67 6f 65 73 20 4f 4f 43 2e 0d 0a

Incoming packet: 62 (2 bytes) at Monday, September 26, 2016, 6:35:09 PM

ÿñ                 ff f1

Incoming packet: 63 (78 bytes) at Monday, September 26, 2016, 6:35:10 PM

[SGP - Main Glob   5b 53 47 50 20 2d 20 4d 61 69 6e 20 47 6c 6f 62
als(#6){.[1mCore   61 6c 73 28 23 36 29 7b 1b 5b 31 6d 43 6f 72 65
.[0m}<-(#21501)]   1b 5b 30 6d 7d 3c 2d 28 23 32 31 35 30 31 29 5d
 GAME> Trino Va   20 47 41 4d 45 3e 20 47 72 65 6e 69 6e 20 53 74
lve goes IC...     72 69 6b 20 67 6f 65 73 20 49 43 2e 0d 0a

Incoming packet: 64 (2 bytes) at Monday, September 26, 2016, 6:36:09 PM

ÿñ                 ff f1

Incoming packet: 65 (2 bytes) at Monday, September 26, 2016, 6:37:09 PM

ÿñ                 ff f1
Amended on Mon 26 Sep 2016 09:39 PM by Tesagk
Australia Forum Administrator #40
Quote:

Is that an extra trace feature?


It shows exactly what has arrived from the MUD. I can convert that back into a test packet which can be used with Ctrl+Shift+F12, such as:


[SGP - Main Globals(#6){\1b[1mCore\1b[0m}<-(#21501)]rik goes OOC.\0d\0a\ff\f1[SGP - Main Globals(#6){\1b[1mCore\1b[0m}<-(#21501)]rik goes IC.\0d\0a\ff\f1\ff\f1


Now, analyzing that with "tprint (styles)" we see that indeed there are multiple style runs, thus the string.gsub doesn't match:


[SGP - Main Globals(#6){Core}<-(#21501)]
1:
  "textcolour"=8454143
  "backcolour"=0
  "length"=24
  "style"=0
  "text"="[SGP - Main Globals(#6){"
2:
  "textcolour"=8454143
  "backcolour"=0
  "length"=4
  "style"=0
  "text"="Core"
3:
  "textcolour"=8454143
  "backcolour"=0
  "length"=12
  "style"=0
  "text"="}<-(#21501)]"
4:
  "textcolour"=12632256
  "backcolour"=0
  "length"=12
  "style"=0
  "text"="rik goes IC."


Funnily enough, the styles are the same, which is odd. There must be some bug in the client where it doesn't merge the styles. As a work-around you can merge them in the script before testing for spoofing:


pnp = pnp or {}
pnp.nospoof = pnp.nospoof or {}

function pnp.nospoof.gather(name, line, wildcards, styles)
    local noSpoof = string.gsub(wildcards[1], "[%^%<%$%(%)%%%.%{%}%[%]%*%+%-%?]", "%%%1")
    local outputted = false
    
    -- merge identical styles
    local i = 1
    while i < #styles do
      local s1 = styles [i]
      local s2 = styles [i + 1]
      if s1.textcolour == s2.textcolour and
         s1.backcolour == s2.backcolour and
         s1.style      == s2.style then
         -- merge this style with the next one
         s1.text = s1.text .. s2.text
         table.remove (styles, i + 1)
      else
        i = i + 1
      end -- if
    end -- while each style
        
    for k,v in ipairs(styles) do
        text = string.gsub(v.text, noSpoof, "")
        if not outputted then
          text = string.gsub (text, "^ ", "")
        end -- leading space on first output
        if #text > 0 then
          outputted = true
        end  -- if
        ColourTell(RGBColourToName(v.textcolour), RGBColourToName(v.backcolour), text)
    end 
    
    Note()
end


That seems to give good results.
Amended on Tue 27 Sep 2016 02:50 AM by Nick Gammon
#41
Seems to be working. Thank you. I'll let you know if there are any additional problems.
Australia Forum Administrator #42
For future reference, I find this plugin useful:

http://www.gammon.com.au/forum/?id=9609

That lets me take a packet debug (such as the ones you supplied) and turn them back into something I can test what you are receiving. It includes the ANSI codes, newlines, MXP stuff and so on.

In your case you can test a trigger quickly without having to log onto the MUD and reproduce a certain message that might be time-consuming to obtain.

The converted text is just pasted into a "debug world output" window (Shift+Ctrl+F12).