Random socials plugin - Lua version - shows serializing data

Posted by Nick Gammon on Thu 03 May 2007 12:21 AM — 1 posts, 9,646 views.

Australia Forum Administrator #0
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.


<?xml Version="1.0" encoding="UTF-8"?>
<!DOCTYPE muclient [
  <!ENTITY socials_command "socials" > 
  <!ENTITY end_socials_regexp "\&gt;" > 
  <!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)) &lt; 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 () &lt; 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>