teeworlds_network/lib/game_client.rb

138 lines
2.8 KiB
Ruby

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: player,
chunk: 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: chunk,
client_id: client_id,
reason: reason == '' ? nil : reason,
silent: 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: 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)
if @client.hooks[:chat]
@client.hooks[:chat].call(msg)
end
end
end