This is all done by sending keystrokes into the There window, as if you were typing conversation and emote directives.
There are two different ways to do this. The intended one (by the There client programmers) is through the localhost:9999 interface. If you query a URL like this,
http://localhost:9999/ScriptHook/Invoke?Path= %2Facc%2FaddChatText&Args=text%3Dsomeconversationtext(but without the line break), then the string "someconversationtext" appears in your avatar's chat bubble.
I don't like this method. It is awkward for sending special characters. I never figured out how to send a carriage return, but a reader has communicated that %0A does the trick, notwithstanding that it is actually the HTTP code for linefeed!
I think it's easier and more versatile to just send keystrokes directly to the There window using Win32::GuiTest, especially since this package provides nice shortcuts for special characters, pauses, etc. Quoting from the documentation:
There are several characters that have special meaning. This allows sending control codes and modifiers:
~ means ENTER
+ means SHIFT
^ means CTRL
% means ALT
The parens allow character grouping. You may group several characters, so that a specific keyboard modifier applies to all of them. E.g. SendKeys("ABC") is equivalent to SendKeys("+(abc)") The curly braces are used to quote special characters (SendKeys("{+}{{}") sends a '+' and a '{'). You can also use them to specify certain named actions: Name Action
{BACKSPACE} Backspace
{BS} Backspace
{BKSP} Backspace
{BREAK} Break
{CAPS} Caps Lock
{DELETE} Delete
{DOWN} Down arrow
{END} End
{ENTER} Enter (same as ~)
{ESCAPE} Escape
{HELP} Help key
{HOME} Home
{INSERT} Insert
{LEFT} Left arrow
{NUMLOCK} Num lock
{PGDN} Page down
{PGUP} Page up
{PRTSCR} Print screen
{RIGHT} Right arrow
{SCROLL} Scroll lock
{TAB} Tab
{UP} Up arrow
{PAUSE} Pause
{F1} Function Key 1
... ...
{F24} Function Key 24
{SPC} Spacebar
{SPACE} Spacebar
{SPACEBAR} Spacebar
{LWI} Left Windows Key
{RWI} Right Windows Key
{APP} Open Context Menu Key
All these named actions take an optional integer argument, like in {RIGHT 5}. For all of them, except PAUSE, the argument means a repeat count. For PAUSE it means the number of milliseconds SendKeys should pause before proceding.
|
Win32::GuiTest::SetForegroundWindow(&GetThereWindow());
Win32::GuiTest::SendKeys("Hello!~I'm your friendly avatar!~");
Win32::GuiTest::SendKeys("\'heyhey\'~");
Win32::GuiTest::SendKeys("{PAUSE 6000}");
Win32::GuiTest::SendKeys("~~~");
The reason that I haven't bothered to encapsulate all the
Win32::GuiTest::SendKeys stuff is that one wouldn't normally
be very interested in sending fixed text from the Perl script itself.
Instead, you might want a simple driver to read a longer set of
commands from a file and send them to the avatar. Here's an
example of such a driver:
@cmds = ();
while ($arg = shift) { # read file name(s) from the command line
print "Reading command file <$arg>\n";
open (IN, "<$arg");
@newcmds = <IN>;
close(IN);
push(@cmds,@newcmds);
}
Win32::GuiTest::SetForegroundWindow(&GetThereWindow());
while ($_ = shift(@cmds)) {
print "$_";
chomp;
if (m/^QUIT$/i) {exit 0;}
elsif (m/^PAUSE ([0-9]+)/i) {Win32::GuiTest::SendKeys("{PAUSE $1}");}
elsif (m/^\@([A-Z0-9_.-]+)/i) {
if (open(IN,"<$1")) {
print "Reading command file <$1>\n";
@newcmds = <IN>;
close(IN);
unshift(@cmds,@newcmds);
}
else {print "Couldn\'t find file $1 !\n";}
}
else {
Win32::GuiTest::SendKeys("$_",50);
Win32::GuiTest::SendKeys("{PAUSE 200}");
}
}
The above example implements what amounts to a simple scripting
language. It allows a script file to contain
the names of other script files (prefixed by @) whose contents
are inserted at the place the new file name is encountered,
provides a slightly simplified syntax for inserting pauses,
and has a QUIT command.Here are the contents of a file that is read and executed by the above code. (It happens to be one of BarkerGirl's spiels, advertising some event in There.) Note the use of carriage returns ("~"), pauses, and dance moves, intermixed with chat. The string of carriage returns at the beginning is to clear away any pre-existing chat balloons.
~~~~~~ PAUSE 2000 'bodywave'~ PAUSE 3000 'handstand'~ PAUSE 4000 'bodywave'~ PAUSE 8000 'bow'~ Hello, my friend!~ PAUSE 2000 'grin'~ PAUSE 2000 I want to tell you about a really fun event~ that's going on right now. 'idea'~ PAUSE 4000 It's the Spades Tournament at Scrutiny.~ 'grin'~ PAUSE 1000 Look in my profile and you can teleport there~ 'tada'~ INSTANTLY! QUITHere's one of BarkerGirl's pure dance numbers:
'bluesteel'~ PAUSE 4000 'backpose'~ PAUSE 4000 'bodywave'~ PAUSE 4000 'handstand'~ PAUSE 4000 'heyhey'~ PAUSE 4000 'nightfever'~ PAUSE 4000 'jig'~ PAUSE 4000 'bodywave'~ PAUSE 4000 'irishdance'~ PAUSE 4000 'twist'~ PAUSE 4000 'toehop'~ PAUSE 4000 'yessir'~ PAUSE 4000 'nightfever'~ PAUSE 4000 'blowkiss'~ PAUSE 4000 'hearts'~ PAUSE 4000 'bow'~ PAUSE 4000 'tada'~ QUITThis isn't really very different from a keyboard macro program, except that you can embed this kind of behavior into a bigger script that also has behaviors discussed in earlier and later parts of this toolkit.
Next: Part 4