# encoding: UTF-8 require 'socket' require_relative 'board' require_relative 'move' require_relative 'player' require_relative 'network' require_relative 'connection' require_relative 'client_interface' require 'rexml/document' require 'rexml/streamlistener' # @author Ralf-Tobias Diekert # This class handles the parsing of xml strings according to the network protocol of twixt class Protocol include REXML::StreamListener # @!attribute [r] gamestate # @return [Gamestate] current gamestate attr_reader :gamestate # @!attribute [rw] roomID # @return [String] current room id attr_accessor :roomID # @!attribute [r] client # @return [ClientInterface] current client attr_reader :client @network def initialize(network, client) @gamestate = GameState.new @network, @client = network, client self.client.gamestate = self.gamestate end # starts xml-string parsing # # @param text [String] the xml-string that will be parsed def processString(text) list = self #puts "Parse XML:\n#{text}\n----END XML" REXML::Document.parse_stream(text, list) end # called if an end-tag is read # # @param name [String] the end-tag name, that was read def tag_end(name) case name when "board" puts @gamestate.board.to_s when "condition" puts "Game ended" @network.disconnect end end # called if a start tag is read # Depending on the tag the gamestate is updated # or the client will be asked for a move # # @param name [String] the start-tag, that was read # @param attrs [Dictionary<String, String>] Attributes attached to the tag def tag_start(name, attrs) case name when "room" @roomID = attrs['roomId'] puts "roomId : "+@roomID when "data" puts "data(class) : "+attrs['class'] if attrs['class'] == "sc.framework.plugins.protocol.MoveRequest" @client.gamestate = self.gamestate move = @client.getMove document = REXML::Document.new document.add_element('room',{'roomId' => @roomID}) data = REXML::Element.new('data') data.add_attribute('class', 'move') data.add_attribute('x', move.x) data.add_attribute('y', move.y) document.root.add_element(data) for h in move.hints hint = REXML::Element.new('hint') hint.add_attribute('content', h.content) document.root.elements['data'].elements << hint end self.sendXml(document) end if attrs['class'] == "error" puts "Game ended - ERROR" puts attrs['message'] @network.disconnect end when "state" puts 'new gamestate' @gamestate.turn = attrs['turn'].to_i @gamestate.startPlayerColor = attrs['startPlayer'] == 'RED' ? PlayerColor::RED : PlayerColor::BLUE @gamestate.currentPlayerColor = attrs['currentPlayer'] == 'RED' ? PlayerColor::RED : PlayerColor::BLUE puts "Turn: #{@gamestate.turn}" when "red" puts 'new red player' @gamestate.addPlayer(Player.new(attrs['color'] == 'RED' ? PlayerColor::RED : PlayerColor::BLUE)) @gamestate.red.points = attrs['points'].to_i when "blue" puts 'new blue player' @gamestate.addPlayer(Player.new(attrs['color'] == 'RED' ? PlayerColor::RED : PlayerColor::BLUE)) @gamestate.blue.points = attrs['points'].to_i when "board" puts 'new board' @gamestate.board = Board.new(true) when "field" type = FieldType::NORMAL ownerColor = PlayerColor::NONE case attrs['type'] when 'SWAMP' type = FieldType::SWAMP when 'RED' type = FieldType::RED when 'BLUE' type = FieldType::BLUE when "winner" puts "Game ended" @network.disconnect end case attrs['owner'] when 'RED' ownerColor = PlayerColor::RED when 'BLUE' ownerColor = PlayerColor::BLUE end x = attrs['x'].to_i y = attrs['y'].to_i @gamestate.board.fields[x][y] = Field.new(type, x, y) @gamestate.board.fields[x][y].ownerColor = ownerColor when "connection" @gamestate.board.connections.push(Connection.new(attrs['x1'].to_i, attrs['y1'].to_i, attrs['x2'].to_i, attrs['y2'].to_i, attrs['owner'])) when "lastMove" @gamestate.lastMove = Move.new(attrs['x'], attrs['y']) when "condition" @gamestate.condition = Condition.new(attrs['winner'], attrs['reason']) end end # send a xml document # # @param document [REXML::Document] the document, that will be send to the connected server def sendXml(document) @network.sendXML(document) end end