wait.lua not working as expected.

Posted by hogarius on Sat 26 Jan 2013 10:39 PM — 6 posts, 22,701 views.

USA #0
I'm having problems with the wait.lua module.

I have MUSHclient version 4.86 installed on a Windows 7 machine, and I play Simutronics' Modus Operandi.

MO requires you to log into an authorization server, exchange some information with the server and use that information to log into the actual game server.

I have the following Simutronics.lua script file:



function ObtainK ()
	Send "K"
	KLine, wildcards = wait.regexp ("^(.*?)$", 10)
end --ObtainK()


function Main ()

	require "wait"

	wait.make (ObtainK)
	Note (KLine)

end --Main()



The first step in interacting with the Simu authorization server is to send "K" to the server. The server responds by sending a 32-character string of gibberish that is commungled with one's account password for additional processing. The script above is written to perform that first step.

When I reload the Simutronics.lua script, connect to the server and enter "/Main()" (without the quotes) from the command line, I get the following output.



K                                  <--in white, echo of "K" sent to server
nil                                <--in blue, MUSHclient Note of value of KLine
Fv`HOxP|aM\WfwE_lEP__eOsymNNWet   <--in white, response from server of 32-character string



This is a problem, because when I've added other functions to process the value of KLine in my Main () function, they read the value of KLine as nil.

However, if I run the Main () function as described above, and then type "/Note (KLine)" (without the quotes) into the command line immediately after running Main (), the value of the 32-character string is printed in blue.

I would appreciate any advice that anyone can give.

Thank you for your help.
Australia Forum Administrator #1
The problem is that the function ObtainK has paused (in the wait.regexp) but the function Main has not paused.

So the line:


	Note (KLine)


is done immediately after creating the coroutine.

Move that line into ObtainK and it will work.

Quote:

This is a problem, because when I've added other functions to process the value of KLine in my Main () function, they read the value of KLine as nil.


Put all that other stuff into (or subordinate to) ObtainK.

What really happens is that ObtainK is turned into a coroutine, and then paused (the coroutine yields). A trigger (or timer) fires and resumes the coroutine. That effectively gives you a pause or a wait for something to happen. Anything outside ObtainK is done instantly.
USA #2
Okay...say I have a series of functions, ObtainK(), ProcessK(), ObtainA(), ProcessA(), ObtainB(), etc. Each successive function depends on data from the previous function. The "Obtain" functions all require data from the authorization server. How do I connect all these functions into a single alias or function call so they can process the data in sequence by typing just one command ( such as /Main() )?
Australia Forum Administrator #3

function ObtainK ()
 Send "K"
 KLine, wildcards = wait.regexp ("^(.*?)$", 10)
 ProcessK()
 ObtainA()
 ProcessA()
 ObtainB()

end --ObtainK()



Inside the coroutine (ObtainK) things will pause.
USA #4
Here is what I ended up with...


require "bit"
require "var"
require "wait"
require "utils"
require "tprint"

function Sub ()


  Send ("K")
  KReply, wildcards = wait.regexp ("^(.*?)$")
  Note (KReply)


  HashPassKey = ""
  PL = #Psswd --length of Psswd

  for  i = 1, PL  do --iterate through each character of Psswd

    PPart = string.sub (Psswd, i, i) --iTH character of Psswd
    PP = string.byte (PPart) - 32 --ASCII value of PPart minus 32

    KPart = string.sub (KReply, i, i) --iTH character of KReply
    KK = string.byte (KPart) --ASCII value of KPart

    HPK = bit.xor (PP,KK) + 32 --bitwise exclusive-or of PP and KK, plus 32
    HashPassKey = HashPassKey .. string.char (HPK) --adds iTH character to end of HashPassKey

  end --for  i = 1, PL

  Note (HashPassKey)


  ALine = "A\t" .. Username .. "\t" .. HashPassKey --Simu username and KLine/pass mungle
  Send (ALine)
  AReply, wildcards = wait.regexp ("^A(.*?)$")
  Note (AReply)

  
  GLine = "G\t" .. Gamecode  --tells Simu what game you want to play
  Send (GLine)
  GReply, wildcards = wait.regexp ("^G(.*?)$") --confirms game, account type and URLs
  Note (GReply)


  Send ("C") --set up a list of characters to choose from
  CReply, wildcards = wait.regexp ("^C(.*?)$") --count and list of characters on the account
  Note (CReply)

  CParts = {} --initializes table
  CharCode = {}
  CharName = {}
  CharList = {}

  CReply1Space = string.gsub (CReply, "%s+", " ") --changes multiple spaces between words to 1 space
    -- NOTE: MUSHclient changes tab characters to multiple spaces
  CParts = utils.split (CReply1Space, " ") --creates table of "words" in CReply1Space
  tprint (CParts)

  CharCount = CParts [2] --2nd item in table is the number of characters on the account 

  --NOTE:  Beginning with the 6th item, CParts lists CharacterCode, CharFirstName, CharLastName, ...
  for  i = 1, CharCount  do

    CharCode  = CParts [ 3 + ( i * 3 ) ] --iTH CharCode, item 6, 9, 12, ...
    CharName  = CParts [ 4 + ( i * 3 ) ] .. " " .. CParts [ 5 + ( i * 3 ) ]
      --iTH FirstName_space_LastName, items 7 & 8, 10 & 11, 13 & 14, ...
    CharList  = CharCode  .. "   " .. CharName 
      --this table lists the CharCodes and CharNames together in a list box

  end  --for  i = 1, CharCount

  for  j = 1, CharCount  do
    Note (j, " ", CharCode [j], " ", CharName [j])
  end --for  j = 1, CharCount

  CharChoice = utils.listbox ("Select the character you want to play.", "Choose Character:", CharName, 1)


  LLine = "L\t" .. CharCode [CharChoice] .. "\tPLAY" --tells server which character to play
  Note (LLine)
  Send (LLine)

  LReply, wildcards = wait.regexp ("^L(.*?)$") --login info
  Note (LReply)

  LParts = {} --initializes table
  LReply1Space = string.gsub (LReply, "%s+", " ") --changes multiple spaces between words to 1 space, not needed)
    --NOTE: MUSHclient changes tab characters to multiple spaces
  LParts = utils.split (LReply1Space, " ") --creates table of sections of LReply1Space

  LoginStatus = string.match (LReply, "^L%s-(%S+)%s-")
  UpPort = string.match (LReply, "UPPORT%=(%d+)%s-")

  ClientShort = string.match (LReply, "GAME%=(%S+)%s-")
  ClientLong = string.match (LReply, "FULLGAMENAME%=(.-)%s-GAMEFILE%=")
  ClientFile = string.match (LReply, "GAMEFILE%=(%S+)%s-")

  Note()

  GameHost = string.match (LReply, "GAMEHOST=(%S+)%s-")
  Note (GameHost)
  
  GamePort = string.match (LReply, "GAMEPORT=(%d+)%s-")
  Note (GamePort)

  Key = string.match (LReply, "KEY%=(.+)$")
  Note (Key)
  SetClipboard (Key)
  
  

  Note ()
  Note ("The key above has been copied to the Windows clipboard.")
  Note ("To play, create a world with the host name")
  Note (" and port number noted above,")
  Note ("connect to the world,")
  Note ("paste the key into the command line, press [ENTER],")
  Note ("and press [ENTER] again.")


end --Sub ()
  
  
function Main ()

  require "wait"

  Username = utils.inputbox ("Username?", "Input Username")
  Psswd = utils.inputbox ("Password?", "Input Password")
  Gamecode = utils.inputbox ("Gamecode?", "Input Gamecode")

  wait.make (Sub)
    
  end --Main ()

	


Given that I put the processing sequence into one long subfunction, do I really need to use wait.lua at all?
Amended on Sun 27 Jan 2013 08:36 AM by Nick Gammon
Australia Forum Administrator #5
Stuff like this:


  LReply, wildcards = wait.regexp ("^L(.*?)$") --login info


requires the wait.lua module.

You can't pause the client without the assistance of coroutines.