|[ LiB ]|
I've improved the SocketLib::Telnet protocol object from Chapter 6 and integrated it into the BetterMUD. You may remember that I described the idea of making the protocol object automatically translate generic text- color tags into actual VT-100 control codes. This is the main addition to the BetterTelnet class (nice original name ).
In Chapter 9, I implemented stores and rooms in the SimpleMUD. In some room descriptions, I told you that I had manually inserted VT-100 color codes into the descriptions of some rooms in the actual text datafiles. This was a tricky business; I actually had to use a binary hex-editor program to insert the escape codes.
Another downside of that method is that it assumes everyone is going to be using Telnet, and it's okay to make that assumption for the SimpleMUD, but for the BetterMUD, which should have no idea what Telnet is (outside the networking module, of course), that's just not going to cut it.
Without messing up how the text displays. I created a method to represent color codes inside a piece of text. I've opted to use an HTML-like method of color tags. Here's a sample description of one of the rooms within the BetterMUD:
You are in the gardens of Worthington, where you can see much <#FFFF00>flora<$reset> and <#00FF00>fauna<$reset> all around.
The text within the angle brackets is color coded. I've included two different kinds of color codes: hex-numeric, and alphabetic.
Whenever the BetterTelnet class is sent a new piece of text to return to the player, it tries to find these tags and replace them with their VT-100 equivalents. So, for example, if this class sees <$red> , it removes that from the string and replaces it with the VT-100 code <esc>[31m . I've included translation mechanisms for all seven color codes, as well as the dim and bold codes, and a reset code as well:
<$ magenta >
The dollar sign signifies "string", which means that whenever the translator finds <$ , it knows a string-based code is going to follow.
Hex-numeric codes are much more versatile and can represent up to 16 million different colors. If you've ever played around with HTML, you should be familiar with the concept. Basically, in <#RRGGBB> , the first two hex-digits represent the red, the next two green, and the last two blue. A code such as <#FFFFFF> represents pure white, whereas <#000000> represents pure black. The two colors shown in the previous description example are pure yellow and pure green.
Unfortunately, there is no magical way to make VT-100 instantly support more than the default 15 colors, so the BetterTelnet protocol module has a bit of work to do. Whenever the protocol class detects a hex-numeric color code, it must translate that color into the puny 15-color palette of VT-100. For this approach, I've used a simple algorithm that splits each color component into the numbers , 0, 1 or 2. For example, the red component of FF (255) translates to the number 2; 00 translates to 0, and 7F (127) translates to 1.
I used an algorithm to downsize the color ranges by splitting up the range 0255 into three regions . So any component from 0 to 85 is treated as 0, 86 to 171 is treated as 1, and any component from 172 to 255 is treated as 2. Figure 16.4 shows this process for a sample color of <#007FFF> , which is a pretty shade of light blue.
If you have a paint program such as Paint Shop Pro, you can probably open up a color picker tool, and enter the HTML code into it. If your paint program doesn't have an HTML converter, then you'll have to make do with color conversion manually, by converting each hex- color component into a decimal.
Therefore, <#007FFF> is translated into 012. Inside the BetterTelnet module file, I have a 3x3x3 array of color codes named g_telnetcolors . I use these three numbers as indexes into that array, like this: g_telnetcolors , and the array at that point holds the Telnet color closest to what I want.
For colors like white, black, blue, and magenta, the translation is exact; VT-100 specifically supports those colors. But VT-100 doesn't support the cool blue color I just converted, so what the heck should I do?
I make an estimate. When I initialized the Telnet color array, the entry 012 looked like this:
g_telnetcolors = blue + bold;
So the color that is output is bold blue. This isn't an exact match, since bold blue is a little bit darker than 007FFF, but it's Telnet's closest color match. Most colors are close enough so that you won't notice too much difference, but there are a few colors that VT-100 doesn't come close to supporting:
g_telnetcolors = yellow + dim; g_telnetcolors = red + bold;
The first color is supposed to be orange, but you'll never get anything orange-looking from VT-100. The closest you'll get is the dim yellow (which, on most clients , ends up looking like a disgusting shade of brownish chartreuse).
The other color is a carnation pink, which the closest you can get to pure bold red.
So you should be aware that the BetterTelnet protocol automatically tries to convert colors as best it can, but sometimes it fails miserably.
The BetterTelnet class adds three new functions to the old SocketLib::Telnet class, as well as a hidden class and a hidden array.
Here are the three new functions:
static std::string TranslateColors( const std::string& p_str ); static void TranslateStringColor( std::string::size_type i, std::string::size_type j, std::string& p_str ); static void TranslateNumberColor( std::string::size_type i, std::string::size_type j, std::string& p_str );
You shouldn't ever need to specifically call any of these functions yourself, because the protocol class automatically calls them functions for you. For example, when you send text to a BetterTelnet protocol object using the SendString (it has the same parameters as SocketLib::Telnet::SendString ), the function automatically calls TranslateColors for you, searches for color tags beginning with <$ or <# , and translates them. The actual translation is done inside the next two functions, which are just helpers. The helpers take the starting index of the color code, the ending index of the color code, and the string to translate as parameters, and it performs the color conversion in place.
I don't want to show you the code, since it is just boring string manipulations, and I'm sure you've had your fill of them.
I also mentioned that I created a hidden class. This class is named INITTELNETCOLORS , and its only purpose is to initialize the g_telnetcolors array with Telnet color codes when the program starts. You don't have to worry about that. If you're interested in seeing how it works though, you can always look at it inside the BetterTelnet.cpp file.
|[ LiB ]|