21 May, 2010, JohnnyStarr wrote in the 21st comment:
Votes: 0
Thanks for the link Kaz.
It's a shame there isn't more chatter about this kind of thing, any examples would really help.
21 May, 2010, Scandum wrote in the 22nd comment:
Votes: 0
JohnnyStarr said:
I would imagine that you could designate coordinates, send the entire screen and parse it to retrieve values?
Is that the wrong way to do it? What I really want is to learn enough to create sort of a GUI that could lead to
a sophisticated menu driven OLC. If you don't have time to spell it out, could you please refer me to some resources?

VT100 wise you got pretty much all you need with the four escape sequences I gave, there are a lot of additional codes that do pretty much the same thing in different ways, which is part of the reason mud client developers have a hard time implementing VT100 as there are a thousand ways to do the same thing. I guess another useful code is \e
VT100 wise you got pretty much all you need with the four escape sequences I gave, there are a lot of additional codes that do pretty much the same thing in different ways, which is part of the reason mud client developers have a hard time implementing VT100 as there are a thousand ways to do the same thing. I guess another useful code is \e[2J which erases the entire display.

What I would do if I was to create a VT interface from scratch is to allocate a 2 dimensional array of characters which contains a plaintext (no color) duplicate of the user's screen. Next you add a second 2d array of characters of the same size holding a value between 0 and 255 that represents the xterm 256 foreground color value, and if needed another one with the background color. Assuming an average display of 50 rows and 80 columns that's 8000 to 12000 bytes total per player. You can use the NAWS telnet option to find out the row and columns size of the player's terminal emulator.

Whenever the user does something you allocate 2 or 3 temporary display arrays, create the entire VT display, next compare each byte with the player's display arrays (color array first), and only send the parts that differ. When all is send you copy the temporary display arrays to the player's display arrays.

Using this approach you save quite a bit of bandwidth.

Besides NAWS you'll also want to use the TTYPE telnet option to find out a client's terminal type to find out if it's VT capable, typically zmud, cmud, and tintin++ support VT100, as well as xterm, rxvt, and other terminal emulators - though it's probably preferable to have a player type 'vt on' or 'vt off' to toggle the interface.

The most interesting usage of vt100 that I can think of would be an editor, possibly something resembling pico - pretty much all OLC engines lack in this department using primitive line editors. Like Kaz pointed out you can add xterm mouse support, though if you want drop down menus it might be worth the trouble to learn how to use a curses library.

I wrote an xterm 256 color snippet (public domain) a while ago that might be of use. http://www.mudbytes.net/file-2596
21 May, 2010, JohnnyStarr wrote in the 23rd comment:
Votes: 0
sandum said:
Whenever the user does something you allocate 2 or 3 temporary display arrays, create the entire VT display, next compare each byte with the player's display arrays (color array first), and only send the parts that differ. When all is send you copy the temporary display arrays to the player's display arrays.


This seems a lot simpler than telnet's Data Entry Terminal option. How exactly to transmit the data to the server though? I understand the usage
of the arrays, but what ESC sequence do I need to use here?
21 May, 2010, JohnnyStarr wrote in the 24th comment:
Votes: 0
Just to add to the last post:

Since you can assign a TAB to different coordinates and jump to and fro, is there also a way to make the client send
data on certain parts of the screen?

Ideally this is what I want:
+——————–+
ROW 1 |username: _________ |
ROW 2 |password: _________ |
+——————–+
1234567890123456789 <- COL 11-19 will be our cords for input
^10

– Now all we have to do is request the specific data

get \e
+——————–+
ROW 1 |username: _________ |
ROW 2 |password: _________ |
+——————–+
1234567890123456789 <- COL 11-19 will be our cords for input
^10

– Now all we have to do is request the specific data

get \e[1;11-19 – username
get \e[2;11-19 – password
[/code]

Now, of course "get" isn't a real command, but it seems like this should be available in some way.
21 May, 2010, quixadhal wrote in the 25th comment:
Votes: 0
What Scandum is describing is what the curses library actually does, although it takes it a few steps further. Curses keeps a map of your screen as several layers, one holds the character for each location, another holds the attributes (color, bold, etc). You change the display via an API with commands like mwprintf(row, col, "%s", stuff), and then eventually call refresh(). That applies your changes to a copy of the display, does a "diff", constructs the appropriate set of movement/terminal codes and pushes them to the user's terminal.

Advantage: curses works for more than just vt100, it works for anything the host has a termcap entry for. It automatically minimizes screen updates for you. It is what most rogue-like games (nethack, etc) already use.

Disadvantage: It's not easy to properly allocate a pty and bind stdin/stdout/stderr to a network socket to use it for multiplayer games. Obviously not impossible, but examples are few and far between. The curses library has some known global-state issues that make it difficult to use in a multiplayer game in this manner. The usual solution for that is to either require a custom client (which the MUD community can't seem to accept), or to fork()/exec() each connection so it has a local curses state.
21 May, 2010, JohnnyStarr wrote in the 26th comment:
Votes: 0
Quix, you know, after reviewing curses, it really seems like the solution.
As much as I would like to have multi player connections, it's not the priority right now.
So thanks.

Does curses provide a listening port for telnet access then?
21 May, 2010, quixadhal wrote in the 27th comment:
Votes: 0
I wish someone would make a netcurses package, but no. If you want to use curses over a socket, you have to allocate a pseudo-terminal and bind stdin/stdout/stderr (which is what curses uses) to it. Maybe I'll look around for a solution again… I have a couple of old curses games that I'd love to add network support to, but that's the main show-stopper.

If all else fails, Runter can surely whip us up a ruby server to do this (basically, write telnetd in ruby). :)
21 May, 2010, Runter wrote in the 28th comment:
Votes: 0
21 May, 2010, quixadhal wrote in the 29th comment:
Votes: 0
That maps curses to ruby, but you still have the legwork of binding it to sockets. Still, that's half the battle! :)

One should probably also implement a TELNET state machine, since you will want to get the NAWS and TTYPE informaton to be able to properly setup a psudo-tty for curses to manage.
22 May, 2010, JohnnyStarr wrote in the 30th comment:
Votes: 0
I was wondering, is there a way to disable the return key from moving the cursor?

I have figured out how to do everything I want but that. See, I'm making a form with tabs
and everything I need. At the bottom of the Form, you have a panel of control key options:

[ N ]ew ave [ D ]elete.

But if someone were to hit enter by mistake, it would make the screen scroll. Or if on some forms
I wanted enter to be the command button, the cursor location would be the factor of which action
to take.

Thanks!
22 May, 2010, Tyche wrote in the 31st comment:
Votes: 0
JohnnyStarr said:
:) this is for an alternate project in Ruby crat.


There's a protocol stack in TeensyMud that handles vt100.
There's also a small markup language that translates the client vt100 codes input to markup, and the server side markup to vt100 commands.
The curses library, and any libraries based on it, maintain global states making it unsuitable for certain multi-user applications, like mud servers that handle multiple-users in the same process. It works with telnet daemon because processes are spawned for each user.
22 May, 2010, quixadhal wrote in the 32nd comment:
Votes: 0
Tyche is correct about curses, however one could work around that if you were willing to fork on new connections. You'd have to call init_curses() after the new connection process started, and you'd also have to use some mechanism to talk to the main mud server process (shared memory probably). I don't think a thread would be enough on some OS's, because the curses library may not be copied.
22 May, 2010, Scandum wrote in the 33rd comment:
Votes: 0
JohnnyStarr said:
sandum said:
Whenever the user does something you allocate 2 or 3 temporary display arrays, create the entire VT display, next compare each byte with the player's display arrays (color array first), and only send the parts that differ. When all is send you copy the temporary display arrays to the player's display arrays.


This seems a lot simpler than telnet's Data Entry Terminal option. How exactly to transmit the data to the server though? I understand the usage
of the arrays, but what ESC sequence do I need to use here?

You'd use \e
You'd use \e[<y>;<x>H to jump to where you want to alter the text and start inserting color codes and characters where needed. Whenever there's a section that's identical you jump past it with another \e[H call.

[quote=[url=/topic-2802-46144#p46144]JohnnyStarr[/url]]Just to add to the last post:

Since you can assign a TAB to different coordinates and jump to and fro, is there also a way to make the client send
data on certain parts of the screen?
[/quote]
You can move the cursor to the part of the screen where you want data entered. The state handling can get pretty complex as you'll at the very least have to handle backspace, typically by printing "\b \b" - without the space in the middle the character doesn't get erased. You could instead disable character mode until the user hits enter, but then you'd have to fix the cursor position right after because the enter would move the cursor at the client side.
23 May, 2010, quixadhal wrote in the 34th comment:
Votes: 0
Well, the good news is that the newest version of ncurses (5.7) has experimental support for threading.

Configuring it with all the thread-related stuff enabled and running the "rain" example program does indeed yield 12 "rain" processes (linux threads are actually full processes).

So, there's at least a chance of handling multiplayer support with threaded connections.
18 Jun, 2010, donky wrote in the 35th comment:
Votes: 0
Scandum said:
Whenever the user does something you allocate 2 or 3 temporary display arrays, create the entire VT display, next compare each byte with the player's display arrays (color array first), and only send the parts that differ. When all is send you copy the temporary display arrays to the player's display arrays.

Using this approach you save quite a bit of bandwidth.

Just as a note related to the implementation of my roguelike. I started off by sending each set of changed characters, as they were changed. "here's a batch that restores a small area of the screen that was drawn over" and "here's a batch that draws over a small area of the screen for now". The changes I sent were absolutely minimal, and were sent as they happened. Unfortunately, this was very slow. I next moved to a model where I did all the changes I need to, but tracked the start and end offsets of the range of changed characters per line. Then sent these line-based patches to a client. This is fast enough that I have no reason to look at other approaches.
18 Jun, 2010, donky wrote in the 36th comment:
Votes: 0
The posts about curses to this topic have been very educational. I don't suppose someone who is familiar with wrapping curses so that for instance a MUD server can instantiate an handler per-client connection and redirect the input and output over the given connection can paint an overview?
20.0/36