Vote for Islands of Myth on Top Mud Sites
firstprevious1nextlast
channel capturing to an external windowThu Sep 8 23:06:52 2011 MST
Vor
admin
offline
avatar
ok. this takes a few steps so bear with me.



first things first, edit your .tfrc file. you want to have these two lines placed in there:



/addworld chans

/load <your_tf_dir>/testchans.tf



now you want to go to your tf dir and add a file named testchans.tf



in it, put this:



/def -p1 -mglob -wchans -hCONNECT chanshook = \

/load <your_tf_dir>/chans.tf



this little puppy will let you load the chans tf file in its own world using your tfrc file. i find this to make my life much easier. otherwise i'd have to open a tf window, run tf with no connection, and load the chans.tf file every time i wanted to use it. huge waste of my time.



next up we get to the actual mandatory stuff. first, in your tf dir, make a file called chans.tf



you'll want it to look something like this:



/def updatechans = \

/let file <your_tf_dir>/chan_capture.txt%; \

/let chanread=%; \

/let chan_read_stream $[tfopen(file, "r")]%; \

/while (tfread(chan_read_stream, chanread) != -1) \

/if (chanread !~ "") \

/eval /echo -p %chanread%; \

/endif%; \

/done%; \

/test $[tfclose(chan_read_stream)]%; \

/unset chan_read_stream%; \

/let chan_read_stream $[tfopen(file, "w")]%; \

/if (!tfwrite(chan_read_stream, "")) \

/return -1%; \

/endif%; \

/test $[tfclose(chan_read_stream)]%; \

/unset chan_read_stream



/repeat -1 i /updatechans





now, first off, if you want to change that filename go right ahead, just be consistent with the change cause i use it in the next file i'll show you too.



here's what this file does.



It starts off by opening a tfio stream. Basically you can imagine that to be a long list of lines. it's opening this stream in read mode. this gives it access to read from the txt file up above. the next thing it does is go through the list of all lines of that stream, which means that it takes the first thing that it sees in the stream (which happens to be the first line of the txt file in this case), applies it to the variable chanread, and then we take the variable and look at it. now, the variables are all going to be strings, so we're going to see if the string has any length. I could use strlen here but i'm lazy and prefer the !~ "" method. don't ask. now, assuming that this variable's value is not "", we're going to echo to the tf world, which in this case is the chans world we made earlier. and we do this til there are no more lines to read.



now, tfread does not actually delete the lines from the file. the problem wiht that is that the next time this refreshes, it's going to load all the lines we've already seen and then add any new ones to the bottom. this is kind of stupid, since the lines aren't going anywhere on the chans screen. so the first thing we're going to do is close our tfio read mode stream. technically because it has reached the last line of its stream (which was the last line of the file at the second it got there), the only useful thing we CAN do with it is close it. even if more things are added to the file, they will not be added to the read stream.



so we close the stream. now we're going to unset the var that was holding the stream's int handle. and then we're immediately going to open another tfio stream, this one in write mode, and we're going to sleect that same file. now, tfio write mode streams override anything in the stream that they are writing to. so we have set the stream's handle to the same var we used before, and now we're going to use tfwrite to override the txt file with a simple "". that won't mess with the messages already in the tf window, it just basically cleans the file out. now we close the tfio stream again, and once again unset the var.



all of the above happens once every second, as you can see from the repeat line below it. i assure you that you won't even notice it.





ok, so that's over with. next up we get to the actual meat of the capturing. make the last file, capture.tf, and put this in it:



prob best to do it in sections so: first section



/def do_chan_setup = \

/let chan_file <your_tf_dir>/chan_capture.txt

/if (chan_setup) \

/return%; \

/else \

/if (chan_stream !~ "") \

/test $[tfclose(chan_stream)]%; \

/unset chan_stream%; \

/endif%; \

/set chan_stream $[tfopen(chan_file, "w")]%; \

/if (!tfwrite(chan_stream, "Channel Capture Window")) \

/eval /echo -p % Error writing to chan capture file from creation.%; \

/return -1%; \

/endif%; \

/test tfclose(chan_stream)%; \

/unset chan_stream%; \

/set chan_stream $[tfopen(chan_file, "a")]%; \

/endif%; \

/set chan_setup 1



/do_chan_setup



k, we're gonna start at the bottom of this functioin. first thing that happens after this file compiles when you load your char's settings file is that the macro do_chan_setup runs. it first sets the filename to a var, mostly cause there's no harm in doing that twice, then it checks to see if it has already run. since it hasn't, it goes on to check to see if for some reason the var chan_setup has been set to 0 (which might happen if you have some kind of bug and want to reload the channel capture streams without closing tf and reopening it). if the var has been set to zero, it closes the tfio stream for the file (not the one in your chans window, this is to the same file but a different stream), and then unsets the stream handle var.



whether or not it has to go through all that, it will definitely now open a tfio stream in write mode. and the first thing it does after that is put a pretty useless message in the file on the first line of the file. next it closes the stream, deletes the stream handle, and opens a new tfio stream in append mode. append will let you write to the file without deleting what's in it, but as far as i know you cannot start append mode unless something is in the file. it could be that i wasted my time doing the tfio write stream. experiment with that if you want.



anyway, the tfio append stream doesn't need anything done with it at this point, so now that it's functioning and we have a var with the handle, we can go on to the next part.





/def addchan = \

/let cn %{*}%; \

/let chan_capture $(/expr %{cn}_capture)%; \

/if (chan_capture) \

/eval /echo -p % You are already capturing that channel (%{cn}).%; \

/return -1%; \

/endif%; \

/eval /echo -p % You are now capturing the channel %{cn}.%; \

/set %{cn}_capture 1%; \

/if (cn =~ "tells") \

/def -mregexp -t'^(?!\\d{2}:\\d{2}:\\d{2})(.+? tell|tells (?:\\(.*\\) ).+?\\s?: .*)' %{cn}_chan_cap1 = \

/if (!tfwrite(chan_stream, %%{P1})) \

/eval /echo -p % Could not write to chan capture file from tells capture1.%%; \

/return -1%%; \

/endif%%; \

/def -mregexp -t'(\\\\s{4}.*)' %{cn}_chan_cap2 = \

/if (!tfwrite(chan_stream, %%%{P1})) \

/eval /echo -p % Could not write to chan capture file from tells capture2.%%%; \

/return -1%%%; \

/endif%%; \

/def -F -p20 -mregexp -t'^[\\\\S]+' %{cn}_chan_cap2_kill = \

/undef %{cn}_chan_cap2%%; \

/undef %{cn}_chan_cap2_kill%%; \

/return%; \

/elseif (cn =~ "says") \

/def -mregexp -t'^(?!\\d{2}:\\d{2}:\\d{2})(.+? \w+s: .*)' %{cn}_chan_cap1 = \

/if (!tfwrite(chan_stream, %%{P1})) \

/eval /echo -p % Could not write to chan capture file from says capture1.%%; \

/return -1%%; \

/endif%%; \

/def -mregexp -t'(\\\\s{4}.*)' %{cn}_chan_cap2 = \

/if (!tfwrite(chan_stream, %%%{P1})) \

/eval /echo -p % Could not write to chan capture file from says capture2.%%%; \

/return -1%%%; \

/endif%%; \

/def -F -p20 -mregexp -t'^[\\\\S]+' %{cn}_chan_cap2_kill = \

/undef %{cn}_chan_cap2%%; \

/undef %{cn}_chan_cap2_kill%%; \

/return%; \

/endif%; \

/def -mregexp -t'^(?!\\d{2}\\:\\d{2}\\:\\d{2} )(.*?[^\\w\\s]+%{cn}[^\\w\\s]+?:.*)' %{cn}_chan_cap1 = \

/eval /echo -p % In here. %%{P1}%%; \

/if (!tfwrite(chan_stream, %%{P1})) \

/eval /echo -p % Could not write to chan capture file from %{cn} capture1.%%; \

/return -1%%; \

/endif%%; \

/def -mregexp -t'(\\\\s{4}.*)' %{cn}_chan_cap2 = \

/if (!tfwrite(chan_stream, %%%{P1})) \

/eval /echo -p % Could not write to chan capture file from %{cn} capture2.%%%; \

/return -1%%%; \

/endif%%; \

/def -F -p20 -mregexp -t'^[\\\\S]+' %{cn}_chan_cap2_kill = \

/undef %{cn}_chan_cap2%%; \

/undef %{cn}_chan_cap2_kill%%; \

/return



this is kind of long. basically this is the ui for the channel capturing. with this command (used by doing /addchan channel, /addchan tells, or /addchan says), you turn on the channels or what have you that you would like to see in your external window. the first thing it does is set your argument to a variable, and the it does something that looks kind of weird.



basically, you want the variables you use for this to be specific to the thing you want to capture. however, for the sake of adding one at a time, we're going to use a local var set to the value of the specific var. in this case, that means that we use $(/expr) (and don't for a minute think i know why that works, i stumbled upon it after a week of trying to make the name of a var use another var in it, and then setting that to a 3rd var. i do it without asking for more now.). anyway, the point of that is that you can't do if (%{{var}_var2}) to test the value of your var. but test it we must, because really things would get silly if you somehow managed to add a second set of trigs or something to capture the same channel twice.



Now we get to the regexp trigs. If you want to understand exactly how the regexp does what it does, i'll tell you privately. however, the way it works is that for tells, says, or channels, it will capture anything live but not anything recorded. no channel history, etc. also, i haven't tested it, but if you have a capture set up for myth and someone on chat says 'Vor <-<myth>->', it shouldn't capture that. or at least, that was my intent. i may have forgotten to put it in.



now, for me at least, when tf wraps a line of conversation, it tends to add a fairly big indent, and you as well as i now that tf trigs do not do multiline automatically. so what i've done is added another trig that fires off of the first trig. 2 actually. the first of the two trigs is set up to add any line that starts with 4 spaces to the capture window, assuming it's a wrap of what came after the first line. the second trig triggers off of the first spot on a new line being anything but a white space. if the 2nd trigger is set off, it immediately undefines the trigger with the indent checker, and then undefines itself for good measure.



any line that is captured is sent along to the file that we have already discussed. the order is first in, first out, so it will not get all backwards or anything.





lastly there's the final function:



/def rmchan = \

/let cn %{*}%; \

/let chan_capture $(/expr %{cn}_capture)%; \

/if (!chan_capture) \

/eval /echo -p % You are not currently capturing that channel (%{cn}).%; \

/return -1%; \

/endif%; \

/undef %{cn}_chan_cap1%; \

/undef %{cn}_chan_cap2%; \

/undef %{cn}_chan_cap2_kill%; \

/unset %{cn}_capture%; \

/eval /echo -p % You are no longer capturing the channel %{cn}.



this one is very simple. you supply a channel name (or says, or tells), and it first checks to see that you're even capturing it (if you aren't it tells you off), and if you are, it undefines the main trig for that, as well as removing the indent trig and the anything but indent trig, just in case somehow they were hanging around. lastly it unsets the var that we use to track whether or not you are capturing that channel. it's a lot less messy here, so notice how i used the vars in the names of the trigs. that makes it way easier to track shit.





and there you have it!





btw, may not be obvious but you do actually have to manually open tf twice, once for your capture window and once for your char's window.
>channel capturing to an external windowMon Sep 12 15:02:44 2011 MST
Korthrun
player
offline
You really should post this to the tf mailing list :)
firstprevious1nextlast