Register forum user name Search FAQ

Gammon Forum

Notice: Any messages purporting to come from this site telling you that your password has expired, or that you need to "verify" your details, making threats, or asking for money, are spam. We do not email users with any such messages. If you have lost your password you can obtain a new one by using the password reset link.
 Entire forum ➜ MUSHclient ➜ Lua ➜ Lua modules supplied with MUSHclient

Lua modules supplied with MUSHclient

This subject is now closed.     Refresh page


Posted by Nick Gammon   Australia  (23,072 posts)  Bio   Forum Administrator
Date Sat 19 Apr 2008 02:09 AM (UTC)

Amended on Sat 17 Feb 2018 10:26 PM (UTC) by Nick Gammon

Message
This page can be quickly reached from the link: http://www.gammon.com.au/modules


The directory "lua" which is created as part of a MUSHclient standard installation contains the following Lua "modules":


  • addxml.lua - add triggers, timers, aliases, macros by supplying a table (and convert back to a table)
  • alphanum.lua - sort names into a more "natural" order
  • check.lua - check a world function return code
  • commas.lua - rounding, duration and comma functions
  • copytable.lua - does a deep or shallow copy of a Lua table
  • declare.lua - ensure variables in a function are declared
  • getlines.lua - iterator to convert a block of text into lines
  • getstyle.lua - finds a style run corresponding to a given column
  • getworld.lua - finds another world, and lets you send text to it
  • movewindow.lua - lets you drag miniwindows around
  • pairsbykeys.lua - iterator to traverse a table, sorted by key order
  • serialize.lua - serialize Lua variables into a string
  • strict.lua - enforce use of local variables inside functions
  • tabbed_window.lua - lets you make miniwindows with tabs
  • tprint.lua - table printer
  • var.lua - use MUSHclient variables as if they are Lua variables
  • wait.lua - for pausing scripts until time elapsed, or certain text arrives from the MUD


This thread describes the purpose of each one, and where to find out more about them.

The general way to use any of these modules is to "require" the module, which is the file name above without the ".lua" part, and then go ahead and use the documented functions in the module.

For example:


require "tprint"

tprint (math)  --> lists all the math functions in the output window


It is a feature of the way that "require" works, that you can use it repeatedly with very little overhead. Lua first checks to see if the wanted function has already been loaded, and if so, does not reload it from disk.

Thus you could conceivably do a require "serialize" in every function that needs to use it, rather than fiddling around trying to do it once in a central place, if that makes coding easier.

Documentation

Each of the modules tries to be self-documenting, so if you open them up in a text editor, there may be further examples and suggestions for using them, in addition to what is written below.



addxml.lua

This lets you add triggers, aliases, timers, or macros by specifying each parameter in a Lua table, which is easier in many ways than getting the correct arguments to AddTrigger etc.

You can also use the addxml.save to do the inverse operation - save an existing trigger, alias, timer or macro as a table.

See forum thread: http://www.gammon.com.au/forum/?id=7123

Exposed functions are:


  • addxml.trigger (t) --> add a trigger
  • addxml.alias (t) --> add an alias
  • addxml.timer (t) --> add a timer
  • addxml.macro (t) --> add a macro
  • addxml.save (type, name) --> convert one of the above back into a table


Example:


require "addxml"

addxml.trigger {
  enabled = 'y',
  custom_colour = '17',
  sequence = '100',
  other_text_colour = 'salmon',
  match = '[Public] * says, "*"',
  name = 'mytrigger',
  }


This adds a new trigger with all the appropriate values as specified.



alphanum.lua

This lets you sort strings with numbers in them into a more "natural" order. For example, normal sorting would put "a100" before "a2". This module provides a comparison routine that "chunks" up strings into batches of letters and numbers, and sorts them individually.

See forum thread: http://www.gammon.com.au/forum/?id=8698

Exposed function is alphanum.

Example:


require "alphanum"

t={
"z18.doc","z19.doc","z2.doc","z16.doc","z17.doc",
"z1.doc","z101.doc","z102.doc","z11.doc","z12.doc",
"z13.doc","z14.doc","z15.doc","z20.doc","z3.doc",
"z4.doc","z5.doc","z6.doc","z10.doc","z100.doc",
"z7.doc","z8.doc","z9.doc", "Z9A.doc",
}

table.sort(t, alphanum (t))

for i=1, #t do
   print(t[i])
end




check.lua

This implements a simple check function, that checks the return codes from the many MUSHclient script functions that return a "status code". This can be useful for catching errors in things like AddTrigger, which would otherwise silently fail.

See forum thread: http://www.gammon.com.au/scripting - look about halfway down at the posting about "Checking return codes".

Exposed functions are:


  • check (code) --> checks argument is zero, if not raises an error


The error message is the correct message from this page:

http://www.gammon.com.au/scripts/doc.php?general=errors

Note that this function is built into MUSHclient from version 4.28 onwards, so you don't need to "require" it.

Example:


require "check"

check (SetVariable ("abc", "def"))  --> works ok
check (SetVariable ("abc-", "def")) --> Error: The name of this object is invalid




commas.lua

This implements four useful functions:


  • round - to round a floating-point number to the nearest integer
  • convert_time - express an interval of seconds as days/hours/minutes etc.
  • commas - add commas to big numbers
  • scan_dir - directory scanner


See forum thread: http://www.gammon.com.au/forum/?id=7805

If you can't find commas.lua in your distribution, there is a copy of it in that thread.

Exposed functions are:


  • round (x) - rounds the argument to the nearest integer
  • convert_time (secs) - converts a numbers of seconds to the nearest relevant interval (eg. 65 seconds becomes "1 m" whereas 119 seconds becomes "2 m")
  • commas (num) - takes a number and adds commas to it (eg. 123456 becomes "123,456")
  • scan_dir (path, f) - scans disk starting at "path" calling function "f" for each file



Example:


require "commas"

print (round (1.5))   --> 2
print (round (-99.8)) --> -100

print (convert_time (70))     --> 1 m
print (convert_time (1000))   --> 17 m
print (convert_time (10000))  --> 3 h
print (convert_time (100000)) --> 1 d

print (commas (123456789)) --> 123,456,789

scan_dir (GetInfo (60),  function (name, stats) print (name, stats.size) end)


More information about the scan_dir function:

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




copytable.lua

Implements a deep or shallow copy of a Lua table.

See forum thread: http://www.gammon.com.au/forum/?id=8042

Normally in Lua if you simply assign a table variable to another variable, you get the original table, not a copy. However by using copytable you actually get a copy of the table.

Exposed functions are:


  • copytable.shallow (t) --> shallow copy of first level values
  • copytable.deep (t) --> copies table, and any nested tables are also copied


For tables which themselves contain nested tables, you may wish to use copytable.deep which effectively "recurses" to make a copy of those tables as well.

Example:


t1 = {5, 6, 7}
t2 = t1 
t2 [3] = 8  --> change t2
print (t1 [3])  --> prints 8, not 7
print (t2 [3])  --> prints 8, as expected


However by using copytable, you get a completely new table:


require "copytable"

t1 = {5, 6, 7}
t2 = copytable.shallow (t1)
t2 [3] = 8
print (t1 [3])  --> prints 7
print (t2 [3])  --> prints 8




declare.lua

Forces you to declare variables (by using the "local" keyword), rather than relying upon "on-the-fly" creation of new variables, which Lua normally does.

See forum thread: http://www.gammon.com.au/forum/?id=7327

Exposed functions are:


  • force_declarations () --> after calling this, all variables must be declared


Example:


require "declare"

a = 42  --> works OK, we haven't called "force_declarations" yet
force_declarations ()  --> from now on, we have to declare variables
local b = 55  --> works OK, we used "local" to declare the variable "b"
c = 66  --> Error: assign to undeclared variable 'c'


The purpose of this is to catch spelling errors in functions, for example, in the above code, if we really meant to say "b = 66" rather than "c = 66" then the error message would alert us.

Also see "strict.lua" below for doing this a bit differently.



getlines.lua

Provides an iterator function to break a string into individual lines.

See forum thread: http://www.gammon.com.au/forum/?id=6544

Exposed functions are:


  • getlines (s) --> iterator to be used in a for loop


Example:


require "getlines"
 
s = [[
every good
boy
deserves 
fruit]]

for line in getlines (s) do
  print (line)  --> print each line
end -- for loop




getstyle.lua

Finds a style run corresponding to a given column. This is intended to be used in situation (like triggers) where you have a "style run" table provided by MUSHclient, and want to find the style of a column (eg. column 15).

You might use this to see if a particular word in a particular column is a certain colour (eg. is the word "bleeding" in red?).

See forum thread: http://www.gammon.com.au/forum/?id=7818

Exposed functions are:


  • GetStyle (styles, column) --> get style items for this column



Example:



require "getstyle"

function my_trigger (name, line, wildcards, styles)
 
  -- find location of word
  col = string.find (line, "bleeding")
  if not col then
    return
  end -- word not found

  -- get style at that location
  style = GetStyle (styles, col)

  -- display it
  print ("word is in", RGBColourToName (style.textcolour))
 
end -- function my_trigger


The above example trigger function uses the style runs table supplied as the fourth argument to a trigger function. It first locates the column in which "bleeding" is, and then finds the style of that column.

It then displays the colour in which the (first letter of) the word "bleeding" is.

Note - capitalization of the function name is "GetStyle", but the module is "getstyle".



getworld.lua

Lets you get a reference to another MUSHclient world, loading it from disk if necessary. Also lets you send trigger data from one world to another.

See forum thread: http://www.gammon.com.au/forum/?id=7991&page=3

Exposed functions are:


  • get_a_world (name) --> returns a "world object" for operating on the named world


The world file is opened if not already opened by appending ".mcl" to the name, and looking in the default MUSHclient worlds directory. If the world cannot be opened nil is returned.

Example:


require "getworld"

local w = GetWorld ("SMAUG chats")
if w then  -- if found
    w:DeleteOutput ()
end -- if



  • send_to_world (name, styles) --> sends the style runs to the named world


Sends the style runs to the named world. It first calls get_a_world (above) and if successful, sends the style runs to it. This effectively lets you write a trigger that sends the matching line, including all colours, to another world window. For example, to filter chats, who lists, and suchlike.

Example:


function mytrigger (name, line, wildcards, styles)
  require "getworld"
  send_to_world ("SMAUG chats", styles)
end -- function




movewindow.lua

This lets you attach a "drag handler" to a miniwindow, letting you drag the window around on the screen to reposition it.

See forum thread: http://www.gammon.com.au/forum/?id=9594

Exposed functions are:


  • movewindow.install (win, default_position, default_flags, nocheck, friends, preprocess, start_position)


Example:


  require "movewindow" 
  windowinfo = movewindow.install (win, miniwin.pos_center_right, 0)  -- default position / flags


The values in "windowinfo" table can now be used to create the miniwindow in the desired position. For example:


  WindowCreate (win, 
                windowinfo.window_left, 
                windowinfo.window_top, 
                WINDOW_WIDTH,    
                WINDOW_HEIGHT,  
                windowinfo.window_mode, 
                windowinfo.window_flags, 
                ColourNameToRGB "slategray") 



  • movewindow.add_drag_handler (win, 0, 0, 0, 0, miniwin.cursor_both_arrow)


Installs the drag handler for the miniwindow. Part or all of the window can be designated as the "drag zone". In the above example, the entire window is the drag zone. Typically you would use the title bar (if the window has one) as the drag zone.


  • movewindow.save_state (win)


This is used to save the window position when saving the plugin state (if you do that). For example:


function OnPluginSaveState ()
  -- save window current location for next time  
  movewindow.save_state (win)
end -- function OnPluginSaveState




pairsbykeys.lua

Provides an iterator function to access a table in alphabetic order, by key.

See forum thread: http://www.gammon.com.au/forum/?id=6036

Exposed functions are:


  • pairsByKeys (t, f) --> iterator to be used in a for loop using optional comparison function f


Example:


require "pairsbykeys"

-- This prints the math functions in key order
for k, v in pairsByKeys (math) do
  print (k, v)
end -- for


The iterator function works by making a temporary table into which it copies all the keys, sorts this temporary table, and then returns each one per iteration, in alphabetic order.

You can provide your own comparison function (less-than function) if you want to compare in some other sequence (eg. descending). For example:


require "pairsbykeys"

function gt (a, b)
  return a > b
end -- gt

-- This prints the math functions in descending key order
for k, v in pairsByKeys (math, gt) do
  print (k, v)
end -- for


This example reverses the normal sort sequence, because the supplied function is supposed to compare for "less than" but we compare for "greater than".

Note - capitalization of the function name is "pairsByKeys", but the module is "pairsbykeys".



serialize.lua

Converts a table into a string, suitable for storing to disk.

See forum thread: http://www.gammon.com.au/forum/?id=4960

Exposed functions are:


  • serialize.save (name, v, t) --> complex serialization
  • serialize.save_simple (v) --> serialize simple tables


Read the forum thread for full details, but basically if you have a table of iteme (eg. mob names, and how many HP each one has) you can use serialize.save to turn that table into a string. It can then be sequently loaded back as a Lua table by doing a "loadstring".

Example:


require "serialize"

mobs = {}  -- create mobs table

mobs.kobold = {
  name = 'killer',
  hp = 22,
  gold = 5,
  location = 'city square',
  treasure = { "sword", "gold", "helmet" } -- sub table
  }

-- and another one ...

mobs.worm = {
  name = 'gordon',
  hp = 4,
  gold = 15,
  location = 'underground',
  treasure = { "food", "knife" },
  attacks = { "bite", "poison" }
  }

s = serialize.save ("mobs")

print (s)


This prints:


mobs = {}
  mobs.kobold = {}
    mobs.kobold.treasure = {}
      mobs.kobold.treasure[1] = "sword"
      mobs.kobold.treasure[2] = "gold"
      mobs.kobold.treasure[3] = "helmet"
    mobs.kobold.name = "killer"
    mobs.kobold.gold = 5
    mobs.kobold.location = "city square"
    mobs.kobold.hp = 22
  mobs.worm = {}
    mobs.worm.attacks = {}
      mobs.worm.attacks[1] = "bite"
      mobs.worm.attacks[2] = "poison"
    mobs.worm.treasure = {}
      mobs.worm.treasure[1] = "food"
      mobs.worm.treasure[2] = "knife"
    mobs.worm.name = "gordon"
    mobs.worm.gold = 15
    mobs.worm.location = "underground"
    mobs.worm.hp = 4


In the above example, we can get our table back like this:


mobs = nil  --> table gone now
assert (loadstring (s)) ()  --> load string "s"
require "tprint"  --> for printing
tprint (mobs) --> table exists, see below


This prints (using tprint described later on):


"kobold":
  "treasure":
    1="sword"
    2="gold"
    3="helmet"
  "name"="killer"
  "gold"=5
  "location"="city square"
  "hp"=22
"worm":
  "attacks":
    1="bite"
    2="poison"
  "treasure":
    1="food"
    2="knife"
  "name"="gordon"
  "gold"=15
  "location"="underground"
  "hp"=4


This shows that we have recreated our mobs table, from the string we got after doing a serialize.

We can also use serialize.save_simple to make a simpler looking table than the one earlier, like this:


s = "mobs = " .. serialize.save_simple (mobs)

print (s)


This prints (for the same mobs table as before) the following:


mobs = {
  kobold = {
    treasure = {
      [1] = "sword",
      [2] = "gold",
      [3] = "helmet",
      },
    name = "killer",
    gold = 5,
    location = "city square",
    hp = 22,
    },
  worm = {
    attacks = {
      [1] = "bite",
      [2] = "poison",
      },
    treasure = {
      [1] = "food",
      [2] = "knife",
      },
    name = "gordon",
    gold = 15,
    location = "underground",
    hp = 4,
    },
  }


Notice how this example looks less "wordy" then doing serialize.save.

I also needed to concatenate "mobs = " to the string returned by serialize.save_simple as this works slightly differently in that it doesn't know the name of the variable, thus I have to supply it.



strict.lua

This function was written by Roberto Ierusalimschy, the developer of Lua. Once you "require" it, it modifies the "global namespace" so that you must declare variables before using them. To "declare" a variable you simply assign to it in global scope. Until you have done that, you are not allowed to read from "undeclared" variables.

See forum thread: http://www.gammon.com.au/forum/?id=7335

If you can't find strict.lua in your distribution, there is a copy of it in that thread.

This works a bit differently from declare.lua described earlier. Here, you simply need to assign something to a variable in global scope (that is, not inside a function) for it to become declared.

Exposed functions are:


  • (none) - you simply "require" it to get the functionality


Example:


require "strict"

a = 20  --> declare "a" by assigning to it
print (a)  --> prints 20
print (b)  --> Error: variable 'b' is not declared




tabbed_window.lua

This lets you set up a miniwindow with "tabs". That is, you can have selectable panes of information which display depending on which tab you click on.

See forum thread: http://www.gammon.com.au/forum/?id=14161

Exposed functions are:


  • init (context) - initialize the module
  • draw_window (context, which_tab) - draws the window, switching to which_tab
  • hide_window (context) - hides the window
  • save_state (context) - to be called from OnPluginSaveState


Example:


require "tabbed_window"

function DrawFoo (win, left, top, right, bottom, context)
  WindowText (win, context.tabfont.id, "This is the foo tab", 
             left + 10, top + 10, 0, 0, ColourNameToRGB "green")
end -- DrawStats

function DrawBar (win, left, top, right, bottom, context)
  WindowText (win, context.tabfont.id, "This is the bar tab", 
              left + 10, top + 10, 0, 0, ColourNameToRGB "darkblue")
end -- DrawEquipment

context = { 

 win = "tabbed_window" .. GetPluginID (),

 tabs = {
      { name = "Foo",       handler = DrawFoo },
      { name = "Bar",       handler = DrawBar },
      } -- end of tabs
    }  -- end of context
    
        
tabbed_window.init (context)
tabbed_window.draw_window (context, 1)




tprint.lua

Table printer - prints a Lua table recursively - that is, it shows every item in the table, and then recurses to show sub-tables.

See forum thread: http://www.gammon.com.au/forum/?id=4903

Exposed functions are:


  • tprint (t) - print table t


Example:


require "tprint"

mobs = {}  -- create mobs table

mobs.kobold = {
  name = 'killer',
  hp = 22,
  gold = 5,
  location = 'city square',
  treasure = { "sword", "gold", "helmet" } -- sub table
  }

-- and another one ...

mobs.worm = {
  name = 'gordon',
  hp = 4,
  gold = 15,
  location = 'underground',
  treasure = { "food", "knife" },
  attacks = { "bite", "poison" }
  }

tprint (mobs)


This prints the mobs table as follows:


"kobold":
  "treasure":
    1="sword"
    2="gold"
    3="helmet"
  "name"="killer"
  "gold"=5
  "location"="city square"
  "hp"=22
"worm":
  "attacks":
    1="bite"
    2="poison"
  "treasure":
    1="food"
    2="knife"
  "name"="gordon"
  "gold"=15
  "location"="underground"
  "hp"=4


Note the way that nested tables are indented. If the key is a string it is quoted, otherwise it is shown not quoted. This helps distinguish a table key 10 (the number) from "10" (the string).



var.lua

This creates a special table "var" which lets you access MUSHclient variables as if they were inside a Lua table.

See forum thread: http://www.gammon.com.au/forum/?id=4904

Exposed items are:


  • var - variables table


Example:


require "var"

var.target = "kobold"   -- set MUSHclient variable 'target' to 'kobold'
print (var.target)      -- print contents of MUSHclient variable 'target'


If the table item does not exist, nil is returned. You can delete an item by assigning nil to it. For example:


print (var.foo)   -- nil (foo does not exist)
var.target = nil  -- delete the variable "target"




wait.lua

Lets you script pauses inside triggers and aliases, where you wait for time to elapse, or some text to arrive from the MUD.


See forum thread: http://www.gammon.com.au/forum/?id=4956 (waiting for time)
and: http://www.gammon.com.au/forum/?id=4957 (waiting for text from the MUD)

Exposed functions are:


  • wait.make (f) - make and calls a function which can pause (a coroutine)

  • line, wildcards, styles = wait.regexp (regexp, timeout) - wait for a trigger with a regular expression

    If no match (ie. a timeout) then the returned values: line, wildcards, styles are all nil.

  • line, wildcards, styles = wait.match (what, timeout) - wait for a trigger with "normal" match text

    If no match (ie. a timeout) then the returned values: line, wildcards, styles are all nil.

  • wait.time (secs) - wait for some time to elapse


(The timeouts are optional and can be omitted).

Example:


require "wait"

wait.make (function ()  --- coroutine below here

  repeat
    Send "cast heal"
    line, wildcards = 
       wait.regexp ("^(You heal .*|You lose your concentration)$", 10)

  until line and string.match (line, "heal")

  -- wait a second for luck
  wait.time (1) 

  Note ("heal done!")

end)  -- end of coroutine


The above example uses make.wait to make an inline (anonymous) function that does the actual waiting. This is needed to create a coroutine which can be paused.

Inside the function we do wait.regexp to wait for certain text to arrive fromt he MUD, with a timeout of 10 seconds. If we successfully heal someone we then use wait.time to wait a further second, and we are done.

If we don't successfully heal, the coroutine loops and casts another "heal".

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Nick Gammon   Australia  (23,072 posts)  Bio   Forum Administrator
Date Reply #1 on Sat 19 Apr 2008 09:34 PM (UTC)
Message
Plugins

The modules described above are intended for Lua scripters to use to supplement their own scripts. This differs from Plugins where are self-contained files which can be added to MUSHclient worlds. Plugin authors may well use the above modules to help write a plugin.

If you are not interested in scripting, or do not use Lua, then you should look at the Plugins feature of MUSHclient.

See: http://www.gammon.com.au/plugins/ for a list of available plugins.

Also see: http://www.gammon.com.au/forum/?bbtopic_id=108 - this part of the forum deals with plugins, and has some links to additional plugins not mentioned on the plugins page.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).

To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.


69,067 views.

This subject is now closed.     Refresh page

Go to topic:           Search the forum


[Go to top] top

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