With the new functionality of OnPluginPacketReceived it is now possible to "fool" MUSHclient into thinking prompt lines have a newline after them, even if they don't.
This can be useful for situations where you want a trigger to match a prompt line the moment it arrives, which it won't normally because trigger matching happens when a newline is received.
The way it is done is this:
The plugin below receives all incoming text from the MUD.
It batches the packets into lines, as sometimes lines are split over packets
All of the lines, except the last one, are just reassembled into normal lines with a newline between them.
The final line (one with no newline after it), is tested against a regular expression which should be set up to match your prompt.
The very first character is the "Escape" character (hex 1B) which is used in this case to reset colours to the default. (ESC[0m). Since we are expecting that we build it into the regular expression.
Note that in the regular expression we have to use two backslashes, as the first is used by Lua to indicate that the second is a "literal" backslash. This gets passed to the regular expression engine as \x1B to indicate the "escape" character.
If the regular expression matches, then the final (partial) line is also returned to MUSHclient (with a newline after it) thus effectively adding the newline to the prompt line.
The lines (saved into table t) are concatenated back into a single string with a newline between each table entry, and returned as the function result.
To use this, just copy below the line, and paste into a text window (notepad window). Change the regular expression (line 3) to match your prompt line, save as Add_Newline_To_Prompt.xml and then install it as a plugin.
All being well, your prompt lines should now automatically end with a newline, and thus match triggers immediately.
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE muclient[
<!ENTITY prompt_regexp "^\\x1B\\[0m<.+hp .+m .+mv .+xp> $" >
]>
<!-- MuClient version 3.59 -->
<!-- Plugin "Add_Newline_To_Prompt" generated by Plugin Wizard -->
<muclient>
<plugin
name="Add_Newline_To_Prompt"
author="Nick Gammon"
id="8316c19c35a9ebdb46055874"
language="Lua"
purpose="Adds a newline to prompt lines"
date_written="2004-12-13 12:08:00"
requires="3.59"
version="1.0"
>
<description trim="y">
Detects prompt lines without a newline, and if found, adds one.
Change ENTITY line on 3rd line of plugin to be a regular expression
that matches your prompt.
</description>
</plugin>
<!-- Script -->
<script>
re = rex.new ("&prompt_regexp;")
<![CDATA[
partial = "" -- partial line from last time through
function OnPluginPacketReceived (s)
-- add packet to what we already have (excluding carriage-returns)
partial = partial .. string.gsub (s, "\r", "")
t = {} -- table of lines to be returned
-- iterate over each line
partial = string.gsub (partial, "(.-)\n",
function (line)
table.insert (t, line)
return "" -- added for MUSHclient 3.80+
end)
-- look for prompt
if (re:match (partial)) then
table.insert (t, partial)
partial = ""
end -- if found prompt
if table.getn (t) > 0 then
table.insert (t, "") -- to get final linefeed
end -- if
-- return table of lines, concatenated with newlines between each one
return table.concat (t, "\n")
end -- function OnPluginPacketReceived
]]>
</script>
</muclient>
[EDIT] Amended on 22 October 2006 to make a change so that this plugins works with MUSHclient 3.80 onwards. The amended line is in bold (return "") and the surrounding lines have been reformatted a bit. See this forum post for a discussion:
Below is a simpler approach. The first one presented above, which breaks the packet into lines, is probably overkill for this application, although it is useful to illustrate how you would do that.
That version could be extended to omit certain lines, since it already processes each line individually.
The one below simply tests each packet against a regular expression, like:
(blah blah)<prompt line>
This uses a multi-line regular expression (hence the (?m) at the start) and if it find a prompt at the very end, adds a newline to it.
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE muclient[
<!ENTITY prompt_regexp "(?m)^.*<.+hp .+m .+mv .+xp> \\z" >
]>
<!-- MuClient version 3.59 -->
<!-- Plugin "Add_Newline_To_Prompt_2" generated by Plugin Wizard -->
<muclient>
<plugin
name="Add_Newline_To_Prompt_2"
author="Nick Gammon"
id="a14e9768c3ad5ce50d202ee0"
language="Lua"
purpose="Adds a newline to prompt lines"
date_written="2004-12-13 14:27"
requires="3.59"
version="1.0"
>
<description trim="y">
Detects prompt lines without a newline, and if found, adds one.
Change ENTITY line on 3rd line of plugin to be a regular expression
that matches your prompt.
</description>
</plugin>
<!-- Script -->
<script>
re = rex.new ("&prompt_regexp;")
<![CDATA[
function OnPluginPacketReceived (s)
if (re:match (s)) then
return s .. "\n"
else
return s
end -- if
end -- function OnPluginPacketReceived
]]>
</script>
</muclient>
Hmmm, how can I use that in Achaea? I have a trigger firing great and the regexp looks like
^(\d+)h, (\d+)m (?:\d+[we] |)(?:\d+[we] |)(\D{0,7})\-
If I try to use that in the plugin nothing happens. Mush keeps waiting for an Enter/newLine before he continues. I have no idea what I am doing wrong. Can i use the regular trigger in the GUI and use the Plugin too, or do they interfere in a way?
Oh, and it works great on a USB-stick, including scite-editor...so the same thing at work and on the linux-box at home.
You need to escape your backslashes (\\) in the entity.
And yes, you do use normal triggers.
The trigger in the plugin only tells MC what to add a newline after. So make sure it is your full prompt.
You then use your normal triggers to actually do stuff with that prompt.
Flannel is right. The backslashes in the regular expression are swallowed up by the Lua interpreter, so you need to double them when putting them into the plugin.
eg. In Lua (and Jscript) if you write this:
a = "\n"
It puts a newline into a. If you want to put in the backslash literally (which you do for a regular expression) you need to put another backslash, eg.
*scratch*, really trying hard, but it simply doesnt sip the vials when nothing else happens. I made the regexp more simple....from perl...
qr/(\d+)h,.+m\s(\d+)m(.+)-/o
I made in simple LUA-plugin (because I dont need the values):
<!ENTITY prompt_regexp ".+h, .+m(.+)-" >
or did I forget something. BTW the original Prompt looks like
3340h, 3796m ex-
Do I have to strip all Ansi-Codes too? And...*shrug*. Any Ideas? Thank you for the help.
This is about the only thing that matches the prompt. But the problem I have now that there is on effect by adding a "\n", still needing a manual Enter. The rest of the Plugin is exactly the same as in the forum.
This is my function
function OnPluginPacketReceived (s)
if (re:match(s)) then
return s .. "\n"
else
return s .. "not matched"
end -- if
end -- function OnPluginPacketReceived
I have no idea how OnPluginPacketReceived works so i lay my fate in your hands *chuckle*
This is about the only thing that matches the prompt. But the problem I have now that there is on effect by adding a "\n", still needing a manual Enter.
What do you mean? It works, but it doesn't work?
Are you seeing "not matched" popping up all the time in your output window?
What the plugin is supposed to do is modify the incoming packet, so MUSHclient thinks the <enter> is there all along.
If the prompt has ANSI codes you will need to detect those, after all the trigger is matching literally. Try using Edit -> Debug Packets to see exactly what is arriving.
The prompt is detected but I dont see any difference in behavior of my script.
I dont see any "not matched" in my window. But I have another script catching the health and mana-values and if it falls below x, I should sip some elixirs.
The bad thing is that I only drink if something else happens in the mud or ... if I press Enter manually, so the plugin doesnt affect that. The Autosipper is NO plugin or should it be one?
I use 3.65, and the regexp matches the prompt.....if I do
function OnPluginPacketReceived (s)
if (re:match(s)) then
return s .. "Eureka!!\n"
else
return s .. "not matched"
end -- if
end -- function OnPluginPacketReceived
I see lots of Eurekas after every prompt, but no autosip until i hit Enter. Maybe I should check the Autosipper, I am very new to Mush and never heard of Lua before.
If you are seeking Eurekas then clearly the plugin is working. Now you need to see what the autosipper is doing. Are there some tests in it that stop it working immediately?
Also, some of those were written before the days when you could force newlines on prompts, and detected a line *without* a newline.
Now, you just need a simple trigger to detect the incoming prompt.
It took long, but after lots of debugging (thanks to Notes) I found the error. It wasnt the plugin, it was indeed the Sipper. This is what the problem caused...
ok, here is the evil chunk of script causing the problem
function PromptCheck (name, output, wildcs)
health = tonumber(wildcs[1])
mana = tonumber(wildcs[2])
if autoHeal == 1 and var.elixBalance == "1" then
if health < 2500 then
Send ("drink health")
SetVariable("elixBalance", "0")
var.elixBalance = "0"
DoAfterSpecial (5, "SetVariable('elixBalance', '1')", 12)
end --if health
if mana < 3500 then
Send ("drink mana")
var.elixBalance = "0"
SetVariable("healthBalance", "0")
DoAfterSpecial (5, "SetVariable('elixBalance', '1')", 12)
end --if mana
end -- if autoheal
end --function
The problem is that the Variable healthBalance gets the new Value, and though the new sip-command is being triggered after another Enter/Mudoutput.
However with "send to script" you may as well be consistent and do it the same way:
DoAfterSpecial (5, "var.elixBalance = 1", 12)
You don't really need to quote the '1' because MUSHclient variables are always stored as strings, they will be converted for you.
I'm not sure what the variable healthBalance is being used for. You set it to zero at one point but never to any other value.
Perhaps it would work better like this:
function PromptCheck (name, output, wildcs)
local health = tonumber (wildcs [1])
local mana = tonumber (wildcs [2])
if autoHeal == 1 then
if health < 2500 and var.elixBalance == "1" then
Send ("drink health")
var.elixBalance = 0
DoAfterSpecial (5, "var.elixBalance = 1", 12)
end --if health
if mana < 3500 and var.healthBalance == "1" then
Send ("drink mana")
var.healthBalance = 0
DoAfterSpecial (5, "var.healthBalance = 1", 12)
end --if mana
end -- if autoheal
end --function
oops, I was playing around with the two sets of varibles, this is why I had a double varible assignment. After trying various combinations of varibles (Mush/Scipt) I came to the conclusion that its much easier jsut using scrip-internal ones, and even the annoying "wait-for-enter" problem is solved. The sipper works great now.
I do understand that...But it's faster if a client does it itself, not some workaround plugin (GA/EOR gets sent, why just ignore it?) . To me, it is just a convenience question.
It works great and achieves what I needed. However, when the trigger matches and the newline is put in, is there any way to get the next packet to start on that newline? I'm now getting an extra blank line after every prompt which is incredibly spammy when you're in combat on the MUD I play (Aetolia).
Here's an example of what my output looks like without the plugin:
H:2886 M:2952 E:14090 W:17420 B:100% [db eb]
(Novices): Bob says, "No? It is a friendly little competition that will
earn you gold and perhaps a prize."
H:2886 M:2952 E:14090 W:17420 B:100% [db eb]
(Novices): Jim says, "Hmm, well i never did it before."
H:2886 M:2952 E:14090 W:17420 B:100% [db eb]
(Novices): Wendy says, "Ooh.. it can be fun."
H:2886 M:2952 E:14090 W:17420 B:100% [db eb]
With the plugin, the same output looks like this:
H:2886 M:2952 E:14090 W:17420 B:100% [db eb]
(Novices): Bob says, "No? It is a friendly little competition that will
earn you gold and perhaps a prize."
H:2886 M:2952 E:14090 W:17420 B:100% [db eb]
(Novices): Jim says, "Hmm, well i never did it before."
H:2886 M:2952 E:14090 W:17420 B:100% [db eb]
(Novices): Wendy says, "Ooh.. it can be fun."
H:2886 M:2952 E:14090 W:17420 B:100% [db eb]
After each prompt, the newline is blank and the next bit of output starts on the line after that. Is there any way to gag that blank line?
I know this doesn't seem too major, but when you get into player vs. player fights on this MUD, the text starts scrolling off the screen at an incredible rate and a blank line after each prompt makes it fly off even faster.
You'll need to translate that to your language of choice which shouldn't be a problem, and enable the "Triggers can match on empty line" option. This is probably most fitting inside a plugin.
I had thought of something like this, but the ^$ trigger never fired, I imagine it's because I was unaware of the "match triggers on empty line" option.
My problem now is . . . .where is that option?!? I can't find it! :)
It seems to be adding a line break at the end of every packet, regardless if it's a prompt or not. Now, this isn't usually a problem because, in most cases, the last line of a packet is the prompt, but when you stack a lot of commands and send them, the response from the server puts several prompts in a packet, and them sometimes ends the packet in the middle of a line, like this example:
Here you can see the packet ended in the middle of a line beginning with "You remove"
The next packet begins:
1 slippery elm, 31 20 73 6c 69 70 70 65 72 79 20 65 6c 6d 2c 20
bringing the tot 62 72 69 6e 67 69 6e 67 20 74 68 65 20 74 6f 74
al in the cache 61 6c 20 69 6e 20 74 68 65 20 63 61 63 68 65 20
to 110....[32mH: 74 6f 20 31 31 30 2e 0d 0a 1b 5b 33 32 6d 48 3a
2886.[37m.[32m M 32 38 38 36 1b 5b 33 37 6d 1b 5b 33 32 6d 20 4d
And continues on from there. So the line that was broken up by the packets was "You remove 1 slippery elm, bringing the total in the cache to 110."
This is how that line displayed in the output to the screen:
You remove
1 slippery elm, bringing the total in the cache to 110.
It should appear as:
You remove 1 slippery elm, bringing the total in the cache to 110.
I'm pretty sure that the plugin is causing this because the problem goes away when I uninstall it. Is there any way to stop it from adding that line break?
Please let me know if you need some more information.
Instead of appending newlines to prompts, on IRE games you could use a temporary patch (until version 3.66 comes out). The following plugin replaces the GO AHEAD codes (\ff\f9) which appear at the end of the packet with newlines (\0d\0a) and suppresses the extra newlines at the beginning of the next packet if GA was already replaced, removing the need for additional triggers to suppress extra empty lines, which result from duplicate newlines being produced. It's in Python since I didn't want to deal with Replace anymore, but it shouldn't be too hard to port to something else. The GA pattern is supposed to only match if it follows the "-" character (the last char in an Achaea prompt) so it would need to be replaced by something that's appropriate in your case:
I got python scripting up and running, so I gave this plugin a whirl. It's not putting any new lines in at all, which makes me think I haven't altered the plugin to properly catch the last character of a prompt line in Aetolia.
Prompts in Aetolia look like this:
H:3038 M:3579 E:15200 W:17420 B:100% [db eb]
They always end with the "]" character. With this in mind, I altered one line of the plugin as such:
pat1 = re.compile(u"\]\u044f\u0449$")
The "\-" has been replaced by "\]" now. But it doesn't seem to match this as the end of the prompt and no new lines are being added. Have I made this alteration correctly or is there something else that must be done?
This one replaces any and all GA codes it finds in a packet, still supressing extra newlines. You'll also need to replace the "-" char with your "]". The previous one only replaced the GA found at the very end of the packet, meaning that all other prompts were left untouched.
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE muclient>
<!-- Saved on Sunday, March 13, 2005, 4:11 PM -->
<!-- MuClient version 3.65 -->
<!-- Plugin "PromptCatcher_Achaea" generated by Plugin Wizard -->
<muclient>
<plugin
name="PromptCatcher_Achaea"
author="Keldar"
id="8f85913ad96bd5bc255e434a"
language="Python"
purpose="Capturing prompts"
date_written="2005-03-13 16:10:15"
requires="3.65"
version="1.0"
>
</plugin>
<script>
<![CDATA[
import re
pat1 = re.compile(u"(\-\u044f\u0449)($)?")
pat2 = re.compile("^\x0d\x0a")
terminated = False
def repl(mo):
global terminated
if mo.groups()[1] == "":
terminated = True
return "-\x0d\x0a"
def OnPluginPacketReceived(packet):
global terminated, pat1,pat2
if terminated:
packet = pat2.sub("",packet)
terminated = False
packet = pat1.sub(repl, packet)
return packet
]]>
</script>
</muclient>
Thanks for all your help, but I'm still not having any luck with this plugin. It's not adding any new line breaks. I wish I could give you more instructive feed back, but I don't know python or how to read packets all that well.
Here are the changes I made to the plugin:
pat1 = re.compile(u"(\]\u044f\u0449)($)?")
and
return "]\x0d\x0a"
Here's a sample of some output I got when I spammed getting several different herbs from my cache:
H:3260 M:3579 E:15200 W:17420 B:100% [d eb]You remove 1 prickly ash bark, bringing the total in the cache to 101.
H:3260 M:3579 E:15200 W:17420 B:100% [d eb]You remove 1 goldenseal root, bringing the total in the cache to 111.
H:3260 M:3579 E:15200 W:17420 B:100% [d eb]You remove 1 kelp, bringing the total in the cache to 106.
H:3260 M:3579 E:15200 W:17420 B:100% [d eb]You remove 1 lobelia seed, bringing the total in the cache to 98.
H:3260 M:3579 E:15200 W:17420 B:100% [d eb]You remove 1 ginseng root, bringing the total in the cache to 134.
H:3260 M:3579 E:15200 W:17420 B:100% [d eb]You remove 1 bellwort flower, bringing the total in the cache to 135.
H:3260 M:3579 E:15200 W:17420 B:100% [d eb]You remove 1 slippery elm, bringing the total in the cache to 112.
H:3260 M:3579 E:15200 W:17420 B:100% [d eb]You remove 1 bloodroot leaf, bringing the total in the cache to 74.
H:3260 M:3579 E:15200 W:17420 B:100% [d eb]You remove 1 valerian, bringing the total in the cache to 17.
H:3260 M:3579 E:15200 W:17420 B:100% [d eb]You remove 1 skullcap, bringing the total in the cache to 118.
H:3260 M:3579 E:15200 W:17420 B:100% [d eb]You remove 1 irid moss, bringing the total in the cache to 71.
H:3260 M:3579 E:15200 W:17420 B:100% [d eb]You remove 1 hawthorn berry, bringing the total in the cache to 83.
H:3260 M:3579 E:15200 W:17420 B:100% [d eb]You remove 1 bayberry bark, bringing the total in the cache to 27.
H:3260 M:3579 E:15200 W:17420 B:100% [d eb]You remove 1 sileris, bringing the total in the cache to 13.
H:3260 M:3579 E:15200 W:17420 B:100% [d eb]You remove 1 black cohosh, bringing the total in the cache to 115.
H:3260 M:3579 E:15200 W:17420 B:100% [d eb]You remove 1 kola nut, bringing the total in the cache to 94.
H:3260 M:3579 E:15200 W:17420 B:100% [d eb]You remove 1 echinacea, bringing the total in the cache to 27.
As you can see, the newlines aren't being added at all. Is there any more information I could give you that might help solve this problem?
Strange, it works for me on Achaea, although it still has the same problem as Lusternia's server-side prompt newlines - extra empty lines every once in a while. About the only thing that comes to my mind is that you somehow managed to get the non-Unicode version of Python, or maybe pywin32. Replace the OnPluginPacketReceived function with the following one and post the output it gives:
You remove 1 kelp, bringing the total in the cache to 104.
H:3260 M:3479 E:10672 W:17420 B:100% [db eb]You remove 1 irid moss, bringing the total in the cache to 69.
The output to the notepad was:
u'You remove 1 kelp, bringing the total in the cache to 104.\r\n\x1b[32mH:3260\x1b[37m\x1b[32m M:3479\x1b[37m\x1b[1;33m E:10672\x1b[0;37m\x1b[32m W:17420\x1b[37m\x1b[1;31m B:100%\x1b[0;37m [db eb]\xff\xf9'u'You remove 1 irid moss, bringing the total in the cache to 69.\r\n\x1b[32mH:3260\x1b[37m\x1b[32m M:3479\x1b[37m\x1b[1;33m E:10672\x1b[0;37m\x1b[32m W:17420\x1b[37m\x1b[1;31m B:100%\x1b[0;37m [db eb]\xff\xf9'
Once again - very strange. Either your Python is screwed up, or mine is :) The problem is that the GA regexp is set to match on the Unicode escape of "\u044f\u0449", which is what I get, but in your case it seems that the GA code is the normal "\xff\xf9". So to fix it, simply replace the pattern for pat1 with: "(\-\xff\xf9)($|\x0d\x0a)?". The extra option in the second group, seems to capture most of the extra lines, and won't hurt in any case.
Hiya, umm, I'm sort of having a similar problem with MUSH, and Achaea and after having pretty much experienced all of the above! I was wondering if I could get some help with these scripts, me having to pick up what I can from examples etc. :)
Basically, I used the updated script by Nick, and got the extra spaces, the weird newlines on things that aren't prompts, so I went back to the first one that was put up.
I'm also using that "Deletes the empty spaces trigger" using "^$", which is a little inconvenient but works, expecially since I've never heard of Python before, or could figure out which bits to change into VBscript (which is what I'm using).
Well, now theres a slight problem that the prompt isn't being picked up, on -every- prompt that comes, basically whenever a few lines are sent rapidly to the world consecutively... possibly its not the fact they're being sent, but that information is coming back too fast...
Its frustrating, especially when important triggers are set for those lines and they aren't recognised... I can't quite seem to figure out how to make either:
1 The prompt be recognised regardless of whats in front or behind (perhaps if the plugin isn't detecting it for some reason).
or 2 Make a trigger, that will send the real command back through the system, since what I've been doing mostly, is putting a trigger that captures stuff that might be tagged onto a prompt and reoutputting it, minus prompt stuff. This doesn't trigger anything though.
Wow, hope that was easy to understand, I'm running 3.65 so any help would be greatly appreciated! Thanks.
I am new to this mushclient but i'm playing achaea and this newline trick is vital.
An enhancement to the gagging trigger would be to use the GetLineCount function. In Vbscript, my blank line gagging trigger is linked to this sub.
Sub GagBlankLine (name, line, wildcards)
dim Prompt
Prompt = World.GetVariable ("PromptLine")
If World.GetLineCount > Prompt + 1 Then
World.Note " "
End If
End Sub
I assume that there is a sub processing the prompt, the trick is to use GetLineCount to get the unique line number of the prompt and to put it in a Variable with World.SetVariable.
Now just link the gagging trigger to a simple sub which will compare the line number of the gag trigger to the line number of the last prompt. Now if the difference is greater than one, it would mean that this "new line" has not been "forced" and this "new line" is coming from the mud which could easily be re_created with a world.send " ".