diff --git a/lib/chunk.rb b/lib/chunk.rb index 9fb2483..12f957a 100644 --- a/lib/chunk.rb +++ b/lib/chunk.rb @@ -58,13 +58,20 @@ class NetChunk # # It will create a 3 byte chunk header # represented as an Array of 3 integers - def self.create_header(opts = { resend: false, vital: false, size: nil, seq: nil }) + def self.create_header(opts = { resend: false, vital: false, size: nil, seq: nil, client: nil }) raise 'Chunk.create_header :size option can not be nil' if opts[:size].nil? return _create_non_vital_header(opts) unless opts[:vital] + # client only counts this class var @@sent_vital_chunks += 1 seq = opts[:seq].nil? ? @@sent_vital_chunks : opts[:seq] + # server counts per client + unless opts[:client].nil? + opts[:client].vital_sent += 1 + seq = opts[:client].vital_sent + end + flag_bits = '00'.dup flag_bits[0] = opts[:resend] ? '1' : '0' flag_bits[1] = opts[:vital] ? '1' : '0' diff --git a/lib/game_server.rb b/lib/game_server.rb index fa8ac03..57d85cd 100644 --- a/lib/game_server.rb +++ b/lib/game_server.rb @@ -28,7 +28,7 @@ class GameServer # TODO: check version and password - @server.send_map(packet.addr) + @server.send_map(packet.client) end def on_ready(_chunk, packet) @@ -38,7 +38,7 @@ class GameServer # - ready # # We only send ready for now - @server.send_ready(packet.addr) + @server.send_ready(packet.client) end def on_startinfo(_chunk, packet) @@ -48,7 +48,7 @@ class GameServer # - ready to enter # # We only send ready to enter for now - @server.send_ready_to_enter(packet.addr) + @server.send_ready_to_enter(packet.client) end def on_enter_game(_chunk, packet) @@ -59,7 +59,7 @@ class GameServer # - game info # - client info # - snap single - @server.send_server_info(packet.addr, ServerInfo.new.to_a) - @server.send_game_info(packet.addr, GameInfo.new.to_a) + @server.send_server_info(packet.client, ServerInfo.new.to_a) + @server.send_game_info(packet.client, GameInfo.new.to_a) end end diff --git a/lib/packet.rb b/lib/packet.rb index 1e8a4bf..227fd72 100644 --- a/lib/packet.rb +++ b/lib/packet.rb @@ -8,7 +8,7 @@ require 'huffman_tw' # Class holding the parsed packet data class Packet attr_reader :flags, :payload, :addr - attr_accessor :client_id + attr_accessor :client_id, :client def initialize(data, prefix = '') # @data and @payload @@ -22,6 +22,7 @@ class Packet @addr = NetAddr.new(nil, nil) @huffman = Huffman.new @client_id = nil + @client = nil @data = data flags_byte = @data[0].unpack('B*') @flags = PacketFlags.new(flags_byte.first[2..5]).hash diff --git a/lib/teeworlds_server.rb b/lib/teeworlds_server.rb index 639fe74..083827a 100644 --- a/lib/teeworlds_server.rb +++ b/lib/teeworlds_server.rb @@ -15,11 +15,12 @@ require_relative 'game_server' require_relative 'message' class Client - attr_accessor :id, :addr + attr_accessor :id, :addr, :vital_sent def initialize(attr = {}) @id = attr[:id] @addr = attr[:addr] + @vital_sent = 0 end end @@ -125,7 +126,7 @@ class TeeworldsServer # @netbase.peer_token = @server_token end - def send_map(addr) + def send_map(client) data = [] data += Packer.pack_str(@game_server.map.name) data += @game_server.map.crc_arr # poor mans pack_raw() @@ -133,36 +134,36 @@ class TeeworldsServer data += Packer.pack_int(8) # chunk num? data += Packer.pack_int(MAP_CHUNK_SIZE) data += @game_server.map.sha256_arr # poor mans pack_raw() - msg = NetChunk.create_header(vital: true, size: data.size + 1) + + msg = NetChunk.create_header(vital: true, size: data.size + 1, client:) + [pack_msg_id(NETMSG_MAP_CHANGE, system: true)] + data - @netbase.send_packet(msg, 1, addr:) + @netbase.send_packet(msg, 1, addr: client.addr) end - def send_ready(addr) - msg = NetChunk.create_header(vital: true, size: 1) + + def send_ready(client) + msg = NetChunk.create_header(vital: true, size: 1, client:) + [pack_msg_id(NETMSG_CON_READY, system: true)] - @netbase.send_packet(msg, 1, addr:) + @netbase.send_packet(msg, 1, addr: client.addr) end - def send_ready_to_enter(addr) - msg = NetChunk.create_header(vital: true, size: 1) + + def send_ready_to_enter(client) + msg = NetChunk.create_header(vital: true, size: 1, client:) + [pack_msg_id(NETMSGTYPE_SV_READYTOENTER, system: false)] - @netbase.send_packet(msg, 1, addr:) + @netbase.send_packet(msg, 1, addr: client.addr) end - def send_server_info(addr, server_info) - msg = NetChunk.create_header(vital: true, size: 1 + server_info.size) + + def send_server_info(client, server_info) + msg = NetChunk.create_header(vital: true, size: 1 + server_info.size, client:) + [pack_msg_id(NETMSG_SERVERINFO, system: true)] + server_info - @netbase.send_packet(msg, 1, addr:) + @netbase.send_packet(msg, 1, addr: client.addr) end - def send_game_info(addr, data) - msg = NetChunk.create_header(vital: true, size: 1 + data.size) + + def send_game_info(client, data) + msg = NetChunk.create_header(vital: true, size: 1 + data.size, client:) + [pack_msg_id(NETMSGTYPE_SV_GAMEINFO, system: false)] + data - @netbase.send_packet(msg, 1, addr:) + @netbase.send_packet(msg, 1, addr: client.addr) end def on_ctrl_token(packet) @@ -257,6 +258,7 @@ class TeeworldsServer next unless packet.addr.eq(client.addr) packet.client_id = id + packet.client = client end puts packet.to_s if @verbose diff --git a/scripts/bad_code.sh b/scripts/bad_code.sh index 8d28daf..5073802 100755 --- a/scripts/bad_code.sh +++ b/scripts/bad_code.sh @@ -53,6 +53,7 @@ function check_chunk_header_args() { local method_args local needed_args local needed_arg + local needed_srv local code needed_args=(vital: size:) while read -r header_line @@ -60,7 +61,14 @@ function check_chunk_header_args() { line="$(echo "$header_line" | cut -d':' -f1-2)" code="$(echo "$header_line" | cut -d':' -f3-)" method_args="$(echo "$header_line" | cut -d'(' -f2-)" - for needed_arg in "${needed_args[@]}" + unset needed_srv + # vital chunk headers sent by the server + # need a client: to get the sequence number + if [[ "$line" =~ server ]] && [[ "$method_args" =~ 'vital: true' ]] + then + needed_srv='client:' + fi + for needed_arg in "${needed_args[@]}" $needed_srv do if ! echo "$method_args" | grep -q "$needed_arg" then