[Home] [Downloads] [Search] [Order] [Support] [Help/forum]

Gammon Software Solutions forum

Read the MUSHclient FAQ! (http://mushclient.com/faq)

[Folder]  Entire forum
-> [Folder]  MUSHclient
. -> [Folder]  Lua
. . -> [Subject]  Lua modules supplied with MUSHclient
Home  |  Users  |  Search  |  FAQ
Username:
Register forum user name
Password:
Forgotten password?

Lua modules supplied with MUSHclient

This subject is now closed.   [New subject]  Start a new subject   [Refresh] Refresh page


Posted by Nick Gammon   Australia  (12,065 posts)  [Biography] bio
Date Sat 19 Apr 2008 02:09 AM (UTC)

Amended on Sat 21 Jun 2008 11:36 PM (UTC) by Nick Gammon

Message
This page can be quickly reached at http://mushclient.com/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)
  • 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
  • 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
  • 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.



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 three 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


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")



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





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





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





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)
  • wait.regexp (regexp, timeout) - wait for a trigger with a regular expression
  • wait.match (what, timeout) - wait for a trigger with "normal" match text
  • 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 string.find (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

Web: www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Nick Gammon   Australia  (12,065 posts)  [Biography] bio
Date 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

Web: www.gammon.com.au, www.mushclient.com
[Go to top] 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.


This subject is now closed.   [New subject]  Start a new subject   [Refresh] Refresh page

Go to topic:           Search the forum


[Go to top] top

[Home]

Written by Nick Gammon - 5K

Comments to: Gammon Software support
[RH click to get RSS URL] Forum RSS feed ( http://www.gammon.com.au/rss/forum.xml )

[Best viewed with any browser - 2K]    [Internet Contents Rating Association (ICRA) - 2K]    [Web site powered by FutureQuest.Net]