Register forum user name Search FAQ

Gammon Forum

Notice: Any messages purporting to come from this site telling you that your password has expired, or that you need to verify your details, confirm your email, resolve issues, making threats, or asking for money, are spam. We do not email users with any such messages. If you have lost your password you can obtain a new one by using the password reset link.

Due to spam on this forum, all posts now need moderator approval.

 Entire forum ➜ SMAUG ➜ SMAUG coding ➜ Question

Question

It is now over 60 days since the last post. This thread is closed.     Refresh page


Posted by Corey   (54 posts)  Bio
Date Sun 09 Dec 2007 06:55 PM (UTC)
Message
How could I make a mod so the players can see what they are typing? I have smaug fuss lua 1.8
Top

Posted by Nick Gammon   Australia  (23,133 posts)  Bio   Forum Administrator
Date Reply #1 on Sun 09 Dec 2007 07:25 PM (UTC)
Message
See what they are typing? What client are you using? Most clients let players see what they type. If they are using telnet they could turn "local echo" on.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Corey   (54 posts)  Bio
Date Reply #2 on Sun 09 Dec 2007 07:37 PM (UTC)
Message
hmm, I just use the win32 telnet to get in.
Top

Posted by Zeno   USA  (2,871 posts)  Bio
Date Reply #3 on Sun 09 Dec 2007 07:40 PM (UTC)
Message
I would suggest using a MUD client and not telnet. Not being able to see the text has to do with the client, and not the MUD.

Zeno McDohl,
Owner of Bleached InuYasha Galaxy
http://www.biyg.org
Top

Posted by Nick Gammon   Australia  (23,133 posts)  Bio   Forum Administrator
Date Reply #4 on Mon 10 Dec 2007 02:44 AM (UTC)
Message
MUSHclient is available for free from this site.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Valcados   (15 posts)  Bio
Date Reply #5 on Wed 19 Dec 2007 02:51 AM (UTC)

Amended on Wed 19 Dec 2007 02:53 AM (UTC) by Valcados

Message
To actually answer your question, this IS possible. Using the telnet protocol. In fact, telnet servers are *supposed* to have support for remote echo. If you set it up so SMAUG listens for remote echo requests and responds appropriately, that'd be a killer snippet. Definitely not a project for a novice coder. It would go like this:

1. In comm.c, before filtering out all non-keyboard characters, check for the special signal which in telnet protocol suggests the client is asking you to provide remote echo.

2. When that signal is heard, send the appropriate reply signal, to the effect of "Okay you got it." (See the protocol for more info) Then flag the descriptor accordingly.

3. Throughout gameplay, keep checking the raw input for signals saying they want you to stop remote echo. If you get such a signal, un-flag the descriptor and send a return signal saying "Ok".

4. For any flagged descriptor.. each time you get input, echo it back. Take care to handle backspaces in a good way.

5. (Optional, extra credit) You could even echo it to any imm who's snooping the player. Making a "realtime snoop".

Here's a link to the telnet protocol specification:
http://www.faqs.org/rfcs/rfc854.html
Top

Posted by ThomasWatts   USA  (66 posts)  Bio
Date Reply #6 on Wed 19 Dec 2007 04:50 AM (UTC)
Message
It's also possible to enable color support and negotiate other things like username, password or encryption. This is how the MCP or Mud Compression Protocol is supported.
As for REMOTE echo it is a waste of bandwith. Most clients have a built in local echo that you can turn off and on. Most muds use the ability of the telnet protocol to turn local echo off before you enter your password, then turn local echo back on. As for the request of a snippet:
BOO ON POST LIMITS! See below.
Top

Posted by ThomasWatts   USA  (66 posts)  Bio
Date Reply #7 on Wed 19 Dec 2007 04:51 AM (UTC)

Amended on Thu 20 Dec 2007 12:00 AM (UTC) by Nick Gammon

Message

// all telnet negotiation options supported, some do not follow the DO-WILL-DONT-WONT
static int check_telopts(DESCRIPTOR_DATA *d, char *soin, int i, int *length) {
  unsigned char iac_type, iac_command;
  int j = 0, l = 0, len = *length;
  if( (unsigned char)soin[i] == IAC ) {
    i++;
    iac_type = soin[i++];
    switch( iac_type ) {
      case DO: // do attempt to negotiate, or client does support
        iac_command = soin[i++];
        if( iac_command == TELOPT_BINARY ) {
          write_to_descriptor(d, wont_binary_str, 0);
        } else if( iac_command == TELOPT_ECHO ) {
          SET_BIT(d->telOpts, 7); // putty sends this automatically
          // we will not echo characters, may be bandwith problems
        } else if( iac_command == TELOPT_OUTMRK ) {
          if( !IS_SET(d->telOpts, 10) ) {
            char out[SHORT_STR_LENGTH];
            strcpy(out, neg_outmrk_start);
            strcat(out, "The Breeding Grounds");
            strcat(out, neg_outmrk_end);
            write_to_descriptor(d, out, 0);
          }
          SET_BIT(d->telOpts, 10);
        } else if( iac_command == TELOPT_COMPRESS2 ) {
          if( !IS_SET(d->telOpts, 3) )
            write_to_buffer(d, "Compression supported.\r\n");
          compressStart(d);
        } else if( iac_command == TELOPT_SGA ) {
          SET_BIT(d->telOpts, 5); // putty sends this automatically
        } else
          bug("Unsupported IAC DO command %x.", iac_command);
        break;
      case WILL: // client will negotiate, or client wants
        iac_command = soin[i++];
        if( iac_command == TELOPT_BINARY ) {
          write_to_descriptor(d, dont_binary_str, 0);
        } else if( iac_command == TELOPT_ECHO ) {
          SET_BIT(d->telOpts, 7);
          bug("Implement WILL ECHO bitches!");
        } else if( iac_command == TELOPT_TTYPE ) {
          SET_BIT(d->telOpts, 0); //supports telnet type
          if( !IS_SET(d->telOpts, 15) )
            write_to_descriptor(d, neg_term_type_str, 0);
        } else if( iac_command == TELOPT_TUID ) {
          if( !IS_SET(d->telOpts, 14) )
            write_to_descriptor(d, do_tuid_str, 0);
        } else if( iac_command == TELOPT_NAWS ) {
          if( !IS_SET(d->telOpts, 1) )
            write_to_descriptor(d, neg_naws_str, 0);
          SET_BIT(d->telOpts, 1);
        } else if( iac_command == TELOPT_LINEMODE ) {
          SET_BIT(d->telOpts, 4);
          bug("Implement WILL LINEMODE bitches!");
        } else if( iac_command == TELOPT_SGA ) {
          SET_BIT(d->telOpts, 5);
        } else if( iac_command == TELOPT_SPEED ) {
          SET_BIT(d->telOpts, 6); // GO PUTTY!
          write_to_descriptor(d, dont_tspeed_str, 0);
        } else if( iac_command == TELOPT_ENVIRON ) {
          write_to_descriptor(d, dont_oldenv_str, 0);
        } else if( iac_command == TELOPT_NEWENV ) {
          write_to_descriptor(d, dont_newenv_str, 0);
        } else
          bug("Unsupported IAC WILL command %x.", iac_command);
        break;
      case DONT: // client does not want
        iac_command = soin[i++];
        if( iac_command == TELOPT_COMPRESS2 ) {
          REMOVE_BIT(d->telOpts, 3);
          compressEnd(d);
        } else if( iac_command == TELOPT_OUTMRK ) {
          REMOVE_BIT(d->telOpts, 10);
        } else
          bug("Unsupported IAC DONT command %x.", iac_command);
        break;
      case WONT: // client does not support
        iac_command = soin[i++];
        if( iac_command == TELOPT_SGA ) {
          write_to_buffer(d, "Half-Duplex connections are not supported.\r\n");
          close_socket(d, FALSE);
        } else if( iac_command == TELOPT_TUID ) {
          REMOVE_BIT(d->telOpts, 14);
        } else if( iac_command == TELOPT_TTYPE ) {
          write_to_buffer(d, "Client does not support terminal type negotiation, ANSI color disabled.\r\n");
          REMOVE_BIT(d->telOpts, 0);
          REMOVE_BIT(d->telOpts, 15);
        } else if( iac_command == TELOPT_NAWS ) {
          REMOVE_BIT(d->telOpts, 1); // Pueblo does not support
        } else if( iac_command == TELOPT_LINEMODE ) {
          REMOVE_BIT(d->telOpts, 2); // Pueblo does not support
        } else if( iac_command == TELOPT_ECHO ) {
          REMOVE_BIT(d->telOpts, 7);
        } else
          bug("Unsupported IAC WONT command %x.", iac_command);
        break;
      case SB: // subnegotiation
        iac_command = soin[i++];
        if( iac_command == TELOPT_TTYPE ) {
          // should be implemented without fault
          char ttype[24]; // should be well long enough for this
          j = 0;
          // blitz thru until we find ascii characters
          while( !isprint(soin[i]) ) i++;
          while( isprint(soin[i]) ) {
            ttype[j] = LOWER(soin[i]);
            i++; j++;
          }
          ttype[j] = '\0';
          j = 0;
          while( supported_ansi[j] != NULL ) {
            if( strcmp(ttype, supported_ansi[j]) == 0 ) {
              if( !IS_SET(d->telOpts, 15) ) {
                SET_BIT(d->telOpts, 15);
                write_to_buffer(d, "&G&uA&bN&yS&rI&& Color supported.\r\n");
              }
              break;
            }
            j++;
          }
          if( !IS_SET(d->telOpts, 15) ) { // only asks twice
            if( !IS_SET(d->nextOpt, 15) ) {
              write_to_descriptor(d, neg_term_type_str, 0);
              SET_BIT(d->nextOpt, 15);
            } else { // no support for color
              REMOVE_BIT(d->nextOpt, 15);
              REMOVE_BIT(d->telOpts, 15);
            }
          }
        } else if( iac_command == TELOPT_TUID ) {
          // use this instead of username/password
          unsigned long uuid = 0L;
          unsigned char tmp;
          SET_BIT(d->telOpts, 14);
          tmp = soin[i++];
          if( tmp > 0 ) {
            if( tmp == 255 ) tmp = soin[i++];
            uuid += (tmp << 24);
          }
          tmp = soin[i++];
          if( tmp > 0 ) {
            if( tmp == 255 ) tmp = soin[i++];
            uuid += (tmp << 16);
          }
          tmp = soin[i++];
          if( tmp > 0 ) {
            if( tmp == 255 ) tmp = soin[i++];
            uuid += (tmp << 8);
          }
          tmp = soin[i++];
          if( tmp > 0 && tmp == 255 ) tmp = soin[i++];
          uuid += tmp;
          if( uuid <= 0 ) {
            write_to_buffer(d, "UUID less than or equal to ZERO not supported.\r\n");
            close_socket(d, FALSE);
            break;
          }
          d->uniqueNumber = uuid;
        } else if( iac_command == TELOPT_NAWS ) {
Top

Posted by ThomasWatts   USA  (66 posts)  Bio
Date Reply #8 on Wed 19 Dec 2007 04:51 AM (UTC)

Amended on Thu 20 Dec 2007 12:00 AM (UTC) by Nick Gammon

Message

          // may be renegotiated during connection
          // 80 width(chars), 24 height(lines) is default
          unsigned char tmp; //should be split into four characters
          SET_BIT(d->telOpts, 1);
          d->max_width = 0;
          tmp = soin[i++];
          if( tmp > 0 ) {
            if( tmp == 255 ) tmp = soin[i++];
            d->max_width += (tmp << 8);
          }
          tmp = soin[i++];
          if( tmp > 0 && tmp == 255 ) tmp = soin[i++];
          d->max_width += tmp;
          d->max_height = 0;
          tmp = soin[i++];
          if( tmp > 0 ) {
            if( tmp == 255 ) tmp = soin[i++];
            d->max_height += (tmp << 8);
          }
          tmp = soin[i++];
          if( tmp > 0 && tmp == 255 ) tmp = soin[i++];
          d->max_height += tmp;
          write_to_buffer(d, "Window Size set to: &r%d&yx&r%d&&\r\n", d->max_width, d->max_height);
        } else if( iac_command == TELOPT_OUTMRK ) {
          unsigned char is_ack = soin[i++];
          if( is_ack == NAK )
            REMOVE_BIT(d->telOpts, 10);
        } else
          bug("Unsupported IAC SB command %x.", iac_command);
        break;
      case IP:
        write_to_buffer(d, "INTERRUPT PROCESS Received. Closing connection.\r\n");
        close_socket(d, FALSE);
        break;
      case AYT:
        write_to_buffer(d, "ARE YOU THERE Received.  Yes, we are here.\r\n");
        break;
      case EC: // Eat the previous character
        if( i < 3 )
          break;
        l = i;
        i -= 3;
        for( j = 0; l + j < len; j++ )
          soin[i+j] = soin[l+j];
        //j = len - i - 1;
        //memmove(soin + i, soin + l, len - l);
        soin[i+j] = '\0';
        *length -= 3;
        break;
      case EL: // Eat the entire line
        soin[0] = '\0';
        i = 0;
        *length = 0;
        break;
      //following are unsupported, ignore
      case SE:  case NOP: case DM:  case BRK: 
      case AO:  case GA:  break;
      default:
        bug("Unsupported IAC type %x.", iac_type);
        break;
    }
  }
  return i;
}
Top

Posted by ThomasWatts   USA  (66 posts)  Bio
Date Reply #9 on Wed 19 Dec 2007 04:53 AM (UTC)
Message
That's the basics of what I've come up with. There is of course more to the above, IE #defines, etc, but the basics.
!!YourMileageMayVary!!
Top

Posted by Valcados   (15 posts)  Bio
Date Reply #10 on Wed 19 Dec 2007 01:58 PM (UTC)
Message
Very impressive :) Yeah, putty is a precious snowflake of a client. Lots of MUDs, when you first enter your name with putty, itll say "Illegal name" because the MUD didn't properly filter out some junk.

As for remote echo. Well, that's what the thread was about. I disagree about bandwidth considerations. Remote echo shouldn't pose any bandwidth problems in this day and age. I think those remarks in the RFC are based on early 80s computing. If I send 100 characters, remote echo will cost 100 characters being sent back. Whereas if I send "L\n\r" 33 times while standing in a room with a big room description, the MUD will send back hundreds of thousands of characters. Drop in the bucket.

I agree about most clients having the local echo option. I just wonder whether respecting remote echo requests, would improve the MUD experience for people using the versions of Windows telnet where local echo is off by default. First impressions last, and I think lots of people won't stick around long enough to blindly stumble their way to a helpfile saying how to turn local echo on.
Top

The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).

To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.


27,314 views.

It is now over 60 days since the last post. This thread is closed.     Refresh page

Go to topic:           Search the forum


[Go to top] top

Information and images on this site are licensed under the Creative Commons Attribution 3.0 Australia License unless stated otherwise.