Drop known chunks. Fixes duplicated chat messages.
This commit is contained in:
parent
deb679d1d0
commit
af7367be0c
11
lib/chunk.rb
11
lib/chunk.rb
|
@ -13,13 +13,14 @@ require_relative 'bytes'
|
||||||
#
|
#
|
||||||
# https://chillerdragon.github.io/teeworlds-protocol/07/packet_layout.html
|
# https://chillerdragon.github.io/teeworlds-protocol/07/packet_layout.html
|
||||||
class NetChunk
|
class NetChunk
|
||||||
attr_reader :next, :data, :msg, :sys, :flags, :header_raw, :full_raw
|
attr_reader :next, :data, :msg, :sys, :flags, :seq, :header_raw, :full_raw
|
||||||
|
|
||||||
@@sent_vital_chunks = 0
|
@@sent_vital_chunks = 0
|
||||||
|
|
||||||
def initialize(data)
|
def initialize(data)
|
||||||
@next = nil
|
@next = nil
|
||||||
@flags = {}
|
@flags = {}
|
||||||
|
@seq = 0
|
||||||
@size = 0
|
@size = 0
|
||||||
parse_header(data[0..2])
|
parse_header(data[0..2])
|
||||||
header_size = if flags_vital
|
header_size = if flags_vital
|
||||||
|
@ -135,8 +136,12 @@ class NetChunk
|
||||||
size_bytes.map! { |b| b[2..].join }
|
size_bytes.map! { |b| b[2..].join }
|
||||||
@size = size_bytes.join.to_i(2)
|
@size = size_bytes.join.to_i(2)
|
||||||
|
|
||||||
# sequence number
|
if @flags[:vital]
|
||||||
# in da third byte but who needs seq?!
|
data = data[0..2].bytes
|
||||||
|
@seq = (data[1] & (0xC0 << 2)) | data[2]
|
||||||
|
else
|
||||||
|
@seq = 0
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# @return [Boolean]
|
# @return [Boolean]
|
||||||
|
|
20
lib/connection.rb
Normal file
20
lib/connection.rb
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
##
|
||||||
|
# Only used for chunks where the sequence number does not match the expected value
|
||||||
|
# to decide wether to drop known chunks silently or request resend if something got lost
|
||||||
|
#
|
||||||
|
# true - if the sequence number is already known and the chunk should be dropped
|
||||||
|
# false - if the sequence number is off and we need to request a resend of lost chunks
|
||||||
|
#
|
||||||
|
# @return [Boolean]
|
||||||
|
def seq_in_backroom?(seq, ack)
|
||||||
|
bottom = ack - (NET_MAX_SEQUENCE / 2)
|
||||||
|
if bottom.negative?
|
||||||
|
return true if seq <= ack
|
||||||
|
return true if seq >= (bottom + NET_MAX_SEQUENCE)
|
||||||
|
elsif seq <= ack && seq >= bottom
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
false
|
||||||
|
end
|
|
@ -14,6 +14,7 @@ require_relative 'packer'
|
||||||
require_relative 'models/player'
|
require_relative 'models/player'
|
||||||
require_relative 'game_client'
|
require_relative 'game_client'
|
||||||
require_relative 'config'
|
require_relative 'config'
|
||||||
|
require_relative 'connection'
|
||||||
|
|
||||||
class TeeworldsClient
|
class TeeworldsClient
|
||||||
attr_reader :state, :hooks, :game_client, :verbose_snap
|
attr_reader :state, :hooks, :game_client, :verbose_snap
|
||||||
|
@ -445,9 +446,19 @@ class TeeworldsClient
|
||||||
end
|
end
|
||||||
chunks = BigChungusTheChunkGetter.get_chunks(data)
|
chunks = BigChungusTheChunkGetter.get_chunks(data)
|
||||||
chunks.each do |chunk|
|
chunks.each do |chunk|
|
||||||
if chunk.flags_vital && !chunk.flags_resend && chunk.msg != NETMSG_NULL
|
if chunk.flags_vital
|
||||||
@netbase.ack = (@netbase.ack + 1) % NET_MAX_SEQUENCE
|
if chunk.seq == (@netbase.ack + 1) % NET_MAX_SEQUENCE
|
||||||
puts "got ack: #{@netbase.ack}" if @verbose
|
# in sequence
|
||||||
|
@netbase.ack = (@netbase.ack + 1) % NET_MAX_SEQUENCE
|
||||||
|
else
|
||||||
|
puts "warning: got chunk out of sequence! seq=#{chunk.seq} expected_seq=#{(@netbase.ack + 1) % NET_MAX_SEQUENCE}"
|
||||||
|
if seq_in_backroom?(chunk.seq, @netbase.ack)
|
||||||
|
puts ' dropping known chunk ...'
|
||||||
|
next
|
||||||
|
end
|
||||||
|
# TODO: request resend
|
||||||
|
puts ' REQUESTING RESEND NOT IMPLEMENTED'
|
||||||
|
end
|
||||||
end
|
end
|
||||||
process_chunk(chunk)
|
process_chunk(chunk)
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue