TeensyMud - 'A ruby mud server.'

Browse repository
back

tclient.rb

#!/usr/bin/env ruby
#
# file:: tclient.rb
# author:: Jon A. Lambert
# version:: 2.8.0
# date:: 01/19/2006
#
# This source code copyright (C) 2005, 2006 by Jon A. Lambert
# All rights reserved.
#
# Released under the terms of the TeensyMUD Public License
# See LICENSE file for additional information.
#
$:.unshift "lib" if !$:.include? "lib"
$:.unshift "vendor" if !$:.include? "vendor"

require 'pp'

require 'network/reactor'

Version = "0.2.0"
BANNER=<<-EOH

This is TeensyClient version #{Version}

Copyright (C) 2005, 2006 by Jon A. Lambert
Released under the terms of the TeensyMUD Public License

EOH


#
# =Purpose
# TeensyClient is a really cheap mud client
#



#
class Client
include Publisher

def initialize(opts)
@opts = opts
@conn = nil
end

def update(msg)
case msg
when Connection
@conn = msg
unsubscribe_all
msg.subscribe(self)
self.subscribe(msg)
if @opts.win32
@conn.set(:terminal, "vt100")
else
@conn.set(:terminal, "xterm")
end
when :initdone
@conn.set(:termsize, [80,43])
end
end

end

class CursesClient < Client
def initialize(opts)
super(opts)
Curses.init_screen
Curses.cbreak
Curses.noecho if @opts.echo
Curses.nl
Curses.stdscr.scrollok(true)
if !$opts.win32 # Need workaround for these
Curses.stdscr.keypad(true)
Curses.timeout = 0
end
Curses.start_color
end

def conmsg msg
Curses.addstr(msg)
Curses.refresh
end

def update(msg)
case msg
when Connection, :initdone
super(msg)
when :disconnected
unsubscribe_all
$shutdown = true
Curses.addstr "Disconnected."
exit
when String
Curses.addstr(msg)
Curses.refresh
else
Curses.addstr "Unknown msg - #{msg.inspect}"
end
end

def run
shutdown = false
connection = Reactor.new(@opts.port, $conntype, $connio, $connopts,
$connfilters, @opts.address)
raise "Unable to start TeensyClient" unless connection.start(self)
conmsg "Connected to #{@opts.address}:#{@opts.port}. Use F10 to QUIT"
until shutdown
connection.poll(0.1)
Curses.refresh
c = Curses.getch
case c
when 32..127
publish(c.chr)
when Curses::KEY_ENTER
publish("\r\n")
when 10
publish("\n")
when 4294967295 # Error Timeout. This is -1 in Bignum format
when Curses::KEY_F10
conmsg "Quitting..."
shutdown = true
else
conmsg "Unknown key hit code - #{c.inspect}"
end
end # until
connection.stop
rescue SystemExit, Interrupt
conmsg "\nConnection closed exiting"
rescue Exception
conmsg "\nException caught error in client: " + $!
conmsg $@
ensure
Curses.close_screen
end

end

class ConsoleClient < Client
def initialize(opts)
super(opts)
system('stty cbreak -echo') if !@opts.win32 && @opts.echo
end

def conmsg msg
puts msg
end

def update(msg)
case msg
when Connection, :initdone
super(msg)
when :disconnected
unsubscribe_all
$shutdown = true
puts "Disconnected."
exit
when String
print msg
else
puts "Unknown msg - #{msg.inspect}"
end
end

def run
shutdown = false
connection = Reactor.new(@opts.port, $conntype, $connio, $connopts,
$connfilters, @opts.address)
raise "Unable to start TeensyClient" unless connection.start(self)
conmsg "Connected to #{@opts.address}:#{@opts.port}. Use CTL-C to QUIT"
until shutdown
connection.poll(0.1)
c = getkey
case c
when nil
when 32..127
publish(c.chr)
when 13
publish("\n") if @opts.win32
when 10
publish("\n") if !@opts.win32
when 315
publish("\e[11~")
when 316
publish("\e[12~")
when 317
publish("\e[13~")
when 318
publish("\e[14~")
when 319
publish("\e[15~")
when 320
publish("\e[17~")
when 321
publish("\e[18~")
when 322
publish("\e[19~")
when 323
publish("\e[20~")
when 324 # Windows F10
conmsg "Quitting..."
shutdown = true
# when 27 # xterm F10
# if getkey == 91 && getkey == 50 && getkey == 49 && getkey == 126
# conmsg "Quitting..."
# shutdown = true
# end

when 338 # INS
publish("\e[2~")
when 339 # DEL
publish("\010")
when 327 # HOME
publish("\e[7~")
when 335 # END
publish("\e[8~")
when 329 # PAGEUP
publish("\e[5~")
when 337 # PAGEDOWN
publish("\e[6~")
when 328 # UP
publish("\e[A")
when 336 # DOWN
publish("\e[B")
when 333 # RIGHT
publish("\e[C")
when 331 # LEFT
publish("\e[D")


when 256..512
conmsg "Unknown key hit code - #{c.inspect}"
else
publish(c.chr)
# conmsg "Unknown key hit code - #{c.inspect}"
end
end # until
connection.stop
rescue SystemExit, Interrupt
conmsg "\nConnection closed exiting"
rescue Exception
conmsg "\nException caught error in client: " + $!
conmsg $@
ensure
system('stty -cbreak echo') if !@opts.win32 && @opts.echo
end

end

#
# Processes command line arguments
#
require 'optparse'
require 'ostruct'
def get_options
# parse options
begin
# The myopts specified on the command line will be collected in *myopts*.
# We set default values here.
myopts = OpenStruct.new
myopts.port = 4000
myopts.address = 'localhost'
myopts.curses = false
myopts.echo = false
myopts.verbose = false
myopts.trace = false
RUBY_PLATFORM =~ /win32/ ? myopts.win32 = true : myopts.win32 = false

opts = OptionParser.new do |opts|
opts.banner = BANNER
opts.separator ""
opts.separator "Usage: ruby #{$0} [options]"
opts.separator ""
opts.on("-p", "--port PORT", Integer,
"Select the port of the mud",
" (defaults to 4000)") {|myopts.port|}
opts.on("-a", "--address URL", String,
"Select the address of the mud",
" (defaults to \'localhost\')") {|myopts.address|}
opts.on("-e", "--[no-]echo", "Run in server echo mode") {|myopts.echo|}
opts.on("-t", "--[no-]trace", "Trace execution") {|myopts.trace|}
opts.on("-c", "--[no-]curses", "Run with curses support") {|myopts.curses|}
opts.on("-v", "--[no-]verbose", "Run verbosely") {|myopts.verbose|}
opts.on_tail("-h", "--help", "Show this message") do
$stdout.puts opts.help
exit
end
opts.on_tail("--version", "Show version") do
$stdout.puts "TeensyClient #{Version}"
exit
end
end

opts.parse!(ARGV)

return myopts
rescue OptionParser::ParseError
$stderr.puts "ERROR - #{$!}"
$stderr.puts "For help..."
$stderr.puts " ruby #{$0} --help"
exit
end
end


if $0 == __FILE__

$conntype = :client
$connio = :sockio
$connopts = [:zmp, :ttype, :naws]
$connfilters = [:telnetfilter, :debugfilter] #, :terminalfilter]
$opts = get_options

if $opts.echo
$connopts << :echo << :sga
end

if $opts.curses
require 'curses'
end

if $opts.win32
require 'Win32API'
Kbhit = Win32API.new("msvcrt", "_kbhit", [], 'I')
Getch = Win32API.new("msvcrt", "_getch", [], 'I')
def getkey
sleep 0.01
return nil if Kbhit.call.zero?
c = Getch.call
c = Getch.call + 256 if c.zero? || c == 0xE0
c
end
else
def getkey
select( [$stdin], nil, nil, 0.01 ) ? c = $stdin.getc : c = nil
end
end

if $opts.trace
$tf = File.open("trace.log","w")
set_trace_func proc { |event, file, line, id, binding, classname|
$tf.printf "%8s %s:%-2d %10s %8s\n", event, file, line, id, classname
}
end

$stdin.sync = true
$stdout.sync = true

if $opts.curses
client = CursesClient.new($opts)
else
client = ConsoleClient.new($opts)
end
client.run
$tf.close if $opts.trace
exit

end