vimtronner
Version:
A multi-player Vim trainer.
119 lines (97 loc) • 3.26 kB
text/coffeescript
socketio = require('socket.io-client')
require '../define_property'
screen = require './screen'
GameView = require './views/game_view'
GameListView = require './views/game_list_view'
class Client
constructor: (@address="127.0.0.1", @port=8000)->
@errorMessages = []
@property 'url', get: -> "http://#{@address}:#{@port}"
join: (@gameAttributes)->
@gameAttributes.width ?= screen.columns
@gameAttributes.height ?= screen.rows - 2
@checkValidity()
@gameView = gameView = new GameView
@connect(@andJoinGame)
checkValidity: ->
errorChecks = {
"Width cannot be smaller than 80": =>
@gameAttributes.width < 80
"Width cannot be greater than screen size": =>
@gameAttributes.width > screen.columns
"Height cannot be smaller than 22": =>
@gameAttributes.width < 22
"Height cannot be greater than screen size": =>
@gameAttributes.height > screen.rows - 2
"Number of players must be between 1 to 6": =>
@gameAttributes.numberOfPlayers < 1 or
@gameAttributes.numberOfPlayers > 6
}
errors = (message for message, check of errorChecks when check())
(throw new Error(
"""
The game parameters are invalid:
#{errors.join '\n'}
"""
)) if errors.length > 0
listGames: ->
@connect(@andListGames)
connect: (callback)->
@socket = socketio.connect(@url)
@socket.on 'connect', callback
@socket.on 'connect_error', @connectError
@socket.on 'connect_timeout', @connectError
@socket.on 'error', @connectError
@socket.on 'connecting', =>
process.stdout.write "Connecting to #{@url} ...\n"
connectError: =>
process.stdout.write "Failed to connect to #{@url}\n"
process.exit 1
andJoinGame: =>
process.on 'SIGINT', @onSigInt
process.stdin.setRawMode true
process.stdin.resume()
process.stdin.on 'data', @onData
@socket.emit 'join', @gameAttributes, (error, cycleNumber, game) =>
return @showErrorMessage(error.message) if error?
@cycleNumber = cycleNumber
@onGameUpdate(game)
@socket.on 'game', @onGameUpdate
@socket.on 'disconnect', @quit
onData: (chunk)=>
switch chunk[0]
when 113
@quit()
screen.clear()
else
@socket.emit 'movement', chunk[0]
quit: ->
process.kill process.pid, 'SIGINT'
onSigInt: =>
screen.resetAll()
screen.showCursor()
screen.clear()
if @errorMessages.length > 0
process.stdout.write '\nERROR MESSAGES'
process.stdout.write '\n--------------'
process.stdout.write("\n#{message}") for message in @errorMessages
process.stdout.write '\n--------------\n\n'
process.stdout.write 'End of line.\n'
process.nextTick process.exit
onGameUpdate: (game)=>
@gameView.game = game
@gameView.cycleNumber = @cycleNumber
@gameView.render()
andListGames: =>
@gameListView = new GameListView
@socket.on 'games', @onGames
@socket.emit 'list'
onGames: (games)=>
@gameListView.addGames(games)
@gameListView.render()
@socket.disconnect()
showErrorMessage: (message) =>
@errorMessages.push message
@quit()
storeCycle: (cycle)=> @cycle = cycle
module.exports = Client