138 lines
2.8 KiB
Ruby
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
|
|
|