On Thu, 11 Nov 1999, Chris Gilbert wrote: > Circle mud (like most muds) switches the client into line mode (Send a > line at a time to the mud) to do tab completion or similair you'd > need to use char mode (send every char typed to the game). Then > pickup on the tab char, and do someting with it, how you go about this > I don't know, but you also need to handle delete's CTRL-U, W, R, IE > standard ctrl sequences that the telnet/mud client handles in line > mode. You'd actually be writing a telnet server in reality. It would > also increase your bandwidth usage as every char typed creates a small > packet, rather than a line that sends just 1 packet containing the > line. This is only one method for implementing auto completion, and it is heavily reliant upon the TELNET protocol. Unfortunately, most MUD clients don't implement much or any of the TELNET protocol -- some implement the terminal type negotiation (if anyone wants information on that, I can send some details to the list) so that a MUD may autodetect ISO6429 ("ANSI") color code support. This means that anyone using such clients or any non-TELNET compliant TCP client (and this is the vast majority of Windows users, who are supplied only with "telnet.exe," which is little more than a TCP client, and a lot less than a TELNET client) would be left out. That's probably not a big difference from the second method, which is using a specialized client. The specialized client does not interfere with or change the basic method of communication between server and client -- that is, the traditional MUD, TELNET, or flat TCP client will work as always without experiencing any oddities for your specialized client support. The client's job is to receive information from the server and use that information for the user's benefit. There are a variety of extensions over the standard view that could be implemented, but strictly in relation to tab completion, the specialized client model allows us two separate ways to implement this model without resorting to "high" bandwidth solutions (such as is the TELNET char-by-char method). The first method is have the client cache certain important data (such as the objects in the room, in the player's inventory, etc.) for the lookup. This means that the tab completion can be done without reference to the server at all: the user types "get sw[tab]", the client inspects its cache of objects in the room and finds one which suits the given criterion. The "problem" with this approach is synchronizing the cache and the actual mud. Let's look at an example: [ Server SENDS expect-room-description ] [ Client PREPARES cache ] 0x90At the Head of a Winding Road0xFF [ Client CACHES "At the Head of a Winding Road" as room-title ] 0x91 You are standing at the head of a road that snakes through a grove of trees that rise to the north. The road, oddly enough, begins here, as to the south, east, and west there is nothing but rows of yellow grass to be seen.0xFF [ Client CACHES "..." as room-description ] 0x92Your bodyguard, Hans, is standing here, looking as menancing as always.0xFF [ Client CACHES mobile Hans as char-in-room ] 0x92Princess Chesapeak Rowle of Alyandri is resting here.0xFF [ Client CACHES player Chesapeak as char-in-room ] 0x92A small group of the princesses' hand-maidens are here.0xFF [ Client CACHES mobilegroup ChesHands as char-in-room ] 0x92A chipmunk is looking at you nervously.0xFF [ Client CACHES mobile chipmunk as char-in-room ] [ Server SENDS end-room-description ] [ Server SENDS waiting ] [ Client SHOWS prompt to User ] > look c[tab] [ Client INSPECTING room cache ] [ Client FINDS ambiguous match: Chesapeak, Chipmunk, ChesHands ] [ Client FILLS-IN 'h' ] > look ch<beep>[tab] [ Client FINDS ambiguous match: Chesapeak, Chipmunk, ChesHands ] [ Client NOTICES second ambiguity with same options, display options ] [ Client DISPLAYS options ] [ User adds 'e' to eliminate "Chipmunk" choice ] > look che[tab] [ Client FINDS ambiguous match: Chesapeak, ChesHands ] [ User adds "sa" to eliminate "ChesHands" choice ] > look che<beep>sa[tab] [ Client FINDS match: Chesapeak ] . . . The hexidecimal codes inside of the room description are used to identify the elements to the specialized client. Note that this is very similar to HTML: there is a starting element ("tag") and an ending element that identify the type of data. Note that there is one and only one ending element. It always closes for the element most recently opened. That is, unlike with HTML, you can NEVER close an element before closing any and all of the elements nested inside of it (i.e., "<b><i>hello</b></i>" is technically valid HTML). This sort of mark-up for the client allows the client to identify elements from the server, cache them locally, and then not have to recommunicate these things whenever the user requests them. The server must, however, keep the client in synch with the latest updates, and so it should have some sort of system for efficiently updating the client's data. The efficiency of bandwidth is already given us by output buffering, so if twelve objects are dropped into the room, the server does not communicate a separate packet for each of these twelve objects, but groups them together in the user's output buffer to be sent a little later. Anyway, the only real cost of this method is determining on each update of the room if there's someone in it who needs to have their client cache updated. It's simple enough to do this by keeping a list of client users on the room so that it may update them as it sees fit. Since when the player first enters the room their data is all the same, the client shouldn't need to worry about User A and User B having different data that needs to be updated. The second method puts more work on the server side. Basically, the client catches the [TAB] as a special character and then sends the incomplete input to server for observation. The server finds a suitable target (or doesn't) and returns the relevant information to the client. A typical communication might look like: PLAYER> get sw[tab] CLIENT> CSI 0x01 "sw" 0xFF SERVER> (Inspecting room contents for takable object.) SERVER> (Found a sword, no ambiguity.) SERVER> CSI 0x01 "sword" 0xFF CLIENT> (Received response, filling in as appropriate.) PLAYER> get sword[ENTER] CLIENT> (Got complete line, sending as is.) SERVER> (Got complete line, interpreting as is.) Note that unlike the previous method, this one shifts the burden of computation of what "sw" refers to to the server. The previous method does this on the client, with the server's only cost being a short loop through room->clientUsersList to update them on XXX_to_room() and XXX_from_room(). Neither method seems difficult to implement from the server side. From the client side, the first method would definately be harder. I couldn't say which method is better, that depends upon whether you want to have that sort of thing up to the client (it's basically harmless, though) and whether you feel reducing server CPU usage justifies the extra effort to shift the burden to the client (maybe or maybe not in a text game). Please, if you're going to be using specialized clients that perform a lot of the work for you, remember the first rule of specialized clients, as most recently proven by problems with Diablo, Ultima Online, distributed.net, and others: Never trust the client. It is, after all, in the hands of the enemy -- the user stops becoming a player and starts becoming a threat when they are given the power to become a threat to the game's integrity. As such, certain things should NEVER be for the client's consideration: damage calculations, etc., are best left on the server side unless you are willing to risk the player modifying the client to cheat. Of course, the best way to catch this sort of cheating is to occassionally have the server compute the amount of damage the player's attack should do and then compare that with what the client is telling us it should do. It's a pretty good method of detecting something fishy going on with the client, but it's hardly foolproof and entirely based on chance. That is, some players, in a pinch, might be willing to risk enabling a super-damage attack based on the idea that the server probably won't be checking up on you on that one specific attack in a thousand others. The fact is, there's no real good way to entrust the client with such calculations, and so it should best not be left to the client at all. -dak +------------------------------------------------------------+ | Ensure that you have read the CircleMUD Mailing List FAQ: | | http://qsilver.queensu.ca/~fletchra/Circle/list-faq.html | +------------------------------------------------------------+
This archive was generated by hypermail 2b30 : 12/15/00 PST