#!/usr/bin/perl

# MMUD V .007 For use with PHMUD (gotbnc.com)
# (C) 2001 James Nonnemaker & James Seter
#
# To use: ./mmud.pl nick host  [./mmud.pl Postal gotbnc.com]
#
# For a realistic 'feel' set your telnet clients font to
# Courier 10 -- Looks just like Zmud ;)
#
# Code portions shamelessly stolen from IRC.PERL
# Copyright (c) 1996 Tomi Ollila ; All rights reserved
# http://www.ajk.tele.fi/~too/sw/irc.readme
#
# This was written very late, and I am very tired, beware of bad coding teq'z ;)
#
# ID: mmud.pl
# Timestamp: Sat Aug 25 01:02:21 2001 EST
# Version: .007  (Shaken, not stirred)

use Socket;

&initcolors;  #init the colors.

print "$cyan+------------------------------------------------------------------+\r\n";
print "$cyan+             $red     MMUD Ver .007 (For use with PHMUD)  $cyan            +\r\n";
print "$cyan+ $yellow     (C) 2001 James Nonnemaker, James Seter, & Tomi Ollila  $cyan     +\r\n";
print "$cyan+$green Its a quick hack, its lame, and buggy -- but it works. Enjoy! :)$cyan +\n\r";
print "$cyan+------------------------------------------------------------------+\n\n\r";

die "Usage: mud nick host\n" if ($#ARGV < 1);

$nick = shift(@ARGV);
$host = shift(@ARGV);

print "$white* Connecting....\n\n\r";

&tcpConnect($host, 9050);

sub resetty { system("stty -raw echo") };
system("stty raw -echo");
select((select(STDOUT), $| = 1)[$[]);

$rin = '';

$fin=fileno(STDIN);
$fs =fileno(S);
vec($rin, $fin, 1) = 1;
vec($rin, $fs, 1) = 1;

print S "newuser $nick human male\n";

while (1)
{
    if ($isline) {
        $x = 1;
        select($rout = $rin, undef, undef, undef);
    }
    else 
    {
        $x = select($rout = $rin, undef, undef, 1.0);
    }

    if (vec($rout, $fs, 1))
    {
        while (&sread) { &parseout; }
    }
    
    if (vec($rout, $fins, 1))
    {
        &iread;
    }
    &cmdline if ($x == 0)
}

# ----- #


sub tcpConnect
{
    local($name, $aliases, $addrtype, $length, @addrs) = gethostbyname($_[0]);

    $that = pack("S n N x8", AF_INET, $_[1], unpack("N", $addrs[0]));

    socket(S, AF_INET, SOCK_STREAM, 0) || die "ERROR socket: $!\n";
    setsockopt(S, SOL_SOCKET, SO_KEEPALIVE, 1);

    connect(S, $that) || die "ERROR connect: $!\n";

    select((select(S), $| = 1)[$[]);
}

sub parseout
{
    if (s/^:([^ ]*) //) { $sender = $1; }
    else { $sender = ""; }

    s/[\r\n]//g;

    ($code, $recipient, @rest) = split(/ /, $_);
    $rest[0] =~ s/^://;

	#This is where we decide what to do with what we got..

$out = '+';
$ts = localtime;
@tsp = split(/\ /,$ts);
@tss = split(/\:/,$tsp[3]);
$ts = "[$tss[0]:$tss[1]]";
$the = "The";
@cur = split(/\:/,$_);
@bur = split(/\ /,$cur[1]);


if ($code eq '501') { $out = "$white* Unknown command."; }
if ($code eq 'PART') { $out  = "$yellow$sender leaves $bur[0]"; }
if ($code eq 'SAY') { if ($sender = $nick) { $sender = "You"; } $out = "$yellow*$cyan$sender says, \'$cur[1]\'"; }
if ($code eq 'EMOTE') { $out = "$green$sender $cur[1]"; }
if ($code eq 'JOIN') { $out = "$white$sender has arrived."; }
if ($code eq 'KICK') { $out = "$white$sender kicks a blow to the head of $recipient, ouch!"; }
if ($code eq 'DEATH') { $out = "$red$recipient dies."; }
if ($code eq '503') { $out = "$white* Unknown target."; }
if ($sender eq 'ERROR') { $out = "$white*** Disconnected."; }
if ($code eq '001') { $out = "$nwhite* @rest"; }
if ($code eq '010') { $out = "$nwhite* @rest\n\r"; }
if ($code eq '100') { $out = "+"; }
if ($code eq '130') { $out = "+"; } 
if ($code eq 'NEWSTATUS') { $out = "+"; }
if ($code eq '131') { $out = "+"; }
if ($code eq '132') { $out = "$red*** $rest[0]: $rest[1]"; }
if ($code eq '133') { $out = "$nwhite/SCORE"; }
if ($code eq '134') { $out = "+"; }
if ($code eq '135') { $out = "+"; }
if ($code eq '136') { $out = "$green$the $cur[1] lies here."; }
if ($code eq '200') { $out = "$cyan* @rest"; }
if ($code eq '201') { $out = "$green* /MOTD\n\r"; }
if ($code eq '205') { $out = "$yellow@rest"; }
if ($code eq '206') { if (length($rest[1]) < 1) { $out = "+"; } else { $out = "$magenta@rest"; } }
if ($code eq '203') { @ugh = split(/\ /,$_); $out = "$green$ugh[2] is $ugh[3] here"; }
if ($code eq '210') { $out = "+"; $exits = "$exits$blue@rest\n\r"; }
if ($code eq '211') { $out = "$blue\n\rExits:\n\r$exits"; $exits = ''; }
if ($code eq '502') { $out = "$white* You can\'t go that way."; }

if ($out ne '+') { print "$out \033[0m\n\r\r"; }
}       

sub parsein { 
$full = $_;
($cmd,$msg) = split(/\ /,$full,2);
if ($_ eq 'e') { $full = "EAST"; }
if ($_ eq 'w') { $full = "WEST"; }
if ($_ eq 'n') { $full = "NORTH"; }
if ($_ eq 's') { $full = "SOUTH"; }
if ($cmd eq 'say') { $full = "SAY :$msg"; }
if ($cmd eq 'emote') { $full = "EMOTE :$msg"; }

print S "$full\n"; 
}

# ------------------------------------------------------------------------

sub sread
{
    if ($#slines < 0)
    {
      SREAD: 
        $len = sysread(S, $sbuf, 1024, length($sbuf));

        unless (defined $len)
        {
            next SREAD if $! =~ /^Interrupted/;
            &resetty;
            die "\nSystem read error: $!\n";
        }
        &resetty, exit (0) if ($len == 0);

        @slines = split(/\n/, $sbuf);

        if (chop($sbuf) ne "\n") { $sbuf = pop(@slines); }
        else { $sbuf = ""; }
        push(@slines, "mark!");  
    }
    if ($#slines > 0)
    {
        $_ = shift(@slines);
        return 1;
    }
    shift(@slines); # remove mark. select() next time.
    0;
}

sub iread
{
    &cmdline if ($isline == 0);

  IREAD:
    $len = sysread(STDIN, $ibuf, 1024);

    unless (defined $len)
    {
        next IREAD if $! =~ /^Interrupted/;
        &resetty;
        die "\nSystem read error: $!\n";
    }
    &resetty, exit (0) if ($len == 0);
    
    @chars = split(//, $ibuf);

    while ($#chars >= 0)
    {
        $c = shift(@chars);
        
        if ($c eq "\003")
        {
            undef(@inarr);
            print "\r+++ Killing line +++\r\n";
        }
        elsif ($c eq "\177" || $c eq "\010")
        {
            if ($#inarr >= 0) 
            {  
                pop(@inarr); 
                print "\b \b";
            }
        }
        elsif ($c ne "\n" && $c ne "\r")
        { 
            push (@inarr, $c);
            print $c;
        }
        else
        {
            $_ = join('', @inarr);
            &beforestdout;
            $isline = 1; # optimize one select() call out.
            undef(@inarr);
            &parsein;
        }
    }
}

sub beforestdout
{
    local ($t) = time;

    if ($isline) 
    { 
        if ($#inarr >= 0)
        {
            $len = ($#inarr > 78)? 78: $#inarr;
            $spcs = substr("                                                                              ", 0, $len);
            print "\r$spcs \r";
        }
    }
    else { print "\r"; }

    $isline = 0;

    if ($tim + 598 < $t)
    {
        $tim = $t;
    }
    
    $msgs = 1;
}

sub cmdline
{
    print "\r";
    print join('', @inarr) if ($#inarr >= 0); 
    $isline = 1;
}


sub initcolors {
$black = "\033[30m";
$red = "\033[31m";
$green = "\033[32m";
$yellow = "\033[33m";
$blue = "\033[34m";
$magenta = "\033[35m";
$cyan = "\033[36m";
$white = "\033[37m";
$nwhite = $white;
}