teeworlds_network/lib/game_client.rb

185 lines
3.7 KiB
Ruby
Raw Normal View History

2022-11-05 16:48:47 +00:00
# frozen_string_literal: true
2022-11-04 15:26:24 +00:00
require_relative 'player'
require_relative 'packer'
require_relative 'chat_message'
class Context
2022-11-05 10:07:16 +00:00
attr_reader :old_data, :client
attr_accessor :data
2022-11-05 10:07:16 +00:00
def initialize(client, keys = {})
@client = client
@cancle = false
@old_data = keys
@data = keys
end
def verify
2022-11-05 16:19:05 +00:00
@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
2022-11-04 15:26:24 +00:00
class GameClient
attr_accessor :players, :pred_game_tick, :ack_game_tick
2022-11-04 15:26:24 +00:00
def initialize(client)
@client = client
@players = {}
@ack_game_tick = -1
@pred_game_tick = 0
2022-11-04 15:26:24 +00:00
end
def on_client_info(chunk)
2022-11-04 15:26:24 +00:00
# puts "Got playerinfo flags: #{chunk.flags}"
u = Unpacker.new(chunk.data[1..])
player = Player.new(
2022-11-05 16:19:05 +00:00
id: u.get_int,
local: u.get_int,
team: u.get_int,
name: u.get_string,
clan: u.get_string,
country: u.get_int
)
2022-11-04 15:26:24 +00:00
# skinparts and the silent flag
# are currently ignored
context = Context.new(
2022-11-05 10:07:16 +00:00
@client,
2022-11-05 16:19:05 +00:00
player:,
chunk:
)
if @client.hooks[:client_info]
@client.hooks[:client_info].call(context)
context.verify
return if context.cancled?
end
player = context.data[:player]
2022-11-04 15:26:24 +00:00
@players[player.id] = player
2022-11-05 10:59:36 +00:00
end
def on_client_drop(chunk)
u = Unpacker.new(chunk.data[1..])
2022-11-05 16:19:05 +00:00
client_id = u.get_int
reason = u.get_string
silent = u.get_int
2022-11-05 10:59:36 +00:00
context = Context.new(
@cliemt,
player: @players[client_id],
2022-11-05 16:19:05 +00:00
chunk:,
client_id:,
2022-11-05 10:59:36 +00:00
reason: reason == '' ? nil : reason,
silent: silent != 0
2022-11-05 10:59:36 +00:00
)
if @client.hooks[:client_drop]
@client.hooks[:client_drop].call(context)
context.verify
return if context.cancled?
end
@players.delete(context.data[:client_id])
2022-11-04 15:26:24 +00:00
end
2022-11-05 16:19:05 +00:00
def on_ready_to_enter(_chunk)
@client.send_enter_game
end
def on_connected
2022-11-05 10:07:16 +00:00
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
2022-11-06 17:26:14 +00:00
def on_rcon_line(chunk)
u = Unpacker.new(chunk.data[1..])
context = Context.new(
@client,
line: u.get_string
)
@client.hooks[:rcon_line]&.call(context)
end
def on_snapshot(chunk)
u = Unpacker.new(chunk.data)
u.get_int
# msg = u.get_int
# msg >>= 1
# num_parts = 1
# part = 0
game_tick = u.get_int
# delta_tick = u.get_int
# part_size = 0
# crc = 0
# complete_size = 0
# data = nil
# TODO: state check
# if msg == NETMSG_SNAP
# num_parts = u.get_int
# part = u.get_int
# end
# unless msg == NETMSG_SNAPEMPTY
# crc = u.get_int
# part_size = u.get_int
# end
# TODO: add get_raw(size)
# data = u.get_raw
# ack every snapshot no matter how broken
@ack_game_tick = game_tick
return unless (@pred_game_tick - @ack_game_tick).abs > 10
@pred_game_tick = @ack_game_tick + 1
end
2022-11-05 16:19:05 +00:00
def on_emoticon(chunk); end
def on_map_change(chunk)
2022-11-05 16:19:05 +00:00
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
2022-11-04 15:26:24 +00:00
def on_chat(chunk)
u = Unpacker.new(chunk.data[1..])
data = {
2022-11-05 16:19:05 +00:00
mode: u.get_int,
client_id: u.get_int,
target_id: u.get_int,
message: u.get_string
2022-11-04 15:26:24 +00:00
}
data[:author] = @players[data[:client_id]]
msg = ChatMesage.new(data)
2022-11-05 16:48:47 +00:00
@client.hooks[:chat]&.call(msg)
2022-11-04 15:26:24 +00:00
end
end