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
|
||||
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
|
||||
|
||||
def initialize(data)
|
||||
@next = nil
|
||||
@flags = {}
|
||||
@seq = 0
|
||||
@size = 0
|
||||
parse_header(data[0..2])
|
||||
header_size = if flags_vital
|
||||
|
@ -135,8 +136,12 @@ class NetChunk
|
|||
size_bytes.map! { |b| b[2..].join }
|
||||
@size = size_bytes.join.to_i(2)
|
||||
|
||||
# sequence number
|
||||
# in da third byte but who needs seq?!
|
||||
if @flags[:vital]
|
||||
data = data[0..2].bytes
|
||||
@seq = (data[1] & (0xC0 << 2)) | data[2]
|
||||
else
|
||||
@seq = 0
|
||||
end
|
||||
end
|
||||
|
||||
# @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 'game_client'
|
||||
require_relative 'config'
|
||||
require_relative 'connection'
|
||||
|
||||
class TeeworldsClient
|
||||
attr_reader :state, :hooks, :game_client, :verbose_snap
|
||||
|
@ -445,9 +446,19 @@ class TeeworldsClient
|
|||
end
|
||||
chunks = BigChungusTheChunkGetter.get_chunks(data)
|
||||
chunks.each do |chunk|
|
||||
if chunk.flags_vital && !chunk.flags_resend && chunk.msg != NETMSG_NULL
|
||||
@netbase.ack = (@netbase.ack + 1) % NET_MAX_SEQUENCE
|
||||
puts "got ack: #{@netbase.ack}" if @verbose
|
||||
if chunk.flags_vital
|
||||
if chunk.seq == (@netbase.ack + 1) % NET_MAX_SEQUENCE
|
||||
# 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
|
||||
process_chunk(chunk)
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue