require_relative 'player' require_relative 'packer' require_relative 'chat_message' class Context attr_reader :old_data, :client attr_accessor :data def initialize(client, keys = {}) @client = client @cancle = false @old_data = keys @data = keys end def verify @data.each do |key, _value| next if @old_data.key? key raise "Error: invalid data key '#{key}'\n valid keys: #{@old_data.keys}" end end def cancled? @cancle end def cancle @cancle = true end end class GameClient attr_accessor :players def initialize(client) @client = client @players = {} end def on_client_info(chunk) # puts "Got playerinfo flags: #{chunk.flags}" u = Unpacker.new(chunk.data[1..]) player = Player.new( id: u.get_int, local: u.get_int, team: u.get_int, name: u.get_string, clan: u.get_string, country: u.get_int ) # skinparts and the silent flag # are currently ignored context = Context.new( @client, player:, chunk: ) if @client.hooks[:client_info] @client.hooks[:client_info].call(context) context.verify return if context.cancled? end player = context.data[:player] @players[player.id] = player end def on_client_drop(chunk) u = Unpacker.new(chunk.data[1..]) client_id = u.get_int reason = u.get_string silent = u.get_int context = Context.new( @cliemt, player: @players[client_id], chunk:, client_id:, reason: reason == '' ? nil : reason, silent: ) if @client.hooks[:client_drop] @client.hooks[:client_drop].call(context) context.verify return if context.cancled? end @players.delete(context.data[:client_id]) end def on_ready_to_enter(_chunk) @client.send_enter_game end def on_connected context = Context.new(@client) if @client.hooks[:connected] @client.hooks[:connected].call(context) context.verify return if context.cancled? end @client.send_msg_startinfo end def on_emoticon(chunk); end def on_map_change(chunk) context = Context.new(@client, chunk:) if @client.hooks[:map_change] @client.hooks[:map_change].call(context) context.verify return if context.cancled? end # ignore mapdownload at all times # and claim to have the map @client.send_msg_ready end def on_chat(chunk) u = Unpacker.new(chunk.data[1..]) data = { mode: u.get_int, client_id: u.get_int, target_id: u.get_int, message: u.get_string } data[:author] = @players[data[:client_id]] msg = ChatMesage.new(data) @client.hooks[:chat].call(msg) if @client.hooks[:chat] end end