10 Oct, 2010, KaVir wrote in the 1st comment:
Votes: 0
Yesterday I was reading a discussion that compared VT100 commands with plugins, and thought it might be fun to have a quick play with cursors - some of my players use basic clients, so they can't use plugins or scripts, and I figured it might be nice to give them energy bars as well.

So this is what I came up with:



One problem I found was that after drawing the bar and restoring the cursor position, the cursor was at the beginning of the line, meaning you'd type over your prompt (as if you'd displayed a "\r"). To get around this, when you're using the energy bar the mud always adds a newline after your prompt if there isn't one already. Not ideal, but it works.

When using my cygwin telnet client, the bar stops updating while typing something. When using TinTin++ it continues to update, but every time it does the prompt returns to the front of the line, so you're typing over your own input. Is there a solution for this other than using character mode?

I've also noticed that sometimes the bar vanishes when text scrolls up the screen, although it reappears a moment later - not a big deal, but not very nice either.

I also tried drawing the bar at the bottom of the window, using NAWS to find the window height - but I had trouble getting the cursor to move up afterwards (you'd start typing over the bar). I know other muds have done this so I'm sure it can be done, but I didn't want to spend more than an hour or two playing with it. It was really just to test the idea out, out of personal curiosity.

Experimental code here, if anyone wants it:
if ( mpThing->GetConfig() != NULL && 
mpThing->GetConfig()->Get(IConfig::eEnergyBar) )
{
// Don't send a new line to the client just because the bar updated.
mbHideNewLine = (mSocket != NULL && !mSocket->IsEmpty());

std::string BarText, PartText;
BarText = "\0337"; // Save the current cursor position.
BarText = "\033
if ( mpThing->GetConfig() != NULL &&
mpThing->GetConfig()->Get(IConfig::eEnergyBar) )
{
// Don't send a new line to the client just because the bar updated.
mbHideNewLine = (mSocket != NULL && !mSocket->IsEmpty());

std::string BarText, PartText;
BarText = "\0337"; // Save the current cursor position.
BarText = "\033[0;0r"; // Remove the bar region.
BarText = "\033[0;0H"; // Move the cursor to the top of the screen.

// Health

BarText += "\033[1;33m\033[1;41m"; // Yellow text on red bar.

int Current = mpThing->Get(att::CURRENT_HEALTH);
int Max = mpThing->Get(att::MAX_HEALTH);
PartText = "Health: ";
PartText += gw2::GetNumber(Current);
PartText += "/";
PartText += gw2::GetNumber(Max);

unsigned int Pos = gw2::SetInRange(Current*100/Max/4, 0, 25);
for ( unsigned int i = 0; i < 25; ++i )
{
if ( Pos == i )
BarText += "\033[1;47m";
BarText += i < PartText.length() ? PartText.at(i) : ' ';
}

// Mana

BarText += "\033[0m "; // Blank gap between the bars.
BarText += "\033[1;33m\033[1;44m"; // Yellow text on blue bar.

Current = mpThing->Get(att::CURRENT_MANA);
Max = mpThing->Get(att::MAX_MANA);
PartText = "Mana: ";
PartText += gw2::GetNumber(Current);
PartText += "/";
PartText += gw2::GetNumber(Max);

Pos = gw2::SetInRange(Current*100/Max/4, 0, 25);
for ( unsigned int i = 0; i < 25; ++i )
{
if ( Pos == i )
BarText += "\033[1;47m";
BarText += i < PartText.length() ? PartText.at(i) : ' ';
}

// Actions

BarText += "\033[0m "; // Blank gap between the bars.
BarText += "\033[1;33m\033[1;42m"; // Yellow text on green bar.

Current = mpThing->Get(att::CURRENT_ACTIONS);
Max = mpThing->Get(att::MAX_ACTIONS);
PartText = "Actions: ";
PartText += gw2::GetNumber(Current);
PartText += "/";
PartText += gw2::GetNumber(Max);

Pos = gw2::SetInRange(Current*100/Max/4, 0, 25);
for ( unsigned int i = 0; i < 25; ++i )
{
if ( Pos == i )
BarText += "\033[1;47m";
BarText += i < PartText.length() ? PartText.at(i) : ' ';
}
BarText += "\033[0m"; // Avoid colour bleeding.
BarText += "\033[2;0r"; // Fix the bar region.
BarText += "\0338"; // Restore the cursor position.

// Display the bar immediately, and flush the buffer.
mSocket->Write(BarText);
mSocket->Flush();
}[/code]
10 Oct, 2010, quixadhal wrote in the 2nd comment:
Votes: 0
One suggestion would be to restrict the scrolling region to lines 1;23. That would give you your status bar at the top (COLS-1 max), and a prompt bar at the bottom (COLS-1).

Unfortunately, my real vt420 terminal is broken so I can't properly test such things. Quite a few terminal emulators don't play nice with ALL vt100 codes, even though they claim to. As I recall, an actual vt100/vt102 has a scroll bug when the cursor is in the bottom right of the screen when input arrives. Many emulators silently fix that, which means code which knows about the actual bug now breaks by overcorrecting. *chuckle*
10 Oct, 2010, Scandum wrote in the 3rd comment:
Votes: 0
TinTin++ doesn't handle \eTinTin++ doesn't handle \e[0;0r properly as of yet, and neither do several terminal emulators. The universal way to reset the scrolling region is by using \e[r, and when setting a scrolling region you ought to explicitly set the upper and lower limit, as using \e[2;0r isn't going to work with all terminal emulators, mainly because the behavior isn't explicitly defined. Windows telnet supports NAWS however, and after detecting someone is using windows telnet you can enable character mode to restore echo.

Another thing that's odd is that you reset the scrolling region when drawing, typically you set the scrolling region once and leave it be until vt100 mode is disabled.

\e[0;0H is ambiguous as well, if you want to move the cursor to the top left position, also known as the home position, you ought to use \e[1;1H. I'm not too sure about universal terminal support in this regard, but \e[H is the equivalent of of \e[0;0H and an option if you want to save bandwidth. Possibly all major terminals support it.

To create a promptbar above the input line you'd do the following, assuming a 24 row screen:

1) To set the scrolling region you'd use: \e[1;22r keep in mind you need to use \e[2;22r for windows telnet due to a bug in its VT100 handling.

2) When updating the status bar you save the cursor, jump to the status bar, and print, so that'd be: \e7\e[23;1H<text>\e8

3) When sending normal text to the user you'd save the cursor, jump to the bottom of the scrolling region, and print away, so that'd be: \e7\e[22;1H<text>\e8 adding a \n at the end is required here to push the text to row 21, otherwise the text stays on row 22 and gets overwritten on the next write.

4) For compression it's easiest to keep a local copy of the status bar in memory with the character and color for each position stored, with a function that takes two local copies and sends the minimum required data to update the player's vt bar, then overwrites the old copy with the new copy.

Color handling can be tricky when saving and restoring the cursor, I forgot the specifics for those.
10 Oct, 2010, KaVir wrote in the 4th comment:
Votes: 0
And of course this:
BarText = "\0337"; // Save the current cursor position.
BarText = "\033
BarText = "\0337"; // Save the current cursor position.
BarText = "\033[0;0r"; // Remove the bar region.
BarText = "\033[0;0H"; // Move the cursor to the top of the screen.[/code]Should have been:
[code]
BarText = "\0337"; // Save the current cursor position.
BarText += "\033[0;0r"; // Remove the bar region.
BarText += "\033[0;0H"; // Move the cursor to the top of the screen.[/code]I broke it up to make it easier to follow, and messed it up by forgetting to change "+" to "+=" - Scandum spotted it when debugging it with tt++ (thanks!). However following his post I've changed it to the following:
[code]
BarText = "\0337"; // Save the current cursor position.
BarText += "\033[1;1H"; // Move the cursor to the top of the screen.[/code]And I've removed the following from the end as well:
[code]
BarText += "\033[2;0r"; // Fix the bar region.[/code]
I'll fiddle with it a bit more, get it to only update if it's actually changed (like I do with MSDP), but as I said before I don't want to invest too much time into it - I've too many projects already :P
11 Oct, 2010, balakoth wrote in the 5th comment:
Votes: 0
Kavir, I am doing alot of VT100 stuff with my small tinkering project at the moment.

(You had responded to my post on mudconnector) Drawing and interface and having certain parts be redrawn, using scrolling regions. So far WinTinTin.net, cmud and telnet are acting as expected and havent had to many issues with anything scrolling off the screen (For me it was just finding the right points at which to save and restore the cursor)

but I do have a question for you, that pertains to both of us. Ive noticed on all of these telnet applications, that once you set the upper scrolling region, and I allow text to scroll below the static field that there is no way for the user to scroll back up through their window buffer to see any past buffer writes that have occured. (For instance if a big help file was to scroll, they would simply miss it without doing some kind of page pause)


Maybe you can key in on what youve done to resolve that issue, or maybe show me what Im doing wrong if this is not the result that should be happening.
11 Oct, 2010, Scandum wrote in the 6th comment:
Votes: 0
TinTin++/WinTin++ supports split screen scrollback using the default page up/page down macros. I don't know of any workarounds, or terminal emulators that support it.

Good workarounds that I've seen are page pausing and a general purpose grep command.
11 Oct, 2010, KaVir wrote in the 7th comment:
Votes: 0
balakoth said:
Kavir, I am doing alot of VT100 stuff with my small tinkering project at the moment.

Then you probably know a lot more about it than me! I literally spent only an hour or two having a tinker, after doing a quick google for the cursor codes, just to see what it would be like. With Scandum's help I've now got it fairly usable (after the next reboot at least), and I may add it to the stats page on my website to see how many people use it, but I'm not sure if I'll bother taking it any further. I really do have far too many projects already, and I don't want to get sidetracked yet again.

I didn't test the scrollback, but that does sound like a potential problem. I do offer commands for viewing the history of each channel though, so at least players won't miss out on tells or chats.
12 Oct, 2010, Rudha wrote in the 8th comment:
Votes: 0
Hmm. That actually might not be a half-bad approach for something I had in mind. Out of curiosity: I never much played with the VT100/etc stuff, is there a decent emulation support in MUD clients?

Maya/Rudha
12 Oct, 2010, David Haley wrote in the 9th comment:
Votes: 0
Rudha said:
Out of curiosity: I never much played with the VT100/etc stuff, is there a decent emulation support in MUD clients?

Yes and no. MUSHclient for instance doesn't support it much at all (Nick has some reasons for explicitly choosing to not support it, like how it makes triggers and logging be very difficult or even almost nonsensical). I think that Zugg's clients and tt++ support it to some extent; however as Scandum noted above support is partial in tt++. He would be able to answer much better what the exact caveats are.

In general I think that it's a poor solution for what people are trying to do here, dated back to decades ago when we only had dumb terminals. Nowadays I think it makes far more sense to send the data using some kind of out-of-band method and having the client render it in some appropriate fashion (like what people have been doing with MUSHclient). All of that said, of course, the vt100 method "just works" without client plugins, assuming client support in the first place of course.
12 Oct, 2010, Scandum wrote in the 10th comment:
Votes: 0
tt++ relies on the terminal to display vt100, but if someone uses xterm - emulation is typically perfect. tt++ has an internal vt100 emulator to keep track of the vt state, which most console clients don't have, and subsequently most of them (like tinyfugue) can't properly display vt100 interfaces.

I added support for \ett++ relies on the terminal to display vt100, but if someone uses xterm - emulation is typically perfect. tt++ has an internal vt100 emulator to keep track of the vt state, which most console clients don't have, and subsequently most of them (like tinyfugue) can't properly display vt100 interfaces.

I added support for \e[2;0r in the next tt++ release, not sure if CMUD supports it, but it looks like PuTTY and the Windows console do. Looks like rxvt does support \e[2r, so that might be preferable to use.

Clients I know of to support vt100 are: CMUD, DF Client, Soiled, SoTerm, TinTin++/WinTin++, Wintin.NET, and zMUD.
13 Oct, 2010, Scandum wrote in the 11th comment:
Votes: 0
TF breaks its inherent VT100 capabilities somewhere along the way, and so do most other console clients that I've tested. All things considered you got at least 50% of the market with those who use zmud, cmud, tt++, wintin.net, and telnet clients, and that number is only to increase if more MUDs implement even the most basic vt interfaces, which isn't all that hard.

With MSDP you open up the option for players to create their own interfaces with very little effort, assuming you don't bother creating your own plugin like KaVir did, which I assume to have taken up quite a bit of time. GMCP remains an option as well.
13 Oct, 2010, JohnnyStarr wrote in the 12th comment:
Votes: 0
VT100 Energy Bar, Mmmmmmmmmmmmmmmmmmmmmmmmmm

YUMMY!
17 Oct, 2010, David Haley wrote in the 13th comment:
Votes: 0
I asked you a technical question about a technical problem, Scandum. Why don't you answer it? Perhaps you're not interested in the topic, in which case I apologize. Just in case you missed it in the brouhaha, the question was what screen readers would do with the kind of features you'd implement with a VT100 interface.
17 Oct, 2010, Scandum wrote in the 14th comment:
Votes: 0
David Haley said:
Just in case you missed it in the brouhaha, the question was what screen readers would do with the kind of features you'd implement with a VT100 interface.

Any sane VT100 interface defines a scrolling region. Any sane VT100 client would respond as following:

1) When using scrollback only the scrolling region should be used for displaying the scrollback buffer.

2) Only text printed inside the scrolling region should be saved to the scrollback buffer. Any sane server will print at the bottom of the scrolling region, there's no need to worry about insane servers, a server can drop your link at any time, it's all powerful, if it wants to be insane you either put up with it or go to a saner server.

3) All text printed outside the scrolling region should be treated as out of band data, as such screen readers should ignore it, not to mention that any sane server will provide an option to disable vt100, there's no need to worry about insane servers.

4) Text triggers shouldn't work on text printed outside the scrolling region, as it's out of band data, for clarification: It's data, not text. A client could provide an event or triggering system for out of band VT100 data, tintin++ doesn't as you can do your own VT100 if you don't like the server's VT100.

5) Out of band VT100 send by peers (Like with MudMaster Chat connections) is removed, the relationship with a peer is different from a server.

6) When clearing the screen you clear the visible screen, you don't erase the entire scrollback buffer, it's that simple.

7) For all other matters apply common sense.
17 Oct, 2010, quixadhal wrote in the 15th comment:
Votes: 0
Scandum said:
Any sane VT100 interface defines a scrolling region. Any sane VT100 client would respond as following:

3) All text printed outside the scrolling region should be treated as out of band data, as such screen readers should ignore it, not to mention that any sane server will provide an option to disable vt100, there's no need to worry about insane servers.

4) Text triggers shouldn't work on text printed outside the scrolling region, as it's out of band data, for clarification: It's data, not text. A client could provide an event or triggering system for out of band VT100 data, tintin++ doesn't as you can do your own VT100 if you don't like the server's VT100.

5) Out of band VT100 send by peers (Like with MudMaster Chat connections) is removed, the relationship with a peer is different from a server.


Wait a minute here. A vt100 "client", like perhaps an actual vt100 terminal? How is an arbitrary vt100 client (which is NOT designed to work with your MUD, but is designed to be as much like a vt100 as possible), supposed to know which regions are valid data to act upon, and which are not?

Remember, the vt100 spec doesn't say anything about content. It's a set of control codes that describe how to manipulate and construct the display… nothing more. If you start saying "It should ignore this" and "It should trigger on that", now you're talking a custom client. Either YOU (the server admin) have to provide this, or you have to expect the player to build it as a plug-in for whatever terminal software they're using.

In either case, you have moved a step beyond vt100 support and now limited your playerbase to those with vt100 emulation *AND* the ability to filter and react to your server's constructed output.

So, in the case of the screen reader David was asking about, the reader itself would have to know the vt100 dialect so it could recognize which part of the "display" is the scrolling region and only attempt to read from it?
18 Oct, 2010, David Haley wrote in the 16th comment:
Votes: 0
Rudha said:
it's caused his valid points, to be lost, on myself and others, because we end up emotionally responding

Well, that certainly explains a lot.

When I find myself in an emotional state such that I am no longer being rational and am therefore missing valid points, I find it helps to step away for a while before replying to something and making matters worse.

Scandum said:
3) All text printed outside the scrolling region should be treated as out of band data, as such screen readers should ignore it,

This is the part I was interested in. Quix's response to your post is interesting too and I would have asked the same, but let me stick with this for now.

OK, so the whole reason we have for discussing things like VT100 in this thread is to display extra information to the player. Presumably, this extra information makes certain game elements more readily available to the player. This information might be things like health status bars, or tactical maps.

But what you're saying now is that whatever information you might have will be inaccessible to the blind players after all. So really, in the end of the day, they're not using the VT100 features at all.

This is exactly why some people have been confused about why VT100 is supposed to be a solution here. These extra features will not be available to blind players. If a game makes use of these extra features in an important way – in other words, if these extra features are important to playing the game effectively – then it stands to reason that blind players will not be able to play competitively.

Now, I mentioned earlier in the thread that maybe this is ok, on the assumption that for some people, playing non-competitively is better than not playing at all. That might in fact be true. But the more you push features away from that main text scrolling window, the less clear it is that they'll be able to play at all, really.

For example, you might decide that since you have a really spiffy map in a corner of the screen, you don't really need to display position updates in the main channel because it's redundant, and in fact less effective in the first place than a visual representation of a player's surroundings. You might also decide to not print out prompts with health information because, again, it would be redundant. When this happens, blind players are really going to be in trouble because the main channel won't have the information for the screen reader at all.

You might argue that you simply shouldn't remove the information. OK, but this is punishing players who can see (or otherwise use) the extra channels. It means that your output is determined by what blind people can see. I think it's pretty easy to see that this leads to unpleasant decisions, and simply isn't practical if your goal is to make something accessible to the larger group of people.

You might also argue that, ok, it's a little silly to force people to read things they can see elsewhere. So you'll have two ports, one that makes use of these new extra channels somehow (whether or not it uses VT100 is more or less irrelevant, at present) and one specially designed for screen readers.

The thing is, you've now created a fair amount of work for yourself. This brings us back to earlier questions regarding how much work is worth expending to cater to a relatively small player segment.

In the end of the day, that decision is up to an individual game's developers/designers. It certainly is not stupid to decide to cut the effort and focus on one aspect, at the expense of some players. It is also not stupid to try to cater to both groups, if that is really what you want to do and the extra development time is reasonable. (If you were working from a business perspective, though, I think it would be harder to justify it.)

Nevertheless, it becomes pretty clear that using VT100 (or whatever other protocol, really) is not a silver bullet that solves all the problems here. Many remain that force complex trade-offs.
18 Oct, 2010, Rudha wrote in the 17th comment:
Votes: 0
quixadhal said:
In either case, you have moved a step beyond vt100 support and now limited your playerbase to those with vt100 emulation *AND* the ability to filter and react to your server's constructed output.


Its trivial to determine if the client has VT100 support if the client supports the TERMTYPE telopt. If they don't, its also pretty trivial to do something like CONFIG VT100 [ON/OFF]

I find it a frustrating recurring arguement that suddenly by supporting something, you alienate everyone that doesn't want or support it. This is not the case, if you have designed it well.

Maya/Rudha
18 Oct, 2010, Scandum wrote in the 18th comment:
Votes: 0
Blind people would obviously disable vt100 as it'd be of little use to them and is likely to confuse their screen reader.

If you're looking at the basics you can do a traditional split screen, giving the players their prompt on the split bar (creating more screen space as there aren't repeat prompts being spawned) and you also create an input area, which avoids input being mangled whenever new text arrives. If this is all you're doing there is no significant tactical advantage, and the sighted users have an easier time typing. It'd be 2 hours work for a competent mud dev who already has NAWS in place.

Further improvements would be an option to create a prompt for the top row, as you need a top row for windows telnet to properly split the screen, and you could parse the prompt to see the number of newlines, and create a 2 row bar above the input bar to display a two line prompt. Probably another 2 hours to get it all straightened out.

Blind people wouldn't benefit, possibly they could use MSDP to their advantage.
18 Oct, 2010, David Haley wrote in the 19th comment:
Votes: 0
Scandum said:
If this is all you're doing there is no significant tactical advantage

I agree with you that if all you're doing is a fairly simple split input/output section, then there isn't a huge advantage. But I thought that the whole point of all of this was to do far more than splitting input and output; for instance, displaying maps and the like.

Scandum said:
Blind people wouldn't benefit, possibly they could use MSDP to their advantage.

It would be interesting to see how people could combine screen readers and out-of-band data for things like maps and other graphical elements.
18 Oct, 2010, balakoth wrote in the 20th comment:
Votes: 0
I personally love the vt100 functionality.. unfortunately it causes many issues for even normal, non handicapped players.

Without customized client support, you are forced to start using other protocols also limited to certain clients (MXP For example) to even get your information to the user in a readable format.

I love what I'm doing, but I also hate the fact I would have to force the user to use a mouse to really gain control of the information they need.

(My problem is with using a top scrolling region, you pretty much limit the ability to even scroll back to see past data that has passed on the bottom scrolling region)

Perhaps someone could help develop a better screen reader to help with vt100 support (The cursor is still redrawing certain areas, does the screen reader only scan the input that is incoming and not the change in the entire output window?)


This is a feeble attempt at trying to get the discussion back on course, after a 5 page derail into an argument that wasnt even a point in Kavirs original post.
0.0/36