Register forum user name Search FAQ

Release notes for MUSHclient version 3.69


Version 3.69

Released on 22 Nov 2005

1. Added plugin callback OnPluginPlaySound. This lets you override the default sound-playing mechanism provided by MUSHclient so that you can play sounds using your own methods (eg. via calling COM objects).

Example:

function OnPluginPlaySound (sound)
Note ("Playing sound " .. sound)
end -- function


Once you have a plugin installed with this function defined, then MUSHclient will not use its internal sound-player.

If you select the menu item Display -> Stop Sound Playing, then your plugin OnPluginPlaySound will be called with an empty sound name.


2. Added new Lua script routine: utils.readdir

This reads an entire directory on your PC into a Lua table, based on the wildcard you supply.

------

t, e = utils.readdir ("c:/mushclient/plugins/*.xml")

assert (t, e) -- raises error on failure

for k, v in pairs (t) do
Tell (k)
if (v.directory) then
Tell (" (dir) ")
end -- if directory
Tell (" size ", v.size, " bytes, ")
Note (os.date ("%c", v.write_time))
end -- for

------

Example output:

ShowActivity.xml size 1429 bytes, 03/23/04 11:06:54
Slow_speedwalk.xml size 9655 bytes, 10/24/05 08:58:07
Automap.xml size 19944 bytes, 03/26/04 14:20:11

If the directory specification is matched, the result from the call is a table of directory items, keyed by the filename. If the directory specification cannot be matched, or is invalid, it returns nil followed by an error message. You can simply test for non-nil, or call "assert" to report the error.

For each file in the directory (that matches the wildcard) the following is returned:

size - file size in bytes
create_time - creation time (except for FAT filesystems, where it is omitted)
access_time - last access time (except for FAT filesystems, where it is omitted)
write_time - time written
archive - true if archive. Set whenever the file is changed, and cleared by the BACKUP command.
hidden - hidden file. Not normally seen with the DIR command
normal - normal file. File can be read or written to without restriction.
readonly - read-only. File cannot be opened for writing, and a file with the same name cannot be created.
directory - Subdirectory.
system - system file. Not normally seen with the DIR command.

By detecting suddirectories you could conceivably recurse and find the contents of subdirectories as well.


3. Added new Lua script routine: utils.xmlread

This uses MUSHclient's internal XML parser to parse an XML string you supply. This effectively would let you parse triggers, aliases etc. that you have copied to the clipboard as text (or created with ExportXML script routine), and see exactly what each value is set to. Or, by reading a MUSHclient world file into memory as a string, you could parse that.

The XML parser is not necessarily 100% industry-standard XML parsing, however it is the method MUSHclient uses for its own XML documents, and should be reasonably compatible with standard XML unless you use some of the more fancy XML extensions. It should certainly parse the XML output by MUSHclient itself (eg. triggers, aliases, world files, plugins) as that is the same routine it uses to read them in.

You pass to the parser a single string, which is the XML to be parsed. If the parsing is successful three results are returned:

* The root node (all other nodes are children of this node)
* The root document name (eg. "muclient")
* A table of custom entities in the document, or nil if no custom entities

If the parsing fails, three results are returned:

* nil - to indicate failure
* The error reason
* The line the error occurred at

You can pass the first 2 results to "assert" to quickly check if the parsing was successful.

Each node consists of a table with the following entries:

* name - name of the node (eg. <trigger>foo</trigger> - the name is "trigger")

* content - contents of the node (eg. <trigger>foo</trigger> - the content is "foo")

* empty - boolean to indicate if the node is empty. (eg. <br/> is an empty node)

* line - which line in the XML string the node occurred on (eg. line 5)

* attributes - a table of attributes for this node, keyed by the attribute name
(eg. "world_file_version"="15"). Attribute names have to be unique so we can used a keyed lookup to find them.

The attributes table is not present if there are no attributes defined.

* nodes - a table of child nodes, keyed by ascending number (the order they appeared in). Each child node has the same contents as described above.
Children are not necessarily unique (eg. there may be more than one <trigger> node in a document) so they are keyed by number, and not by node name.

The nodes table is not present if there are no children of this node.

Example of use:

-------
a, b, c = utils.xmlread [[
<foo width="1" height="2">
contents of foo
<bar west="true" fish="bicycle">
child of foo
</bar>
</foo>
<goat blood="100">eep</goat>
]]

if not a then
print ("error on line = ", c)
end -- if

assert (a, b)

tprint (a)

-------

Output:

"line"=0
"name"=""
"content"=""
"nodes":
1:
"line"=2
"name"="foo"
"nodes":
1:
"line"=4
"name"="bar"
"content"="
child of foo
"
"attributes":
"fish"="bicycle"
"west"="true"
"content"="
contents of foo

"
"attributes":
"height"="2"
"width"="1"
2:
"line"=8
"name"="goat"
"content"="eep"
"attributes":
"blood"="100"

-----

You can see from the above that the "root" node is really just an unnamed node which is the placeholder for the top level nodes (ie. the first "real" node is a child of the root node). In this case the node "foo" is the first child of the root node. The node "goat" is the 2nd child of the root node.

Custom entities are declared in the <!DOCTYPE> directive, like this:

<!DOCTYPE muclient [
<!ENTITY afk_command "afk" >
<!ENTITY timer_mins "5" >
<!ENTITY timer_secs "0" >
<!ENTITY afk_message "You are now afk." >
<!ENTITY not_afk_message "You are no longer afk." >
]>

If your XML document contains such entries, they will appear in the "custom entities" table returned as the 3rd result from utils.xmlread.

Note that custom entities are automatically replaced in the body of the document, it is not possible to reconstruct from the nodes where they occurred.


4. Fixed a bug in the XML parser, where a document like this would not raise an error: <foo>

Now you will get an error message:

Unexpected end-of-file while looking for </foo>


5. Changed the default scripting language (when you create new worlds) to Lua, as this is the recommended script language now.


6. Added new script function PasteCommand.

This pastes the supplied text into the command window, which does not have to be empty (unlike SetCommand) at the current cursor position, replacing any selection. It returns the text that it replaced, if any.

eg.

Command window reads:

go north
^^

("go" is selected)

You execute: s = PasteCommand ("walk")

Command window now reads:

walk north

s contains "go"

You could use this to make shortcut keys that paste frequently-used words into the command window.

For example:

/Accelerator ("Alt+N", "/PasteCommand 'swordfish'")

Now, whenever you hit Alt+N the word "swordfish" is pasted into the command window, replacing the current selection, or at the cursor.


7. Added new Lua script function: utils.split

This is intended to do the reverse of table.concat. That is, it takes a string and generates a table of entries, delimited by single-character delimiters (such as comma or newline).

Example:

test = "the,quick,brown,dog,jumped"

t = utils.split (test, ",")

tprint (t)

print (table.concat (t, ","))

Output:

1="the"
2="quick"
3="brown"
4="dog"
5="jumped"

the,quick,brown,dog,jumped

You pass utils.split 2 or 3 arguments:

* The string to be split
* The single-character delimiter
* (optional) the maximum number of splits to do

If the 3rd argument is not supplied, or is zero, then the entire string is split. Otherwise, it will be split the number of times you specify. eg.

t = utils.split (test, ",", 2)

tprint (t)

Output:

1="the"
2="quick"
3="brown,dog,jumped"

In this case the remaining text is placed in the 3rd table item.


8. Documented Lua-specific script routines (like utils.split) in the Help file, and online documentation.


9. Changed the "rex" library slightly (called from Lua) so that if you have an error in creating a PCRE regular expression it now tells you the column at which the error occurred (1-relative). eg.

rex.new ("(") --> raises the error: missing ) (pattern offset: 2)


10. Added the "check" function to the exampscript.lua file. This is designed to check for return codes from MUSHclient scripting functions - the ones that return eOK on success, and some error code on failure (not all do this). The function is:

function check (result)
if result ~= error_code.eOK then
error (error_desc [result], 2)
end -- if
end -- function check


Effectively it checks that the return code is eOK and if not, raises an error with a proper description.

eg.

check (DeleteAlias ("xx")) --> error: The specified alias name does not exist


11. Rewrote the functions waitforregexp and wait in the exampscript.lua to be a bit better coded. Recent improvements which added a timeout feature were done in a rather messy way. This version is cleaner.

View all MUSHclient release notes

Information and images on this site are licensed under the Creative Commons Attribution 3.0 Australia License unless stated otherwise.