The Account class handles connection login and passes them to character.
Create an Account connection. This is a temporary object that handles login for character and gets them connected.
# File lib/core/account.rb, line 32 def initialize(conn) super("",nil) self.passwd = nil self.color = false self.characters = [] @conn = conn # Reference to network session (connection) @mode = :initialize @echo = false @termsize = nil @terminal = nil @checked = 3 # Login retry counter - on 0 disconnect @account = nil # used only during sign-in process @character = nil # reference to the currently played Character. end
If echo hasn’t been negotiated, we want to leave the cursor after the message prompt, so we prepend linefeeds in front of messages. This is hackish.
# File lib/core/account.rb, line 327 def append_echo(msg) @echo ? msg : "\n" + msg end
Disconnects this account
# File lib/core/account.rb, line 371 def disconnect(msg=nil) publish("[home 1,1][scrreset][clear]") if vtsupport? publish(msg + "\n") if msg publish("Bye!\n") publish(:quit) unsubscribe_all end
Handles String messages from Connection - called by update. This was refactored out of #update for length reasons.
msg
The message string
@mode tracks the state changes, The Account is created with the initial state of :initialize. The following state transition diagram illustrates the possible transitions.
:intialize -> :name Set when Account:update receives :initdone msg :name -> :password Sets @login_name and finds @account
:playing Creates a new character if Guest account
:password -> :newacct Sets @login_passwd
-> :menu Good passwd, switches account, if account_system option on goes to menu -> :playing Good passwd, switches account, loads character -> :name Bad passwd -> disconnect Bad passwd, exceeds @check attempts (see Account#disconnect)
:newacct -> :menu If account_system option on goes to menu
-> :playing Creates new character, adds account
:menu -> #parse_menu Redirect message (see #parse_menu) :playing -> @character Redirect message (see Character#parse)
# File lib/core/account.rb, line 148 def parse_messages(msg) case @mode when :initialize # ignore everything until negotiation done when :name publish("[clearline]") if vtsupport? @login_name = msg.proper_name if options['guest_accounts'] && @login_name =~ %rGuest/ self.name = "Guest#{id}" @character = new_char put_object(self) world.all_accounts << id # make the account non-swappable so we dont lose connection Engine.instance.db.makenoswap(id) @conn.set(:color, color) welcome @mode = :playing elsif @login_name.empty? sendmsg(append_echo("login> ")) @mode = :name else acctid = world.all_accounts.find {|a| @login_name == get_object(a).name } @account = get_object(acctid) sendmsg(append_echo("password> ")) @conn.set(:hide, true) @mode = :password end when :password @login_passwd = msg @conn.set(:hide, false) if @account.nil? # new account sendmsg(append_echo("Create new user?\n'Y/y' to create, Hit enter to retry login> ")) @mode = :newacct else if @login_passwd.is_passwd?(@account.passwd) # good login # deregister all observers here and on connection unsubscribe_all @conn.unsubscribe_all # reregister all observers to @account @conn.subscribe(@account.id) # make the account non-swappable so we dont lose connection Engine.instance.db.makenoswap(@account.id) @conn.set(:color, @account.color) switch_acct(@account) # Check if this account already logged in reconnect = false if @account.subscriber_count > 0 @account.publish(:reconnecting) @account.unsubscribe_all reconnect = true end @account.subscribe(@conn) if options['account_system'] @account.sendmsg(append_echo(login_menu)) @account.mode = :menu else @character = get_object(@account.characters.first) # make the character non-swappable so we dont lose references Engine.instance.db.makenoswap(@character.id) world.connected_characters << @character.id @character.account = @account @account.character = @character welcome(reconnect) @account.mode = :playing end else # bad login @checked -= 1 sendmsg(append_echo("Sorry wrong password.")) if @checked < 1 disconnect else @mode = :name sendmsg(append_echo("login> ")) end end end when :newacct if msg =~ %r^y/ self.name = @login_name self.passwd = @login_passwd.encrypt put_object(self) # make the account non-swappable so we dont lose connection Engine.instance.db.makenoswap(id) world.all_accounts << id @conn.set(:color, color) if options['account_system'] sendmsg(append_echo(login_menu)) @mode = :menu else @character = new_char welcome @mode = :playing end else @mode = :name sendmsg(append_echo("login> ")) end when :menu, :menucr, :menupl parse_menu(msg) when :playing @character.parse(msg) else log.error "Account#parse_messages unknown :mode - #{@mode.inspect}" end end
# File lib/core/account.rb, line 338 def prompt if vtsupport? publish("[cursave][home #{@termsize[1]-2},1]" + "[color Yellow on Red]#{" "*@termsize[0]}[/color]" + "[home #{@termsize[1]-1},1][clearline][color Magenta](#{name})[#{@mode}][/color]" + "[currest][clearline]> ") publish("[home #{@termsize[1]-2},1]" + "[color Yellow on Red]#{" "*@termsize[0]}[/color]" + "[home #{@termsize[1]-1},1][clearline][color Magenta](#{name})[#{@mode}][/color]" + "[home #{@termsize[1]},1][clearline]> ") else # publish("> ") end end
# File lib/core/account.rb, line 331 def sendmsg(msg) publish("[cursave][home #{@termsize[1]-3},1]") if vtsupport? publish(msg) publish("[currest]") if vtsupport? prompt end
# File lib/core/account.rb, line 355 def status_rept str = "Terminal: #{@terminal}\n" str << "Terminal size: #{@termsize[0]} X #{@termsize[1]}\n" str << "Colors toggled #{@color ? '[COLOR Magenta]ON[/COLOR]' : 'OFF' }\n" str << "Echo is #{@echo ? 'ON' : 'OFF' }\n" str << "ZMP is #{@conn.query(:zmp) ? 'ON' : 'OFF' }\n" end
# File lib/core/account.rb, line 363 def toggle_color color ? self.color = false : self.color = true @conn.set(:color,color) "Colors toggled #{color ? '[COLOR Magenta]ON[/COLOR]' : 'OFF' }\n" end
Receives messages from a Connection being observed and handles login state.
msg
The message string
This supports the following:
This symbol from the server informs us that the
Connection has disconnected.
This symbol from the server indicates that the Connection is done setting up and done negotiating an initial state. It triggers us to start sending output and parsing input.
This is sent everytime the terminal size changes (NAWS)
# File lib/core/account.rb, line 62 def update(msg) case msg # Handle disconnection from server # Note that publishing a :quit event (see #disconnect) will return a # :disconnected event when server has closed the connection. # Guest accounts and characters are deleted here. when :disconnected @conn = nil unsubscribe_all Engine.instance.db.makeswap(id) if @character world.connected_characters.delete(@character.id) world.connected_characters.each do |pid| add_event(@character.id,pid,:show,"#{name} has disconnected.") end Engine.instance.db.makeswap(@character.id) @character.account = nil if @character.name =~ %rGuest/ world.all_characters.delete(@character.id) delete_object(@character.id) end @character = nil end if name =~ %rGuest/ world.all_accounts.delete(id) delete_object(id) end # Issued when a NAWS event occurs # Currently this clears and resets the screen. Ideally it should attempt # to redraw it. when :termsize @termsize = @conn.query(:termsize) if vtsupport? publish("[home #{@termsize[1]},1][clearline][cursave]" + "[home 1,1][scrreset][clear][scrreg 1,#{@termsize[1]-3}][currest]") end # Negotiation with client done. Start talking to it. when :initdone @echo = @conn.query(:echo) @termsize = @conn.query(:termsize) @terminal = @conn.query(:terminal) if vtsupport? publish("[home #{@termsize[1]},1][clearline][cursave]" + "[home 1,1][scrreset][clear][scrreg 1,#{@termsize[1]-3}][currest]") sendmsg(LOGO) end sendmsg(BANNER) sendmsg(append_echo("login> ")) @mode = :name # This is a message from our user when String parse_messages(msg) else log.error "Account#update unknown message - #{msg.inspect}" end rescue # We squash and print out all exceptions here. There is no reason to # throw these back at the Connection. log.error $! end
# File lib/core/account.rb, line 391 def vtsupport? @terminal =~ %r^vt|xterm/ end