Below is a version of the "random socials" plugin that has been shipping with MUSHclient for a while now, reworked into Lua.
This shows how you can save a Lua table into the plugin's state file (using serialize.save), and then when the plugin is used next time, convert the variable back into a table (using loadstring). It also uses a timer to save the plugin state every hour, just in case of a PC crash, you don't lose your plugin state.
It also handles the case of being run for the first time, by making an empty table, just in case.
It also demonstrates a couple of other interesting points, like using 'next' to see if a table is empty, and using string.gmatch to process a string and build items from it into a table.
This shows how you can save a Lua table into the plugin's state file (using serialize.save), and then when the plugin is used next time, convert the variable back into a table (using loadstring). It also uses a timer to save the plugin state every hour, just in case of a PC crash, you don't lose your plugin state.
It also handles the case of being run for the first time, by making an empty table, just in case.
It also demonstrates a couple of other interesting points, like using 'next' to see if a table is empty, and using string.gmatch to process a string and build items from it into a table.
<?xml Version="1.0" encoding="UTF-8"?>
<!DOCTYPE muclient [
<!ENTITY socials_command "socials" >
<!ENTITY end_socials_regexp "\>" >
<!ENTITY timer_interval "30" >
]>
<!--
Customising (change above entities) ...
Change "socials_command" to whatever sends a list of socials.
Default: socials
Change "end_socials_regexp" to whatever will *not* be in a socials line.
Default: >
Change "timer_interval" to be the number of seconds between checking for socials.
Default: 30 seconds
(Note - every "timer_interval" seconds there is a 20% chance that the social will be sent.)
-->
<muclient>
<plugin name="Random_Socials"
author="Nick Gammon"
language="Lua"
id = "e032b4b7db80da78a87dc708"
purpose = "Displays a random social from time to time"
save_state = "y"
date_written="2007-05-03 09:30"
requires="3.80"
version = "1.1"
>
<description Trim="y">
<![CDATA[
This plugin checks to see if it has a list of socials (in the "Socials" table).
If not, it sends "socials" to the MUD to build a list.
Then, every 30 seconds it has a 20% chance of displaying one picked at random.
Commands
--------
socials:Help - shows this description in the output window
socials:remove:all - removes all socials (ie. reloads the list)
socials:remove X - removes social X from the list (eg. socials:remove burp)
]]>
</description>
</plugin>
<script>
-- convert socials command (entity) into Lua variable
socials_command = "&socials_command;"
<![CDATA[
-- on plugin install, convert variable into Lua table
function OnPluginInstall ()
require "serialize" -- needed to serialize table to string
Socials = {} -- ensure table exists, if not loaded from variable
-- seed random number generator
math.randomseed (os.time ())
assert (loadstring (GetVariable ("Socials") or "")) ()
end -- function OnPluginInstall
-- on saving state, convert Lua table back into string variable
function OnPluginSaveState ()
SetVariable ("Socials", serialize.save ("Socials"))
end -- function OnPluginSaveState
]]>
</script>
<!-- =============================================
Timer: RandomSocial
Purpose: Chooses a social at random, builds the list if necessary
============================================= -->
<timers>
<timer
name="RandomSocial"
enabled="y"
second="&timer_interval;"
send_to="12"
>
<send>
--
-- Wait a minute after connecting to let them put in the character name and password
--
if (GetInfo (304) - GetInfo (301)) < 1 then
return
end -- if
--
-- if already collecting socials list, just wait for it to finish
--
if GetTriggerInfo ("Collect_Socials", 8) then
return
end -- if already doing it
--
-- if no socials list, get one
--
if next (Socials) == nil then
EnableTrigger ("Collect_Socials", true)
Send (socials_command) -- e.g. "socials"
Note ("Collecting list of socials ...")
return
end -- if
--
-- Do a random social (20% of the time)
--
if math.random () < 0.20 then
Send (Socials [math.random (1, #Socials)])
end -- if
</send>
</timer>
<timer enabled="y" hour="1" send_to="12">
<send>SaveState ()</send>
</timer>
</timers>
<!-- =============================================
Trigger: Collect_Socials
Purpose: Matches a line of socials
============================================= -->
<triggers>
<trigger
custom_colour="2"
match="^([A-Za-z ]+)$"
name="Collect_Socials"
regexp="y"
sequence="100"
send_to="12"
>
<send>
EnableTrigger ("End_Socials", true)
for w in string.gmatch ("%1", "%a+") do
table.insert (Socials, w)
end -- for each social
</send>
</trigger>
</triggers>
<!-- =============================================
Trigger: End_Socials
Purpose: Detects end of socials list - in this case we look for the > at the
start of a MUD prompt, but you could look for anything that wouldn't be
a social line.
============================================= -->
<triggers>
<trigger
custom_colour="1"
match="&end_socials_regexp;"
name="End_Socials"
regexp="y"
sequence="100"
send_to="12"
>
<send>
EnableTrigger ("Collect_Socials", false)
EnableTrigger ("End_Socials", false)
Note "End of socials list detected. Random socials now active."
</send>
</trigger>
</triggers>
<!-- =============================================
Alias: Remove_Social
Purpose: Removes a social from the list (eg. it might be inappropriate)
============================================= -->
<aliases>
<alias
name="Remove_Social"
match="^socials\:remove ([A-Za-z]+)$"
enabled="y"
regexp="y"
send_to="12"
>
<send>
local which = string.lower ("%1")
-- do linear search for it - key is the item number, value is the social
for k, v in ipairs (Socials) do
if string.lower (v) == which then
table.remove (Socials, k) -- delete from table
Note ("Social '" .. which .. "' removed.")
return -- all done
end -- if found
end -- for each social
Note ("Social '" .. which .. "' was not in the list.")
</send>
</alias>
</aliases>
<!-- =============================================
Alias: Remove_All_Socials
Purpose: Removes all socials (ie. forces list to be regenerated)
============================================= -->
<aliases>
<alias
name="Remove_All_Socials"
match="socials:remove:all"
enabled="y"
send_to="12"
>
<send>
Socials = {}
Note ("All socials removed from list.")
</send>
</alias>
</aliases>
<!-- =============================================
Alias: socials:Help
Purpose: Shows plugin Help
============================================= -->
<aliases>
<alias
match="socials:Help"
enabled="y"
send_to="12"
>
<send>
Note (GetPluginInfo (GetPluginID (), 3))
</send>
</alias>
</aliases>
</muclient>